diff --git a/bin/uce_fastcgi.debug.linux.bin b/bin/uce_fastcgi.debug.linux.bin index b505e38..e106942 100755 Binary files a/bin/uce_fastcgi.debug.linux.bin and b/bin/uce_fastcgi.debug.linux.bin differ diff --git a/build_linux.sh b/build_linux.sh index 1557ca1..5ebb078 100755 --- a/build_linux.sh +++ b/build_linux.sh @@ -18,7 +18,7 @@ mkdir work > /dev/null 2>&1 COMPILER="clang++" FLAGS="-g -rdynamic -w -Wall -$OPT_FLAG -std=c++17 -fpermissive -ffast-math" -LIBS="-ldl -lm -lpthread " +LIBS="-ldl -lm -lpthread `mysql_config --cflags --libs`" SRCFLAGS="-D EXEC_NAME=\"$GF\" -D PLATFORM_NAME=\"linux\"" echo "Compliling executable..." diff --git a/src/lib/mysql-connector.cpp b/src/lib/mysql-connector.cpp new file mode 100644 index 0000000..6bfba59 --- /dev/null +++ b/src/lib/mysql-connector.cpp @@ -0,0 +1,197 @@ +#include +#include +#include + +bool MySQL::connect(string host, string username, string password) +{ + connection = mysql_init(NULL); + if (connection == NULL) + { + fprintf(stderr, "%s\n", mysql_error((MYSQL*)connection)); + return(false); + } + + if (mysql_real_connect((MYSQL*)connection, host.c_str(), username.c_str(), password.c_str(), + NULL, 0, NULL, 0) == NULL) + { + fprintf(stderr, "%s\n", mysql_error((MYSQL*)connection)); + mysql_close((MYSQL*)connection); + return(false); + } + + printf("(i) MySQL Connection established to %s\n", host.c_str()); + /* + if (mysql_query(con, "CREATE DATABASE testdb")) + { + fprintf(stderr, "%s\n", mysql_error(con)); + mysql_close(con); + exit(1); + } + */ + context->resources.mysql_connections.push_back(connection); + return(true); +} + +string MySQL::escape(string raw, char quote_char) +{ + string result; + result.append(1, quote_char); + + for(u32 i = 0; i < raw.length(); i++) + { + char c = raw[i]; + switch(c) + { + case('\n'): + result.append("\\n"); + break; + case('\r'): + result.append("\\r"); + break; + case('\t'): + result.append("\\t"); + break; + case('\\'): + case('\''): + case('"'): + result.append(1, '\\'); + result.append(1, c); + break; + default: + result.append(1, c); + break; + } + } + + result.append(1, quote_char); + return(result); +} + +/* static function ParseQueryParams($query, $parameters = null) + { + if ($parameters != null) + { + $pctr = 0; + $result = ''; + for($a = 0; $a < strlen($query); $a++) + { + $chr = substr($query, $a, 1); + if ($chr == '?') + { + $result .= '"'.DB::Safe($parameters[$pctr]).'"'; + $pctr++; + } + else if ($chr == '&') + { + $result .= ''.intval($parameters[$pctr]).''; + $pctr++; + } + else if ($chr == ':') + { + $paramName = ''; + $a += 1; + $pFormat = 'string'; + if($query[$a] == ':') + { + $pFormat = 'number'; + $a += 1; + } + while(!ctype_space($chr = substr($query, $a, 1)) && $a < strlen($query)) + { + $paramName .= $chr; + $a += 1; + } + if($pFormat == 'number') + $result .= ' '.($parameters[$paramName]+0).' '; + else + $result .= ' "'.DB::Safe($parameters[$paramName]).'" '; + } + else + $result .= $chr; + } + } + else + $result = $query; + $q = str_replace('#', cfg('db/prefix'), $result); + self::$lastQuery = $q; + return($q); + }*/ + + string MySQL::parse_query_parameters(string query, StringMap map) + { + string result; + query.append(1, ' '); + + u8 mode = 0; + char quote; + string identifier; + for(u32 i = 0; i < query.length(); i++) + { + char c = query[i]; + if(mode == 0) // normal, unquoted mode + { + if(c == ':') + { + mode = 1; + identifier = ""; + } + else if(c == '"' || c == '\'') + { + result.append(1, c); + mode = 2; + quote = c; + } + else + { + result.append(1, c); + } + } + else if(mode == 1) // identifier mode + { + if(isalnum(c)) + { + identifier.append(1, c); + } + else + { + result.append(escape(map[identifier])); + result.append(1, c); + mode = 0; + } + } + else if(mode == 2) // quoted mode + { + if(c == quote) + mode = 0; + result.append(1, c); + } + } + + return(result); + } + +void MySQL::disconnect() +{ + if(connection) + mysql_close((MYSQL*)connection); + connection = NULL; +} + +string MySQL::error() +{ + const char* res = mysql_error((MYSQL*)connection); + if(res) + { + return(string(res)); + } + else + { + return(""); + } +} + +void cleanup_mysql_connections() +{ + for(auto& con : context->resources.mysql_connections) + mysql_close((MYSQL*)con); +} diff --git a/src/lib/mysql-connector.h b/src/lib/mysql-connector.h new file mode 100644 index 0000000..c9910bd --- /dev/null +++ b/src/lib/mysql-connector.h @@ -0,0 +1,12 @@ + +struct MySQL { + + void* connection; + + bool connect(string host = "localhost", string username = "root", string password = ""); + void disconnect(); + string error(); + string escape(string raw, char quote_char = '\''); + string parse_query_parameters(string query, StringMap m); + +}; diff --git a/src/lib/types.h b/src/lib/types.h index 8e5ce02..8a28371 100644 --- a/src/lib/types.h +++ b/src/lib/types.h @@ -173,6 +173,7 @@ struct Request { struct Resources { std::vector sockets; + std::vector mysql_connections; } resources; void invoke(string file_name) diff --git a/src/lib/uce_gen.h b/src/lib/uce_gen.h index dd37a77..09b1986 100644 --- a/src/lib/uce_gen.h +++ b/src/lib/uce_gen.h @@ -4,4 +4,4 @@ #include "sys.h" #include "uri.h" #include "compiler.h" - +#include "mysql-connector.h" diff --git a/src/linux_fastcgi.cpp b/src/linux_fastcgi.cpp index 17d02be..35ca1aa 100644 --- a/src/linux_fastcgi.cpp +++ b/src/linux_fastcgi.cpp @@ -1,4 +1,5 @@ #include "lib/uce_gen.h" +#include "lib/mysql-connector.cpp" #include "fastcgi/src/fcgicc.cc" @@ -81,6 +82,8 @@ int handle_complete(FastCGIRequest& request) { if(request.session_id.length() > 0) save_session_data(request.session_id, request.session); + cleanup_mysql_connections(); + request.time_end = microtime(); printf("(r) %s\t%0.6fs\t%0.1fkB\n", request.params["REQUEST_URI"].c_str(), @@ -103,6 +106,8 @@ int main(int argc, char** argv) //if(server_state.config.COMPILER_SYS_PATH == "") server_state.config.COMPILER_SYS_PATH = get_cwd(); + printf("MySQL client version: %s\n", mysql_get_client_info()); + printf("Compiler base path: %s\n", server_state.config.COMPILER_SYS_PATH.c_str()); server_state.config.BIN_DIRECTORY = @@ -123,6 +128,14 @@ int main(int argc, char** argv) //server.process(100); //server.process(); + /*try + { + server.process_forever(); + } + catch (const std::runtime_error& e) + { + std::cout << e.what(); + }*/ server.process_forever(); return 0; diff --git a/start.sh b/start.sh new file mode 100755 index 0000000..585ecbc --- /dev/null +++ b/start.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +rm -r work/* ; ./build_linux.sh && bin/uce_fastcgi.debug.linux.bin diff --git a/test/index.uce b/test/index.uce index 9124c20..dac5750 100644 --- a/test/index.uce +++ b/test/index.uce @@ -20,6 +20,7 @@ RENDER()
  • DTree
  • JSON
  • Memcached
  • +
  • MySQL Connector
  • params) ?>
    diff --git a/test/mysql.uce b/test/mysql.uce new file mode 100644 index 0000000..82cc874 --- /dev/null +++ b/test/mysql.uce @@ -0,0 +1,36 @@ + + +RENDER() +{ + + + +

    + UCE Test: + MySQL Connector Test +

    + + +
    + + +
    params) ?>
    + + +} diff --git a/test/style.css b/test/style.css index e403301..033090f 100644 --- a/test/style.css +++ b/test/style.css @@ -20,6 +20,8 @@ body { max-width: 1024px; margin-left: auto; margin-right: auto; + padding-left: 16px; + padding-right: 16px; font-family: Tahoma, Helvetica, Arial; font-size: 1.2em; box-sizing: border-box;