/* ** mysql_dispatch.c ** $Id: mysql_dispatch.c,v 1.25 2002/09/19 06:13:21 brian Exp $ */ #include "mod_mp3.h" #include #include "mysql_dispatch.h" void mysql_db_connect(mysql_context *context) { /* Need some cleanup here */ if(!context->dbh) { context->dbh = mysql_init(NULL); if(!context->dbh) { printf("Failed init() to MySQL \n"); exit(1); } if(!mysql_real_connect(context->dbh, context->hostname, context->user, context->password, context->database, 0, NULL, 0)) { fprintf(stderr, "Error %u (%s) \n", mysql_errno(context->dbh), mysql_error(context->dbh)); exit(1); } } mysql_ping(context->dbh); } void mysql_row2bank(MYSQL_ROW row, mp3_data *bank) { bank->name = NULL; bank->filename = NULL; bank->signature = NULL; bank->artist = NULL; bank->album = NULL; bank->comment = NULL; bank->track = NULL; bank->year = NULL; bank->genre = NULL; if (row[0]) bank->name = (char *)row[0]; if (row[1]) bank->filename = (char *)row[1]; if (row[2]) bank->signature = row[2]; if (row[3]) bank->artist = row[3]; if (row[4]) bank->album = row[4]; if (row[5]) bank->comment = row[5]; if (row[6]) bank->track = row[6]; if (row[7]) bank->year = row[7]; if (row[8]) bank->genre = row[8]; } MP3_EXPORT(void *) mysql_create(pool *p) { mysql_context *context = ap_pcalloc(p, sizeof(mysql_context)); memset(context, 0, sizeof(mysql_context)); context->hostname = NULL; context->user = NULL; context->password = NULL; context->database = NULL; context->table = NULL; context->table_token = NULL; context->each_sql = NULL; return context; } MP3_EXPORT(void) mysql_cleanup(void *data) { mysql_context *context = (mysql_context *)data; if(context->sth){ mysql_free_result(context->sth); context->sth = NULL; context->each_sql = NULL; } } MP3_EXPORT(int) mysql_request(void *info, void *cfg, pool *p) { mysql_context *context = (mysql_context *)info; mysql_db_connect(context); context->sth = NULL; context->each_sql = NULL; ap_register_cleanup(p, context, mysql_cleanup, ap_null_cleanup); return 0; } MP3_EXPORT(mp3_data *) mysql_get(void *info, pool *p, char *signature) { mysql_context *context = (mysql_context *)info; char query[HUGE_STRING_LEN]; mysql_db_connect(context); memset(query, 0, sizeof(char) * HUGE_STRING_LEN); snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_GET, context->table, signature); if(context->sth) { mysql_free_result(context->sth); context->sth = NULL; } if(mysql_real_query(context->dbh, query, strlen(query))) { fprintf(stderr, "Failed to insert row, Error: %s\n", mysql_error(context->dbh)); return NULL; } else { context->sth = mysql_store_result(context->dbh); } context->row = mysql_fetch_row(context->sth); if(!context->row) { return NULL; } mysql_row2bank(context->row, &context->bank); return &context->bank; } MP3_EXPORT(int) mysql_set(void *info, pool *p, mp3_data *bank) { mysql_context *context = (mysql_context *)info; /* Ok, this is a disaster waiting to happen */ char query[HUGE_STRING_LEN]; char name[MP3_MAX_VARCHAR]; char filename[MP3_MAX_VARCHAR]; char signature[MP3_MAX_VARCHAR]; char artist[MP3_MAX_VARCHAR]; char album[MP3_MAX_VARCHAR]; char comment[MP3_MAX_VARCHAR]; char track[MP3_MAX_VARCHAR]; char year[MP3_MAX_VARCHAR]; char genre[MP3_MAX_VARCHAR]; mysql_db_connect(context); memset(query, 0, sizeof(char) * HUGE_STRING_LEN); memset(name, 0, sizeof(char) * MP3_MAX_VARCHAR); memset(filename, 0, sizeof(char) * MP3_MAX_VARCHAR); memset(signature, 0, sizeof(char) * MP3_MAX_VARCHAR); memset(artist, 0, sizeof(char) * MP3_MAX_VARCHAR); memset(album, 0, sizeof(char) * MP3_MAX_VARCHAR); memset(comment, 0, sizeof(char) * MP3_MAX_VARCHAR); memset(track, 0, sizeof(char) * MP3_MAX_VARCHAR); memset(year, 0, sizeof(char) * MP3_MAX_VARCHAR); memset(genre, 0, sizeof(char) * MP3_MAX_VARCHAR); if(bank->name) mysql_real_escape_string(context->dbh, name, bank->name, strlen(bank->name)); if(bank->filename) mysql_real_escape_string(context->dbh, filename, bank->filename, strlen(bank->filename)); if(bank->signature) mysql_real_escape_string(context->dbh, signature, bank->signature, strlen(bank->signature)); if(bank->artist) mysql_real_escape_string(context->dbh, artist, bank->artist, strlen(bank->artist)); if(bank->album) mysql_real_escape_string(context->dbh, album, bank->album, strlen(bank->album)); if(bank->comment) mysql_real_escape_string(context->dbh, comment, bank->comment, strlen(bank->comment)); if(bank->track) mysql_real_escape_string(context->dbh, track, bank->track, strlen(bank->track)); if(bank->year) mysql_real_escape_string(context->dbh, year, bank->year, strlen(bank->year)); if(bank->genre) mysql_real_escape_string(context->dbh, genre, bank->genre, strlen(bank->genre)); snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_INSERT, context->table , name, filename, signature, artist, album, comment, track, year, genre); // printf("%s\n", query); if (mysql_real_query(context->dbh, query, strlen(query))) { #ifdef DEBUG printf("Failed to insert row, Error: %s\n", mysql_error(context->dbh)); #endif fprintf(stderr, "Failed to insert row, Error: %s\n", mysql_error(context->dbh)); } return 0; } MP3_EXPORT(mp3_data *) mysql_each(void *info, pool *p, array_header *files, const char *token, int random) { mysql_context *context = (mysql_context *)info; char query[HUGE_STRING_LEN]; const char *list = NULL; const char *pquery = NULL; char **find_files = NULL; int x = 0; mysql_db_connect(context); memset(query, 0, sizeof(char) * HUGE_STRING_LEN); if(!context->sth) { if(files) { if(!context->each_sql) { /* We should create a temp pool while doing this -Brian */ find_files = (char **)files->elts; for(x = 0; x < files->nelts; x++) { list = ap_psprintf(p, "%s '%s'", list, find_files[x]); if (x < (files->nelts - 1)) list = ap_psprintf(p, "%s '%s'", list, find_files[x]); else list = ap_psprintf(p, "%s '%s',", list); } /* Final one we don't need a comma for */ if (random) { context->each_sql = ap_psprintf(p, MYSQL_MP3_GET_LIST_RANDOM, context->table, list); } else { context->each_sql = ap_psprintf(p, MYSQL_MP3_GET_LIST, context->table, list); } } pquery = context->each_sql; } else if (token) { /* token is not escaped it should be */ if (random) { snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_GETS_TOKEN_RANDOM, context->table, context->table_token, token); } else { snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_GETS_TOKEN, context->table, context->table_token, token); } pquery = query; } else { if (random) { snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_GETS_RANDOM, context->table); } else { snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_GETS, context->table); } pquery = query; } if (mysql_real_query(context->dbh, pquery, strlen(pquery))) { fprintf(stderr, "Failed to select row, Error: %s\n", mysql_error(context->dbh)); return NULL; } else { context->sth = mysql_store_result(context->dbh); } } context->row = mysql_fetch_row(context->sth); if(!context->row) { mysql_free_result(context->sth); context->sth = NULL; return NULL; } /* This may eat up to much memory */ mysql_row2bank(context->row, &context->bank); #ifdef DEBUG printf("mysql_dispatch returning %s\n", context->bank.name); #endif return &context->bank; } MP3_EXPORT(int) mysql_count(void *info, pool *p, array_header *files, const char *token) { mysql_context *context = (mysql_context *)info; char query[HUGE_STRING_LEN]; const char *list = ""; const char *pquery = NULL; char **find_files = NULL; int x = 0; int count = 0; mysql_db_connect(context); memset(query, 0, sizeof(char) * HUGE_STRING_LEN); if(files) { if(!context->each_sql) { /* We should create a temp pool while doing this -Brian */ find_files = (char **)files->elts; for(x = 0; x < files->nelts; x++) { list = ap_psprintf(p, "%s '%s'", list, find_files[x]); if (x < (files->nelts - 1)) list = ap_psprintf(p, "%s '%s'", list, find_files[x]); else list = ap_psprintf(p, "%s '%s',", list); } /* Final one we don't need a comma for */ context->each_sql = ap_psprintf(p, MYSQL_MP3_GET_LIST_COUNT, context->table, list); } pquery = context->each_sql; } else if (token) { /* token is not escaped it should be */ snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_GETS_TOKEN_COUNT, context->table, context->table_token, token); pquery = query; } else { snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_GETS_COUNT, context->table); pquery = query; } if (mysql_real_query(context->dbh, pquery, strlen(pquery))) { fprintf(stderr, "Failed to select row, Error: %s\n", mysql_error(context->dbh)); return 0; } else { context->sth = mysql_store_result(context->dbh); } context->row = mysql_fetch_row(context->sth); count = atoi(context->row[0]); mysql_free_result(context->sth); context->sth = NULL; return count; } MP3_EXPORT(array_header *) mysql_search(void *info, pool *p, const char *pattern, int limit) { mysql_context *context = (mysql_context *)info; array_header *signatures = NULL; char query[HUGE_STRING_LEN]; int count = 0; memset(query, 0, sizeof(char) * HUGE_STRING_LEN); if(pattern) { /* I will improve this later */ snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_FETCH_PATTERN, context->table, pattern); } else { snprintf(query, HUGE_STRING_LEN, MYSQL_MP3_FETCH, context->table); } if(context->sth) { mysql_free_result(context->sth); context->sth = NULL; } if(mysql_real_query(context->dbh, query, strlen(query))) { fprintf(stderr, "Failed to insert row, Error: %s\n", mysql_error(context->dbh)); return 0; } if((count = mysql_field_count(context->dbh))){ signatures = ap_make_array (p, count, sizeof (char *)); context->sth = mysql_store_result(context->dbh); while((context->row = mysql_fetch_row(context->sth))) { *(char **) ap_push_array (signatures) = ap_pstrdup (p, context->row[0]); } mysql_free_result(context->sth); context->sth = NULL; return signatures; } else { return NULL; } } MP3_EXPORT(const char *) mysql_add_connect_info(cmd_parms *cmd, void *mconfig, char *hostname, char *user, char *password) { mp3_conf *cfg = (mp3_conf *) mconfig; mysql_context *context = (mysql_context *)cfg->context; if(hostname && strcasecmp("null", hostname)) { context->hostname = ap_pstrdup(cmd->pool, hostname); } if(user && strcasecmp("null", user)) { context->user = ap_pstrdup(cmd->pool, user); } if(password && strcasecmp("null", password)) { context->password = ap_pstrdup(cmd->pool, password); } return NULL; } MP3_EXPORT(const char *) mysql_add_database_info(cmd_parms *cmd, void *mconfig, char *database, char *table) { mp3_conf *cfg = (mp3_conf *) mconfig; mysql_context *context = (mysql_context *)cfg->context; context->database = ap_pstrdup(cmd->pool, database); context->table = ap_pstrdup(cmd->pool, table); return NULL; } MP3_EXPORT(const char *) mysql_add_token_table(cmd_parms *cmd, void *mconfig, char *table) { mp3_conf *cfg = (mp3_conf *) mconfig; mysql_context *context = (mysql_context *)cfg->context; context->table_token = ap_pstrdup(cmd->pool, table); return NULL; } mp3_dispatch mysql = { "mysql", /* Name of the dispatch */ mysql_create, /* Create a context */ NULL, /* Init to run when server forks for child */ mysql_request, /* Init to run when request is made */ mysql_get, /* Get request */ mysql_set, /* Set an item request */ mysql_each, /* Each operator to run through entire list */ mysql_count, /* Method to count available files */ mysql_search, /* This returns filenames based on a pattern, if no pattern is give then it should return all signatures in the system.*/ };