int main(void) { URL_T url; char buf[BSIZE]; char *help = "Please enter a valid database connection URL and press ENTER\n" "E.g. sqlite:///tmp/sqlite.db?synchronous=off&heap_limit=2000\n" "E.g. mysql://localhost:3306/test?user=root&password=root\n" "E.g. postgresql://localhost:5432/test?user=root&password=root\n" "E.g. oracle://localhost:1526/test?user=scott&password=tiger\n" "To exit, enter '.' on a single line\n\nConnection URL> "; ZBDEBUG = true; Exception_init(); printf("============> Start Connection Pool Tests\n\n"); printf("This test will create and drop a table called zild_t in the database\n"); printf("%s", help); while (fgets(buf, BSIZE, stdin)) { if (*buf == '.') break; if (*buf == '\r' || *buf == '\n' || *buf == 0) goto next; url = URL_new(buf); if (! url) { printf("Please enter a valid database URL or stop by entering '.'\n"); goto next; } testPool(URL_toString(url)); URL_free(&url); printf("%s", help); continue; next: printf("Connection URL> "); } return 0; }
static T ctor(uchar_t *data) { T U; NEW(U); U->data = data; YYCURSOR = U->data; U->port = UNKNOWN_PORT; YYLIMIT = U->data + strlen(U->data); if (! parseURL(U)) URL_free(&U); return U; }
int URL_put_data_mysql ( const char *url_s, const PKI_MEM *data ) { int ret = 0; URL *url = NULL; // Parameter checking if( !url_s ) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return (PKI_ERR); } // Allocates a new URL structure if ((url = URL_new(url_s)) == NULL) { PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL); return PKI_ERR; } // Checks the protocol to by MySQL if (url->proto != URI_PROTO_MYSQL) { PKI_log_debug("Wrong protocol for MySQL queries (%d)", URI_PROTO_MYSQL); URL_free(url); return PKI_ERR; } // Gets the response ret = URL_put_data_mysql_url( url, data ); // Frees the URL data structure URL_free (url); return ret; }
PKI_X509_STACK *PKI_X509_STACK_get ( char *url_s, PKI_DATATYPE type, PKI_CRED *cred, HSM *hsm ) { URL *url = NULL; PKI_X509_STACK *ret = NULL; if( !url_s ) return (NULL); if((url = URL_new( url_s )) == NULL ) { return(NULL); } ret = PKI_X509_STACK_get_url ( url, type, cred, hsm ); if( url ) URL_free ( url ); return ( ret ); }
int PKI_X509_STACK_put (PKI_X509_STACK *sk, PKI_DATA_FORMAT format, char *url_string, const char *mime, PKI_CRED *cred, HSM *hsm) { URL *url = NULL; int ret = PKI_OK; if( !sk || !url_string ) return (PKI_ERR); if((url = URL_new (url_string)) == NULL ) { return (PKI_ERR); } ret = PKI_X509_STACK_put_url( sk, format, url, mime, cred, hsm ); if( url ) URL_free ( url ); return ( ret ); }
int main(void) { URL_T url = URL_new("sqlite:///tmp/test.db"); ConnectionPool_T pool = ConnectionPool_new(url); ConnectionPool_start(pool); Connection_T con = ConnectionPool_getConnection(pool); TRY { Connection_execute(con, "create table bleach(name varchar(255))"); PreparedStatement_T p = Connection_prepareStatement(con, "insert into bleach values (?)"); const char *bleach[] = { "Ichigo Kurosaki", "Rukia Kuchiki", "Orihime Inoue", "Yasutora \"Chad\" Sado", "Kisuke Urahara", "Uryū Ishida", "Renji Abarai", 0 }; for (int i = 0; bleach[i]; i++) { PreparedStatement_setString(p, 1, bleach[i]); PreparedStatement_execute(p); } ResultSet_T r = Connection_executeQuery(con, "select name from bleach"); while (ResultSet_next(r)) printf("%s\n", ResultSet_getString(r, 1)); Connection_execute(con, "drop table bleach;"); } CATCH(SQLException) { printf("SQLException -- %s\n", Exception_frame.message); } FINALLY { Connection_close(con); } END_TRY; ConnectionPool_free(&pool); URL_free(&url); return 0; }
int PKI_HTTP_GET_data (const char * url_s, int timeout, size_t max_size, PKI_MEM_STACK ** ret, PKI_SSL * ssl ) { URL *url = NULL; int rv = PKI_OK; if( !url_s ) return PKI_ERR; if((url = URL_new( url_s )) == NULL ) { return PKI_ERR; } rv = PKI_HTTP_get_url ( url, NULL, 0, NULL, PKI_HTTP_METHOD_GET, timeout, max_size, ret, ssl ); if ( url ) URL_free ( url ); return rv; }
int main(int argc, char *argv[]) { URL_T url = URL_new("mysql://127.0.0.1:3306/oauth2?user=dev&password=dev"); ConnectionPool_T pool = ConnectionPool_new(url); ConnectionPool_start(pool); Connection_T con = ConnectionPool_getConnection(pool); TRY { ResultSet_T result = Connection_executeQuery(con, "SELECT access_token, client_id, user_id, expires FROM oauth_access_tokens"); while (ResultSet_next(result)) { const char *access_token = ResultSet_getStringByName(result, "access_token"); printf("%s\t", access_token); const char *client_id = ResultSet_getStringByName(result, "client_id"); printf("%s\t", client_id); printf("\n"); } } CATCH(SQLException) { printf("SQLException -- %s\n", Exception_frame.message); } FINALLY { Connection_close(con); } END_TRY; ConnectionPool_free(&pool); URL_free(&url); return 0; }
PKI_CONFIG_STACK * PKI_CONFIG_load_dir ( char *dir, PKI_CONFIG_STACK *sk ) { struct dirent *dd = NULL; DIR *dirp = NULL; URL *url = NULL; int found = 0; PKI_CONFIG_STACK *ret = NULL; /* Check input */ if( !dir ) { return (NULL); } if(( url = URL_new ( dir )) == NULL ) { PKI_log_debug( "Dir not valid for config (%s)", dir ); return ( NULL ); } if( url->proto != URI_PROTO_FILE ) { PKI_log_debug( "Dir not valid for config (%s)", dir ); return (NULL); } if((dirp = opendir( url->addr )) == NULL ) { PKI_log_debug("ERROR, Can not open dir %s!\n", url->addr ); return (NULL); } else { if( !sk ) { if((ret = PKI_STACK_CONFIG_new()) == NULL ) { PKI_log_debug("Memory Error (%s:%d)", __FILE__, __LINE__ ); return(NULL); } } else { ret = sk; } while(( dd = readdir( dirp )) != NULL ) { long len; char *filename = NULL; filename = dd->d_name; len = (long) strlen( filename ); if( (len < 4) || (strcmp( ".xml", filename +len -4 ))) { PKI_log_debug( "Skipping file %s", filename); continue; } else { char fullpath[BUFF_MAX_SIZE]; size_t fullsize = 0; PKI_CONFIG *tmp_cfg = NULL; PKI_log_debug( "Loading file %s" LIBPKI_PATH_SEPARATOR "%s", url->addr, filename ); snprintf(fullpath, BUFF_MAX_SIZE, "%s" LIBPKI_PATH_SEPARATOR "%s", url->addr, filename ); if((fullsize = strlen(url->addr) + strlen( filename ) + 1) > BUFF_MAX_SIZE) { continue; } if((tmp_cfg = PKI_CONFIG_load( fullpath )) == NULL ) { continue; } PKI_log_debug( "Loaded %s file", fullpath ); PKI_STACK_CONFIG_push( ret, tmp_cfg ); found = 1; } } closedir( dirp ); } if( url ) URL_free (url); if( found == 1 ) { return (ret); } else { PKI_STACK_CONFIG_free( ret ); PKI_log_debug("PKI_CONFIG_load_dir() Failed!\n" ); return ( NULL ); } }
char * PKI_CONFIG_find ( char *dir, char *name ) { struct dirent *dd = NULL; DIR *dirp = NULL; URL *url = NULL; int found = 0; char *ret = NULL; /* Check input */ if( !dir || !name ) { PKI_ERROR(PKI_ERR_PARAM_NULL, NULL); return (PKI_ERR); } if ((url = URL_new(dir)) == NULL) { PKI_log_debug("Dir [%s] is not a valid URI", dir ); return (PKI_ERR); } if (url->proto != URI_PROTO_FILE) { PKI_log_debug("URL is not a file, skipping!", dir ); return (PKI_ERR); } if ((dirp = opendir(url->addr)) == NULL) { PKI_log_debug("Can not open directory [%s]", url->addr ); return (PKI_ERR); } else { while(( dd = readdir( dirp )) != NULL ) { long len; char *filename = NULL; filename = dd->d_name; len = (long) strlen( filename ); PKI_log_debug("Processing file [%s]", filename ); if (len < 4 || strcmp(".xml", filename +len-4) != 0) { PKI_log_debug("Skipping %s", filename ); continue; } else { char fullpath[BUFF_MAX_SIZE]; size_t fullsize = 0; PKI_CONFIG *tmp_cfg = NULL; char *tmp_name = NULL; snprintf(fullpath, BUFF_MAX_SIZE, "%s/%s", url->addr, filename ); PKI_log_debug("Opening File %s", fullpath ); // Check the allowed size fullsize = strlen(url->addr) + strlen( filename ) + 1; if (fullsize > BUFF_MAX_SIZE) continue; if ((tmp_cfg = PKI_CONFIG_load(fullpath)) == NULL) { PKI_log_debug("Can not load %s", fullpath ); continue; } PKI_log_debug("Getting Name Param... "); tmp_name = PKI_CONFIG_get_value(tmp_cfg, "/*/name"); PKI_CONFIG_free(tmp_cfg); if (tmp_name != NULL) { PKI_log_debug("Got Name::%s", tmp_name); if (strcmp_nocase(tmp_name, name) == 0) { PKI_Free(tmp_name); tmp_name = NULL; // Safety found = 1; ret = strdup(fullpath); PKI_log_debug("File successfully loaded %s", fullpath ); break; } PKI_Free(tmp_name); tmp_name = NULL; // Safety } else PKI_log_debug("No Name found!"); } } closedir( dirp ); } // Let's free the URL memory if (url) URL_free(url); // If found, let's return it if (found == 1) return ret; // If not found, we return NULL return NULL; }
int PKI_HTTP_get_socket (const PKI_SOCKET * sock, const char * data, size_t data_size, const char * content_type, int method, int timeout, size_t max_size, PKI_MEM_STACK ** sk ) { size_t len = 0; const char *my_cont_type = "application/unknown"; PKI_HTTP *http_rv = NULL; int rv = -1; int ret = PKI_OK; size_t max_len = 0; size_t auth_len = 0; char *tmp = NULL; char *auth_tmp = NULL; char *head_get = "GET %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: LibPKI\r\n" "Connection: close\r\n" "%s"; char *head_post = "POST %s HTTP/1.1\r\n" "Host: %s\r\n" "User-Agent: LibPKI\r\n" "Connection: close\r\n" "Content-type: %s\r\n" "Content-Length: %d\r\n" "%s"; char *head = NULL; if ( timeout < 0 ) timeout = 0; if ( !sock || !sock->url ) return PKI_ERR; // Process the authentication information if provided by the caller if (sock->url && sock->url->usr && sock->url->pwd) { // Rough estimate for the auth string max_len = strlen(sock->url->usr) + strlen(sock->url->pwd) + 100; // Special case for when a usr/pwd was specified in the URL auth_tmp = PKI_Malloc(len); auth_len = (size_t)snprintf(auth_tmp, len, "Authentication: user %s:%s\r\n\r\n", sock->url->usr, sock->url->pwd); } else { // If we do not have the auth info, we just add the end of header auth_len = 2; auth_tmp = "\r\n"; } if (method == PKI_HTTP_METHOD_GET) { // Gets the right header head = head_get; // Estimate the header's final size max_len = strlen(head) + strlen(sock->url->path) + strlen(sock->url->addr) + 101; // Allocates enough space for the header tmp = PKI_Malloc ( max_len + auth_len ); // Prints the header into the tmp container len = (size_t) snprintf(tmp, max_len, head, sock->url->path, sock->url->addr, auth_tmp); } else if (method == PKI_HTTP_METHOD_POST) { // Gets the right head head = head_post; // Determines the right content type if ( content_type ) my_cont_type = content_type; else my_cont_type = "text/html"; // Checks the max len for the allocated header max_len = strlen(head) + strlen(sock->url->path) + strlen(sock->url->addr) + strlen(my_cont_type) + 101; // Allocates the memory for the header tmp = PKI_Malloc ( max_len + auth_len ); // Prints the header into the tmp container len = (size_t) snprintf(tmp, max_len, head, sock->url->path, sock->url->addr, my_cont_type, data_size, auth_tmp ); } else { PKI_log_err ( "Method (%d) not supported!", method ); return PKI_ERR; } // PKI_MEM *r = PKI_MEM_new_data(len, tmp); // URL_put_data("file://http_req.txt", r, NULL, NULL, 0, 0, NULL); // PKI_MEM_free(r); if ((rv = (int) PKI_SOCKET_write(sock, tmp, len)) < 0) { PKI_log_err("Can not write HTTP header to socket"); PKI_Free(tmp); goto err; } // Free the tmp pointer that held the request header if (tmp) PKI_Free (tmp); // If we were using a POST method, we need to actually send the data if(data != NULL) { PKI_log_err("{DEBUG} Writing Data -> data_size = %d, data = %p", data_size, data); if ((PKI_SOCKET_write(sock, data, data_size)) < 0) { PKI_log_err ("Can not write POST to socket."); goto err; } } // Let's now wait for the response from the server if ((http_rv = PKI_HTTP_get_message(sock, timeout, max_size)) == NULL) { PKI_log_err ("HTTP retrieval error\n"); goto err; } // We shall now check for the return code if (http_rv->code >= 400 ) { goto err; } else if (http_rv->code >= 300) { /* Redirection - let's try that */ if (http_rv->location == NULL) { PKI_log_debug ( "HTTP Redirection but no location provided!"); goto err; } PKI_log_debug("HTTP Redirection Detected [URL: %s]", http_rv->location ); if (strstr(http_rv->location, "://") != NULL) { URL *url_tmp = NULL; if( strncmp_nocase( http_rv->location, sock->url->url_s, (int) strlen(http_rv->location)) == 0) { PKI_log_debug( "HTTP cyclic redirection!"); goto err; } if ((url_tmp = URL_new ( http_rv->location )) == NULL) { PKI_log_debug("HTTP location is not a valid URI (%s)", http_rv->location ); goto err; } if ( sock->url->ssl == 0 ) { ret = PKI_HTTP_get_url ( url_tmp, data, data_size, content_type, method, timeout, max_size, sk, NULL ); } else { PKI_SSL *ssl2 = PKI_SSL_dup ( sock->ssl ); ret = PKI_HTTP_get_url ( url_tmp, data, data_size, content_type, method, timeout, max_size, sk, ssl2 ); } if ( url_tmp ) URL_free ( url_tmp ); goto end; } else { const char *prot_s = NULL; char new_url[2048]; URL *my_new_url = NULL; PKI_SSL *ssl2 = PKI_SSL_dup ( sock->ssl ); prot_s = URL_proto_to_string ( sock->url->proto ); if( !prot_s ) goto err; snprintf(new_url, sizeof(new_url),"%s://%s%s", prot_s, sock->url->addr, http_rv->location ); if( strncmp_nocase( new_url, sock->url->url_s, (int) strlen ( new_url )) == 0 ) { PKI_log_debug( "HTTP cyclic redirection!"); goto err; } my_new_url = URL_new ( new_url ); ret = PKI_HTTP_get_url ( my_new_url, data, data_size, content_type, method, timeout, max_size, sk, ssl2 ); if (ssl2) PKI_SSL_free ( ssl2 ); } } else if (http_rv->code != 200) { PKI_log_debug( "Unknown HTTP Return code [Code: %d]", http_rv->code ); goto err; } /* PKI_log_err("{DEBUG} method = %d, header->size = %d, body = %p, body_size = %d", http_rv->method, http_rv->head->size, http_rv->body, http_rv->body->size); URL_put_data("file://http-resp-header.txt", http_rv->head, NULL, NULL, 0, 0, NULL); URL_put_data("file://http-resp-data.txt", http_rv->body, NULL, NULL, 0, 0, NULL); */ // If a Pointer was provided, we want the data back if (sk) { // Checks if the caller provided an already allocated data // structure. If not, we allocate it. if (*sk) PKI_STACK_MEM_free_all(*sk); // Allocates a new structure if ((*sk = PKI_STACK_MEM_new()) == NULL) { // If a memory error occurs report it and exit PKI_ERROR(PKI_ERR_MEMORY_ALLOC, NULL); // Nothing more to do goto err; } // Add the returned value to the stack if (PKI_STACK_MEM_push(*sk, http_rv->body) != PKI_OK) { PKI_log_err("Can not push the HTTP result body in the result stack"); goto err; } // Remove ownership of the body PKI_MEM from the original // HTTP msg container http_rv->body = NULL; } end: // Finally free the HTTP message memory if (http_rv) PKI_HTTP_free(http_rv); // Returns the result return ret; err: // Error condition if (http_rv) PKI_HTTP_free ( http_rv ); // Free the locally allocated memory if (*sk) PKI_STACK_MEM_free_all(*sk); *sk = NULL; return PKI_ERR; }
PKI_X509_PRQP_RESP * PKI_DISCOVER_get_resp_url ( PKI_X509_PRQP_REQ *p, URL *url ) { PKI_X509_PRQP_RESP * ret = NULL; char line[1024], name[1024], addr[1024]; FILE *file; if( !p || !p->value ) { PKI_log_debug( "WARNING, no PRQP request when trying to get" " the response!"); return ( NULL ); } if( url ) { if (( ret = PKI_X509_PRQP_RESP_get_http ( url, p, 0)) != NULL ) { return ret; } else { return NULL; } } file = fopen( PKI_PRQP_LIB_CONF_FILE, "r"); if( !file ) { PKI_log_debug( "WARNING, PRQP config file %s not found!", PKI_PRQP_LIB_CONF_FILE ); return ( NULL ); } while(!feof(file)) { if( fgets(line, sizeof(line), file) ) { if((memcmp(line, ";", 1) == 0) || (memcmp(line, "#", 1) == 0)) continue; if(sscanf(line, "%1024s %1024s", name, addr ) > 1 ) { char *full_url_s = NULL; size_t full_len = 0; if((strcmp_nocase( name, PKI_PRQP_LIB_CONF_ENTRY_LONG)==0) || (strcmp_nocase ( name, PKI_PRQP_LIB_CONF_ENTRY_SHORT ) == 0)) { URL *l_url = NULL; full_len = sizeof( addr ) + 12; full_url_s = PKI_Malloc ( full_len ); snprintf( full_url_s, full_len, "http://%s", addr ); if ( strchr ( addr, ':') == NULL ) { strncat ( full_url_s, ":830", full_len ); } PKI_log_debug( "Trying PRQP RQA -> %s", full_url_s ); if((l_url = URL_new( full_url_s )) == NULL) { PKI_log_debug("Can not parse address %s", full_url_s ); PKI_Free ( full_url_s ); continue; } if( l_url->port <= 0 ) l_url->port = PKI_PRQP_DEFAULT_PORT; l_url->proto = URI_PROTO_HTTP; ret = PKI_X509_PRQP_RESP_get_http ( l_url, p, 0); PKI_Free ( full_url_s ); if( ret == NULL ) { PKI_log( PKI_LOG_ERR, "Can not get response " "from server (%s:%d)!", l_url->addr, l_url->port); URL_free ( l_url ); } else { /* Exit the cycle */ PKI_log_debug("Got PRQP response from server"); URL_free ( l_url ); fclose(file); return ret; } } } } } fclose(file); return ret; }
static void testPool(const char *testURL) { URL_T url; char *schema; ConnectionPool_T pool; char *data[]= {"Fry", "Leela", "Bender", "Farnsworth", "Zoidberg", "Amy", "Hermes", "Nibbler", "Cubert", "Zapp", "Joey Mousepad", "ЯΣ༆", 0}; if (Str_startsWith(testURL, "mysql")) { schema = SCHEMA_MYSQL; } else if (Str_startsWith(testURL, "postgresql")) { schema = SCHEMA_POSTGRESQL; } else if (Str_startsWith(testURL, "sqlite")) { schema = SCHEMA_SQLITE; } else if (Str_startsWith(testURL, "oracle")) { schema = SCHEMA_ORACLE; } else { printf("Unsupported database protocol\n"); exit(1); } printf("=> Test1: create/destroy\n"); { pool = ConnectionPool_new(URL_new(testURL)); assert(pool); url = ConnectionPool_getURL(pool); ConnectionPool_free(&pool); assert(! pool); URL_free(&url); } printf("=> Test1: OK\n\n"); printf("=> Test2: NULL value\n"); { url = URL_new(NULL); assert(! url); pool = ConnectionPool_new(url); assert(! pool); } printf("=> Test2: OK\n\n"); printf("=> Test3: start/stop\n"); { url = URL_new(testURL); pool = ConnectionPool_new(url); assert(pool); ConnectionPool_start(pool); ConnectionPool_stop(pool); ConnectionPool_free(&pool); assert(pool==NULL); URL_free(&url); // Test that exception is thrown on start error TRY { url = URL_new("not://a/database"); pool = ConnectionPool_new(url); assert(pool); ConnectionPool_start(pool); printf("\tResult: Test failed -- exception not thrown\n"); exit(1); } CATCH(SQLException) { // OK } FINALLY { ConnectionPool_free(&pool); assert(pool==NULL); URL_free(&url); } END_TRY; } printf("=> Test3: OK\n\n"); printf("=> Test4: Connection execute & transaction\n"); { int i; Connection_T con; url = URL_new(testURL); pool = ConnectionPool_new(url); assert(pool); ConnectionPool_setAbortHandler(pool, TabortHandler); ConnectionPool_start(pool); con = ConnectionPool_getConnection(pool); assert(con); TRY Connection_execute(con, "drop table zild_t;"); ELSE END_TRY; Connection_execute(con, "%s", schema); Connection_beginTransaction(con); /* Insert values into database and assume that auto increment of id works */ for (i = 0; data[i]; i++) Connection_execute(con, "insert into zild_t (name, percent) values('%s', %d.%d);", data[i], i+1, i); // Assert that the last insert statement added one row assert(Connection_rowsChanged(con) == 1); /* Assert that last row id works for MySQL and SQLite. Neither Oracle nor PostgreSQL support last row id directly. The way to do this in PostgreSQL is to use currval() or return the id on insert. */ if (IS(URL_getProtocol(url), "sqlite") || IS(URL_getProtocol(url), "mysql")) assert(Connection_lastRowId(con) == 12); Connection_commit(con); printf("\tResult: table zild_t successfully created\n"); Connection_close(con); } printf("=> Test4: OK\n\n"); printf("=> Test5: Prepared Statement\n"); { int i; char blob[8192]; char *images[]= {"Ceci n'est pas une pipe", "Mona Lisa", "Bryllup i Hardanger", "The Scream", "Vampyre", "Balcony", "Cycle", "Day & Night", "Hand with Reflecting Sphere", "Drawing Hands", "Ascending and Descending", 0}; Connection_T con = ConnectionPool_getConnection(pool); assert(con); // 1. Prepared statement, perform a nonsense update to test rowsChanged PreparedStatement_T p1 = Connection_prepareStatement(con, "update zild_t set image=?;"); PreparedStatement_setString(p1, 1, ""); PreparedStatement_execute(p1); printf("\tRows changed: %lld\n", PreparedStatement_rowsChanged(p1)); // Assert that all 12 rows in the data set was changed assert(PreparedStatement_rowsChanged(p1) == 12); // 2. Prepared statement, update the table proper with "images". PreparedStatement_T pre = Connection_prepareStatement(con, "update zild_t set image=? where id=?;"); assert(pre); for (i = 0; images[i]; i++) { PreparedStatement_setBlob(pre, 1, images[i], (int)strlen(images[i])+1); PreparedStatement_setInt(pre, 2, i + 1); PreparedStatement_execute(pre); } // The last execute changed one row only assert(PreparedStatement_rowsChanged(pre) == 1); /* Add a database null blob value */ PreparedStatement_setBlob(pre, 1, NULL, 0); PreparedStatement_setInt(pre, 2, 5); PreparedStatement_execute(pre); /* Add a database null string value */ PreparedStatement_setString(pre, 1, NULL); PreparedStatement_setInt(pre, 2, 1); PreparedStatement_execute(pre); /* Add a large blob */ memset(blob, 'x', 8192); blob[8191] = 0; /* Mark start and end */ *blob='S'; blob[8190] = 'E'; PreparedStatement_setBlob(pre, 1, blob, 8192); PreparedStatement_setInt(pre, 2, i + 1); PreparedStatement_execute(pre); printf("\tResult: prepared statement successfully executed\n"); Connection_close(con); } printf("=> Test5: OK\n\n"); printf("=> Test6: Result Sets\n"); { int i; int imagesize = 0; Connection_T con; ResultSet_T rset; ResultSet_T names; PreparedStatement_T pre; con = ConnectionPool_getConnection(pool); assert(con); rset = Connection_executeQuery(con, "select id, name, percent, image from zild_t where id < %d order by id;", 100); assert(rset); printf("\tResult:\n"); printf("\tNumber of columns in resultset: %d\n\t", ResultSet_getColumnCount(rset)); assert(4==ResultSet_getColumnCount(rset)); i = 1; printf("%-5s", ResultSet_getColumnName(rset, i++)); printf("%-16s", ResultSet_getColumnName(rset, i++)); printf("%-10s", ResultSet_getColumnName(rset, i++)); printf("%-16s", ResultSet_getColumnName(rset, i++)); printf("\n\t------------------------------------------------------\n"); while (ResultSet_next(rset)) { int id = ResultSet_getIntByName(rset, "id"); const char *name = ResultSet_getString(rset, 2); double percent = ResultSet_getDoubleByName(rset, "percent"); const char *blob = (char*)ResultSet_getBlob(rset, 4, &imagesize); printf("\t%-5d%-16s%-10.2f%-16.38s\n", id, name ? name : "null", percent, imagesize ? blob : ""); } rset = Connection_executeQuery(con, "select image from zild_t where id=12;"); assert(1==ResultSet_getColumnCount(rset)); // Assert that types are interchangeable (to some degree) and that all data is returned while (ResultSet_next(rset)) { const char *image = ResultSet_getStringByName(rset, "image"); const void *blob = ResultSet_getBlobByName(rset, "image", &imagesize); assert(image && blob); assert(strlen(image) + 1 == 8192); assert(imagesize == 8192); } printf("\tResult: check max rows.."); Connection_setMaxRows(con, 3); rset = Connection_executeQuery(con, "select id from zild_t;"); assert(rset); i = 0; while (ResultSet_next(rset)) i++; assert((i)==3); printf("success\n"); printf("\tResult: check prepared statement resultset.."); Connection_setMaxRows(con, 0); pre = Connection_prepareStatement(con, "select name from zild_t where id=?"); assert(pre); PreparedStatement_setInt(pre, 1, 2); names = PreparedStatement_executeQuery(pre); assert(names); assert(ResultSet_next(names)); assert(Str_isEqual("Leela", ResultSet_getString(names, 1))); printf("success\n"); printf("\tResult: check prepared statement re-execute.."); PreparedStatement_setInt(pre, 1, 1); names = PreparedStatement_executeQuery(pre); assert(names); assert(ResultSet_next(names)); assert(Str_isEqual("Fry", ResultSet_getString(names, 1))); printf("success\n"); printf("\tResult: check prepared statement without in-params.."); pre = Connection_prepareStatement(con, "select name from zild_t;"); assert(pre); names = PreparedStatement_executeQuery(pre); assert(names); for (i = 0; ResultSet_next(names); i++); assert(i==12); printf("success\n"); /* Need to close and release statements before we can drop the table, sqlite need this */ Connection_clear(con); Connection_execute(con, "drop table zild_t;"); Connection_close(con); ConnectionPool_stop(pool); ConnectionPool_free(&pool); assert(pool==NULL); URL_free(&url); } printf("=> Test6: OK\n\n"); printf("=> Test7: reaper start/stop\n"); { int i; Vector_T v = Vector_new(20); url = URL_new(testURL); pool = ConnectionPool_new(url); assert(pool); ConnectionPool_setInitialConnections(pool, 4); ConnectionPool_setMaxConnections(pool, 20); ConnectionPool_setConnectionTimeout(pool, 4); ConnectionPool_setReaper(pool, 4); ConnectionPool_setAbortHandler(pool, TabortHandler); ConnectionPool_start(pool); assert(4==ConnectionPool_size(pool)); printf("Creating 20 Connections.."); for (i = 0; i<20; i++) Vector_push(v, ConnectionPool_getConnection(pool)); assert(ConnectionPool_size(pool) == 20); assert(ConnectionPool_active(pool) == 20); printf("success\n"); printf("Closing Connections down to initial.."); while (! Vector_isEmpty(v)) Connection_close(Vector_pop(v)); assert(ConnectionPool_active(pool) == 0); assert(ConnectionPool_size(pool) == 20); printf("success\n"); printf("Please wait 10 sec for reaper to harvest closed connections.."); Connection_T con = ConnectionPool_getConnection(pool); // Activate one connection to verify the reaper does not close any active fflush(stdout); sleep(10); assert(5 == ConnectionPool_size(pool)); // 4 initial connections + the one active we got above assert(1 == ConnectionPool_active(pool)); printf("success\n"); Connection_close(con); ConnectionPool_stop(pool); ConnectionPool_free(&pool); Vector_free(&v); assert(pool==NULL); URL_free(&url); } printf("=> Test7: OK\n\n"); printf("=> Test8: Exceptions handling\n"); { int i; Connection_T con; ResultSet_T result; url = URL_new(testURL); pool = ConnectionPool_new(url); assert(pool); ConnectionPool_setAbortHandler(pool, TabortHandler); ConnectionPool_start(pool); con = ConnectionPool_getConnection(pool); assert(con); /* * The following should work without throwing exceptions */ TRY { Connection_execute(con, "%s", schema); } ELSE { printf("\tResult: Creating table zild_t failed -- %s\n", Exception_frame.message); assert(false); // Should not fail } END_TRY; TRY { Connection_beginTransaction(con); for (i = 0; data[i]; i++) Connection_execute(con, "insert into zild_t (name, percent) values('%s', %d.%d);", data[i], i+1, i); Connection_commit(con); printf("\tResult: table zild_t successfully created\n"); } ELSE { printf("\tResult: Test failed -- %s\n", Exception_frame.message); assert(false); // Should not fail } FINALLY { Connection_close(con); } END_TRY; assert((con = ConnectionPool_getConnection(pool))); TRY { int i, j; const char *bg[]= {"Starbuck", "Sharon Valerii", "Number Six", "Gaius Baltar", "William Adama", "Lee \"Apollo\" Adama", "Laura Roslin", 0}; PreparedStatement_T p = Connection_prepareStatement (con, "insert into zild_t (name) values(?);"); /* If we did not get a statement, an SQLException is thrown and we will not get here. So we can safely use the statement now. Likewise, below, we do not have to check return values from the statement since any error will throw an SQLException and transfer the control to the exception handler */ for (i = 0, j = 42; bg[i]; i++, j++) { PreparedStatement_setString(p, 1, bg[i]); PreparedStatement_execute(p); } } CATCH(SQLException) { printf("\tResult: prepare statement failed -- %s\n", Exception_frame.message); assert(false); } END_TRY; TRY { printf("\t\tBattlestar Galactica: \n"); result = Connection_executeQuery(con, "select name from zild_t where id > 12;"); while (ResultSet_next(result)) printf("\t\t%s\n", ResultSet_getString(result, 1)); } CATCH(SQLException) { printf("\tResult: resultset failed -- %s\n", Exception_frame.message); assert(false); } FINALLY { Connection_close(con); } END_TRY; /* * The following should fail and throw exceptions. The exception error * message can be obtained with Exception_frame.message, or from * Connection_getLastError(con). Exception_frame.message contains both * SQL errors or api errors such as prepared statement parameter index * out of range, while Connection_getLastError(con) only has SQL errors */ TRY { assert((con = ConnectionPool_getConnection(pool))); Connection_execute(con, "%s", schema); /* Creating the table again should fail and we should not come here */ printf("\tResult: Test failed -- exception not thrown\n"); exit(1); } CATCH(SQLException) { Connection_close(con); } END_TRY; TRY { assert((con = ConnectionPool_getConnection(pool))); printf("\tTesting: Query with errors.. "); Connection_executeQuery(con, "blablabala;"); printf("\tResult: Test failed -- exception not thrown\n"); exit(1); } CATCH(SQLException) { printf("ok\n"); Connection_close(con); } END_TRY; TRY { printf("\tTesting: Prepared statement query with errors.. "); assert((con = ConnectionPool_getConnection(pool))); PreparedStatement_T p = Connection_prepareStatement(con, "blablabala;"); ResultSet_T r = PreparedStatement_executeQuery(p); while(ResultSet_next(r)); printf("\tResult: Test failed -- exception not thrown\n"); exit(1); } CATCH(SQLException) { printf("ok\n"); Connection_close(con); } END_TRY; TRY { assert((con = ConnectionPool_getConnection(pool))); printf("\tTesting: Column index out of range.. "); result = Connection_executeQuery(con, "select id, name from zild_t;"); while (ResultSet_next(result)) { int id = ResultSet_getInt(result, 1); const char *name = ResultSet_getString(result, 2); /* So far so good, now, try access an invalid column, which should throw an SQLException */ int bogus = ResultSet_getInt(result, 3); printf("\tResult: Test failed -- exception not thrown\n"); printf("%d, %s, %d", id, name, bogus); exit(1); } } CATCH(SQLException) { printf("ok\n"); Connection_close(con); } END_TRY; TRY { assert((con = ConnectionPool_getConnection(pool))); printf("\tTesting: Invalid column name.. "); result = Connection_executeQuery(con, "select name from zild_t;"); while (ResultSet_next(result)) { const char *name = ResultSet_getStringByName(result, "nonexistingcolumnname"); printf("%s", name); printf("\tResult: Test failed -- exception not thrown\n"); exit(1); } } CATCH(SQLException) { printf("ok\n"); Connection_close(con); } END_TRY; TRY { assert((con = ConnectionPool_getConnection(pool))); PreparedStatement_T p = Connection_prepareStatement(con, "update zild_t set name = ? where id = ?;"); printf("\tTesting: Parameter index out of range.. "); PreparedStatement_setInt(p, 3, 123); printf("\tResult: Test failed -- exception not thrown\n"); exit(1); } CATCH(SQLException) { printf("ok\n"); } FINALLY { Connection_close(con); } END_TRY; assert((con = ConnectionPool_getConnection(pool))); Connection_execute(con, "drop table zild_t;"); Connection_close(con); ConnectionPool_stop(pool); ConnectionPool_free(&pool); assert(pool==NULL); URL_free(&url); } printf("=> Test8: OK\n\n"); printf("=> Test9: Ensure Capacity\n"); { /* Check that MySQL ensureCapacity works for columns that exceed the preallocated buffer and that no truncation is done */ if ( Str_startsWith(testURL, "mysql")) { int myimagesize; url = URL_new(testURL); pool = ConnectionPool_new(url); assert(pool); ConnectionPool_start(pool); Connection_T con = ConnectionPool_getConnection(pool); assert(con); Connection_execute(con, "CREATE TABLE zild_t(id INTEGER AUTO_INCREMENT PRIMARY KEY, image BLOB, string TEXT);"); PreparedStatement_T p = Connection_prepareStatement(con, "insert into zild_t (image, string) values(?, ?);"); char t[4096]; memset(t, 'x', 4096); t[4095] = 0; for (int i = 0; i < 4; i++) { PreparedStatement_setBlob(p, 1, t, (i+1)*512); // store successive larger string-blobs to trigger realloc on ResultSet_getBlobByName PreparedStatement_setString(p, 2, t); PreparedStatement_execute(p); } ResultSet_T r = Connection_executeQuery(con, "select image, string from zild_t;"); for (int i = 0; ResultSet_next(r); i++) { ResultSet_getBlobByName(r, "image", &myimagesize); const char *image = ResultSet_getStringByName(r, "image"); // Blob as image should be terminated const char *string = ResultSet_getStringByName(r, "string"); assert(myimagesize == (i+1)*512); assert(strlen(image) == ((i+1)*512)); assert(strlen(string) == 4095); } p = Connection_prepareStatement(con, "select image, string from zild_t;"); r = PreparedStatement_executeQuery(p); for (int i = 0; ResultSet_next(r); i++) { ResultSet_getBlobByName(r, "image", &myimagesize); const char *image = ResultSet_getStringByName(r, "image"); const char *string = (char*)ResultSet_getStringByName(r, "string"); assert(myimagesize == (i+1)*512); assert(strlen(image) == ((i+1)*512)); assert(strlen(string) == 4095); } Connection_execute(con, "drop table zild_t;"); Connection_close(con); ConnectionPool_stop(pool); ConnectionPool_free(&pool); URL_free(&url); } } printf("=> Test9: OK\n\n"); printf("============> Connection Pool Tests: OK\n\n"); }
int OCSPD_build_ca_list ( OCSPD_CONFIG *handler, PKI_CONFIG_STACK *ca_conf_sk) { int i = 0; PKI_STACK *ca_list = NULL; PKI_log_debug("Building CA List"); if ( !ca_conf_sk ) { PKI_log( PKI_LOG_ERR, "No stack of ca configs!"); return ( PKI_ERR ); } if((ca_list = PKI_STACK_new((void (*))CA_LIST_ENTRY_free)) == NULL ) { PKI_log_err ( "Memory Error"); return ( PKI_ERR ); } for (i = 0; i < PKI_STACK_CONFIG_elements( ca_conf_sk ); i++) { char *tmp_s = NULL; URL *tmp_url = NULL; PKI_X509_CERT *tmp_cert = NULL; CA_LIST_ENTRY *ca = NULL; PKI_CONFIG *cnf = NULL; /* Get the current Configureation file */ cnf = PKI_STACK_CONFIG_get_num( ca_conf_sk, i ); if (!cnf) continue; /* Get the CA cert from the cfg file itself */ if((tmp_s = PKI_CONFIG_get_value( cnf, "/caConfig/caCertValue" )) == NULL ) { /* Get the CA parsed url */ if((tmp_url = URL_new( PKI_CONFIG_get_value( cnf, "/caConfig/caCertUrl" ))) == NULL ) { /* Error, can not parse url data */ PKI_log( PKI_LOG_ERR, "Can not parse CA cert url (%s)", PKI_CONFIG_get_value(cnf, "/caConfig/caCertUrl")); continue; } if((tmp_cert = PKI_X509_CERT_get_url(tmp_url, NULL, NULL ))== NULL) { PKI_log_err("Can not get CA cert from (%s)", tmp_url); URL_free (tmp_url); continue; } } else { PKI_X509_CERT_STACK *cc_sk = NULL; PKI_MEM *mm = NULL; if((mm = PKI_MEM_new_null()) == NULL ) { PKI_Free(tmp_s); continue; } PKI_MEM_add ( mm, tmp_s, strlen(tmp_s)); if((cc_sk=PKI_X509_CERT_STACK_get_mem(mm, NULL)) == NULL ) { PKI_log_err ( "Can not parse cert from /caConfig/caCertValue"); PKI_Free(tmp_s); continue; } if ((tmp_cert = PKI_STACK_X509_CERT_pop( cc_sk )) == NULL ) { PKI_log_err ( "No elements on stack from /caConfig/caCertValue"); PKI_STACK_X509_CERT_free_all(cc_sk); PKI_Free(tmp_s); continue; } PKI_STACK_X509_CERT_free ( cc_sk ); PKI_Free(tmp_s); } /* OCSPD create the CA entry */ if ((ca = CA_LIST_ENTRY_new()) == NULL ) { PKI_log_err ( "CA List structure init error"); /* remember to do THIS!!!! */ if( tmp_url ) URL_free ( tmp_url ); if( tmp_cert ) PKI_X509_CERT_free ( tmp_cert ); continue; } ca->ca_cert = tmp_cert; tmp_cert = NULL; ca->ca_url = tmp_url; tmp_url = NULL; ca->ca_id = PKI_CONFIG_get_value( cnf, "/caConfig/name" ); ca->cid = CA_ENTRY_CERTID_new ( ca->ca_cert, handler->digest ); /* Get the CRL URL and the CRL itself */ if((tmp_s = PKI_CONFIG_get_value(cnf, "/caConfig/crlUrl")) == NULL) { PKI_STACK *cdp_sk = NULL; /* Now let's get it from PRQP */ /* Now from the Certificate */ if((cdp_sk = PKI_X509_CERT_get_cdp (ca->ca_cert)) ==NULL) { // No source for the CRL Distribution Point PKI_log_err ( "ERROR::Can not find the CDP for %s, skipping CA", ca->ca_id ); CA_LIST_ENTRY_free ( ca ); continue; } while ((tmp_s = PKI_STACK_pop ( cdp_sk )) != NULL) { if ((ca->crl_url = URL_new ( tmp_s )) == NULL ) { PKI_log_err( "URL %s not in the right format!"); CA_LIST_ENTRY_free ( ca ); continue; } else if( tmp_s ) PKI_Free ( tmp_s ); break; } } else { PKI_log_debug("Got CRL Url -> %s", tmp_s ); if((ca->crl_url = URL_new ( tmp_s )) == NULL ) { PKI_log_err ("Error Parsing CRL URL [%s] for CA [%s]", ca->ca_id, tmp_s); CA_LIST_ENTRY_free ( ca ); PKI_Free(tmp_s); continue; } PKI_Free(tmp_s); } if(OCSPD_load_crl ( ca, handler ) == PKI_ERR ) { PKI_log_err ( "Can not get CRL for %s", ca->ca_id); CA_LIST_ENTRY_free ( ca ); continue; } /* If the Server has a Token to be used with this CA, let's load it */ if((tmp_s = PKI_CONFIG_get_value ( cnf, "/caConfig/serverToken" )) == NULL) { /* No token in config, let's see if a specific cert is configured */ ca->token = NULL; if((tmp_s = PKI_CONFIG_get_value ( cnf, "/caConfig/serverCertUrl" )) == NULL ) { /* No cert is configured, we will use the defaults */ ca->server_cert = NULL; } else { /* The Server's cert URL is found, let's load the certificate */ if ((tmp_cert = PKI_X509_CERT_get ( tmp_s, NULL, NULL )) == NULL ) { PKI_log_err("Can not get server's cert from %s!", tmp_s ); CA_LIST_ENTRY_free ( ca ); PKI_Free(tmp_s); continue; } else { ca->server_cert = tmp_cert; } PKI_Free(tmp_s); } } else { /* A Token for this CA is found - we do not load it to avoid problems with Thread Initialization */ ca->server_cert = NULL; ca->token_name = tmp_s; ca->token = PKI_TOKEN_new_null(); if ((tmp_s = PKI_CONFIG_get_value ( cnf, "/caConfig/pkiConfigDir" )) != NULL) { ca->token_config_dir = strdup( tmp_s ); PKI_Free(tmp_s); } else { ca->token_config_dir = strdup(handler->token_config_dir); } } if((tmp_s = PKI_CONFIG_get_value ( cnf, "/caConfig/caCompromised" )) == NULL) { ca->compromised = 0; } else { ca->compromised = atoi(tmp_s); PKI_Free(tmp_s); } /* Responder Id Type */ if ((tmp_s = PKI_CONFIG_get_value(cnf, "/caConfig/responderIdType")) != NULL) { if (strncmp_nocase(tmp_s, "keyid", 5) == 0) { ca->response_id_type = PKI_X509_OCSP_RESPID_TYPE_BY_KEYID; } else if (strncmp_nocase(tmp_s, "name", 4) == 0) { ca->response_id_type = PKI_X509_OCSP_RESPID_TYPE_BY_NAME; } else { PKI_log_err("Can not parse responderIdType: %s (allowed 'keyid' or 'name')", tmp_s); exit(1); } PKI_Free(tmp_s); } else { // Default Value ca->response_id_type = PKI_X509_OCSP_RESPID_TYPE_BY_NAME; } // Now let's add the CA_LIST_ENTRY to the list of configured CAs PKI_STACK_push ( ca_list, ca ); } handler->ca_list = ca_list; return ( PKI_OK ); }