diff -Nur mpg123-0.59r-orig/Makefile mpg123-0.59r/Makefile --- mpg123-0.59r-orig/Makefile Tue Jun 15 22:39:06 1999 +++ mpg123-0.59r/Makefile Fri Dec 31 05:14:40 1999 @@ -558,12 +558,12 @@ tabinit.o audio.o layer1.o layer2.o layer3.o buffer.o \ getlopt.o httpget.o xfermem.o equalizer.o \ decode_ntom.o Makefile wav.o readers.o getbits.o \ - control_generic.o + control_generic.o mysqlsupport.o mysqlconfigure.o $(CC) $(CFLAGS) $(LDFLAGS) mpg123.o tabinit.o common.o layer1.o \ layer2.o layer3.o audio.o buffer.o decode_2to1.o equalizer.o \ decode_4to1.o getlopt.o httpget.o xfermem.o decode_ntom.o \ - wav.o readers.o getbits.o control_generic.o \ - $(OBJECTS) -o $(BINNAME) -lm $(AUDIO_LIB) + wav.o readers.o getbits.o control_generic.o mysqlsupport.o mysqlconfigure.o \ + $(OBJECTS) -o $(BINNAME) -lm -L/usr/local/lib/mysql -lmysqlclient $(AUDIO_LIB) mpg123.exe: mpg123.o common.o $(OBJECTS) decode_2to1.o decode_4to1.o \ tabinit.o audio.o layer1.o layer2.o layer3.o buffer.o \ @@ -583,7 +583,7 @@ decode_ntom.o: mpg123.h decode_i386.o: mpg123.h common.o: mpg123.h common.h -mpg123.o: mpg123.c mpg123.h getlopt.h xfermem.h version.h buffer.h term.h +mpg123.o: mpg123.c mpg123.h getlopt.h xfermem.h version.h buffer.h term.h mysqlsupport.h mpg123.h: audio.h audio.o: mpg123.h audio_oss.o: mpg123.h @@ -606,6 +606,8 @@ wav.o: mpg123.h readers.o: mpg123.h buffer.h common.h term.o: mpg123.h buffer.h term.h common.h +mysqlsupport.o: mysqlsupport.h mpg123.h +mysqlconfigure.o: mysqlsupport.h mpg123.h ########################################################################### ########################################################################### diff -Nur mpg123-0.59r-orig/mpg123.c mpg123-0.59r/mpg123.c --- mpg123-0.59r-orig/mpg123.c Tue Jun 15 22:21:36 1999 +++ mpg123-0.59r/mpg123.c Fri Dec 31 05:09:41 1999 @@ -27,6 +27,10 @@ #include #endif +#ifdef __FreeBSD__ +#include +#endif + #include "mpg123.h" #include "getlopt.h" #include "buffer.h" @@ -34,6 +38,9 @@ #include "version.h" +/* domi: header for MySQL support */ +#include "mysqlsupport.h" + static void usage(char *dummy); static void long_usage(char *); static void print_title(void); @@ -90,6 +97,9 @@ static void catch_interrupt(void) { intflag = TRUE; + /* domi: additional flag for MySQL to decide whether a stream has been + completely played or not */ + mysql_support_opts.int_flag = -1; } #endif @@ -322,6 +332,14 @@ } if (loptind < argc) return (argv[loptind++]); + + /* domi: get playlist entries from database, if + * query parameter (Q) was given + */ + if(mysql_support_opts.query_string || mysql_support_opts.query_all) { + return mysql_get_file(mysql_support_opts.query_string); + } + return (NULL); } @@ -509,6 +527,13 @@ {'h', "halfspeed", GLO_ARG | GLO_LONG, 0, ¶m.halfspeed, 0}, {'p', "proxy", GLO_ARG | GLO_CHAR, 0, &proxyurl, 0}, {'@', "list", GLO_ARG | GLO_CHAR, 0, &listname, 0}, + +/* domi: */ + {'Q', "query", GLO_ARG | GLO_CHAR, 0, &mysql_support_opts.query_string, 0}, + {'A', "all", 0, 0, &mysql_support_opts.query_all, -1}, + {0, "auto-insert", 0, 0, &mysql_support_opts.auto_insert, -1}, + {0, "auto-delete", 0, 0, &mysql_support_opts.auto_delete, -1}, + /* 'z' comes from the the german word 'zufall' (eng: random) */ {'z', "shuffle", 0, 0, ¶m.shuffle, 1}, {'Z', "random", 0, 0, ¶m.shuffle, 2}, @@ -780,6 +805,10 @@ _wildcard(&argc,&argv); #endif +#ifdef __FreeBSD__ + fpsetmask(0); +#endif + if(sizeof(short) != 2) { fprintf(stderr,"Ouch SHORT has size of %d bytes (required: '2')\n",(int)sizeof(short)); exit(1); @@ -812,7 +841,17 @@ exit (1); } - if (loptind >= argc && !listname && !frontend_type) + /* Get DB host, user name, passwd, table, ... */ + mysql_configure(); + + /* domi: connect to MySQL database or die */ + if((mysql_support_opts.query_string || mysql_support_opts.query_all) && !mysql_connect_to()) { + fprintf(stderr, "MySQL: Can't connect to requested RDBMS!\n"); + exit(1); + } + + /* domi: take the database as the source for playlist optionally */ + if (loptind >= argc && !listname && !frontend_type && !mysql_support_opts.query_string && !mysql_support_opts.query_all) usage(NULL); #if !defined(WIN32) && !defined(GENERIC) @@ -906,6 +945,15 @@ if(!*fname || !strcmp(fname, "-")) fname = NULL; + + if(fname && access(fname, R_OK)) { + mysql_do_auto_delete(fname); + continue; /* We can't play non-reabable _files_ so let's skip over + to the next one */ + } + if(fname) + mysql_do_auto_insert(fname); + open_stream(fname,-1); if (!param.quiet) { @@ -1019,6 +1067,10 @@ term_restore(); #endif + /* domi: if playing has been interrupted, then decrement rating + else increment */ + mysql_in_or_decrement(mysql_support_opts.int_flag ? MYSQL_DECREMENT : MYSQL_INCREMENT, fname); + if (!param.quiet) { /* * This formula seems to work at least for @@ -1093,6 +1145,12 @@ cdr_close(); break; } + + /* Exiting */ + + /* FIXME: Do this in mysql_build_playlist()!!! */ + if(mysql_support_opts.have_playlist_handle) + mysql_close_playlist_handle(); return 0; } @@ -1103,6 +1161,9 @@ fprintf(stderr,"Version %s (%s). Written and copyrights by Michael Hipp.\n", prgVersion, prgDate); fprintf(stderr,"Uses code from various people. See 'README' for more!\n"); fprintf(stderr,"THIS SOFTWARE COMES WITH ABSOLUTELY NO WARRANTY! USE AT YOUR OWN RISK!\n"); + /* domi: */ + fprintf(stderr,"MySQL support Version %s by Dominik Brettnacher \n",MYSQL_SUPPORT_VERSION); + fprintf(stderr,"Improved MySQL support Version %s by Jan-Benedict Glaw \n",MYSQL_IMPROVED_SUPPORT_VERSION); } static void usage(char *dummy) /* print syntax & exit */ @@ -1134,6 +1195,8 @@ #else fprintf(stderr," -@ f read filenames/URLs from f\n"); #endif + fprintf(stderr," -Q s search for s case-insensitive in database\n"); + fprintf(stderr," -A search for all files in database\n"); fprintf(stderr," -z shuffle play (with wildcards) -Z random play\n"); fprintf(stderr," -u a HTTP authentication string -E f Equalizer, data from file\n"); fprintf(stderr," -C enable control keys\n"); @@ -1183,6 +1246,10 @@ fprintf(o," -h --halfspeed Play every frame twice\n"); fprintf(o," -p --proxy Set WWW proxy\n"); fprintf(o," -@ --list Play songs in file-list\n"); + fprintf(o," -Q --query Search for in database\n"); + fprintf(o," -A --all Request all files from database\n"); + fprintf(o," --auto-insert Automatically add command line files to database\n"); + fprintf(o," --auto-delete Automatically remove command line files from database\n"); fprintf(o," -z --shuffle Shuffle song-list before playing\n"); fprintf(o," -Z --random full random play\n"); fprintf(o," --equalizer Exp.: scales freq. bands acrd. to 'equalizer.dat'\n"); diff -Nur mpg123-0.59r-orig/mysqlconfigure.c mpg123-0.59r/mysqlconfigure.c --- mpg123-0.59r-orig/mysqlconfigure.c Thu Jan 1 01:00:00 1970 +++ mpg123-0.59r/mysqlconfigure.c Fri Dec 31 03:06:09 1999 @@ -0,0 +1,239 @@ +/* + * char *canonicalize_file_name(char *filename); <--- free icht vergessen! + */ + +#include +#include "mysqlsupport.h" +#include "mpg123.h" + +/* + * 0 -- used configuration + * 1 -- command line options + * 2 -- environmental configuration + * 3 -- config file (~/.mpg123-mysql) + * 4 -- config file (/etc/mpg123-mysql) + * 5 -- default configuration + */ + +struct mm_conf mm_config[MYSQL_NR_CONFIGS]; + +void mysql_config_default(struct mm_conf *conf) { + conf->dbhost = NULL; + conf->set_dbhost = -1; + conf->dbport = 0; + conf->set_dbport = -1; + conf->dbname = NULL; + conf->set_dbname = -1; + conf->dbtable = NULL; + conf->set_dbtable = -1; + conf->dbuser = NULL; + conf->set_dbuser = -1; + conf->dbpasswd = NULL; + conf->set_dbpasswd = -1; + conf->dbusepasswd = 1; + conf->set_dbusepasswd = -1; +} + +void mysql_config_file(char *filename, struct mm_conf *conf) { + FILE *fp; + int items, i; + char *item[3]; + char buf[1024]; + + conf->set_dbhost = 0; + conf->set_dbport = 0; + conf->set_dbname = 0; + conf->set_dbtable = 0; + conf->set_dbuser = 0; + conf->set_dbpasswd = 0; + conf->set_dbusepasswd = 0; + + if(!filename) { + fprintf(stderr, "MySQL: NULL filename for configure!\n"); + return; + } + + if(access(filename, R_OK) && param.verbose) { + fprintf(stderr, "MySQL: Can't access file '%s' for configure!\n", filename); + return; + } + + if((fp=fopen(filename, "r")) == NULL) { + if(param.verbose) { + fprintf(stderr, "MySQL: Couldn't open config file '%s' for ", filename); + perror("reading"); + } + } else { + /* read & process!!! */ + while(fgets(buf, 1024, fp)) { + items = sscanf(buf, "%as %as %as\n", &item[0], &item[1], &item[2]); +#ifdef DEBUG_MYSQL + fprintf(stderr, "MySQL: Got config line with %i token\n", items); +#endif + if(items == 2) { + if(strcmp(item[0], "dbhost") == 0) { +#ifdef DEBUG_MYSQL + fprintf(stderr, "MySQL: Recognized dbhost=%s\n", item[1]); +#endif + if(conf->set_dbhost) { + fprintf(stderr, "MySQL: Why do you use several 'dbhost ...' lines in config file '%s'?\n", filename); + free(conf->dbhost); + } + conf->dbhost = item[1]; + conf->set_dbhost = -1; + free(item[0]); + continue; + } + if(strcmp(item[0], "dbport") == 0) { +#ifdef DEBUG_MYSQL + fprintf(stderr, "Recognized dbport=%s\n", item[1]); +#endif + if(conf->set_dbport) + fprintf(stderr, "MySQL: Why do you use several 'dbport ...' lines in config file '%s'?\n", filename); + conf->dbport = atoi(item[1]); + conf->set_dbport = -1; + free(item[0]); + free(item[1]); + continue; + } + if(strcmp(item[0], "dbname") == 0) { +#ifdef DEBUG_MYSQL + fprintf(stderr, "MySQL: Recognized dbname=%s\n", item[1]); +#endif + if(conf->set_dbname) { + fprintf(stderr, "MySQL: Why do you use several 'dbname ...' lines in config file '%s'?\n", filename); + free(conf->dbname); + } + conf->dbname = item[1]; + conf->set_dbname = -1; + free(item[0]); + continue; + } + if(strcmp(item[0], "dbtable") == 0) { +#ifdef DEBUG_MYSQL + fprintf(stderr, "MySQL: Recognized dbtable=%s\n", item[1]); +#endif + if(conf->set_dbtable) { + fprintf(stderr, "MySQL: Why do you use several 'dbtable ...' lines in config file '%s'?\n", filename); + free(conf->dbtable); + } + conf->dbtable = item[1]; + conf->set_dbtable = -1; + free(item[0]); + continue; + } + if(strcmp(item[0], "dbuser") == 0) { +#ifdef DEBUG_MYSQL + fprintf(stderr, "MySQL: Recognized dbuser=%s\n", item[1]); +#endif + if(conf->set_dbuser) { + fprintf(stderr, "MySQL: Why do you use several 'dbuser ...' lines in config file '%s'?\n", filename); + free(conf->dbuser); + } + conf->dbuser=item[1]; + conf->set_dbuser = -1; + free(item[0]); + continue; + } + if(strcmp(item[0], "dbpasswd") == 0) { +#ifdef DEBUG_MYSQL + fprintf(stderr, "MySQL: Recognized dbpasswd=%s\n", item[1]); +#endif + if(conf->set_dbpasswd) { + fprintf(stderr, "MySQL: Why do you use several 'dbpasswd ...' lines in config file '%s'?\n", filename); + free(conf->dbpasswd); + } + conf->dbpasswd=item[1]; + conf->set_dbpasswd = -1; + free(item[0]); + continue; + } + if(strcmp(item[0], "dbusepasswd") == 0) { +#ifdef DEBUG_MYSQL + fprintf(stderr, "MySQL: Recognized dbusepasswd=%s\n", item[1]); +#endif + if(conf->set_dbusepasswd) + fprintf(stderr, "MySQL: Why do you use several 'dbusepasswd ...' lines in config file '%s'?\n", filename); + if((atoi(item[1]) != 0) && (atoi(item[1]) != 1)) { + fprintf(stderr, "MySQL: Config file '%s' contains disallowed dbusepasswd value '%i'. Please use _only_ '0' or '1'.\n", filename, atoi(item[1])); + if(conf->set_dbusepasswd) { + fprintf(stderr, "MySQL: Using prior set value '%i' for dbusepasswd\n", conf->dbusepasswd); + } else { + fprintf(stderr, "MySQL: Ignoring wrong dbusepasswd line in config file '%s'\n", filename); + } + } else { + conf->dbusepasswd=atoi(item[1]); + conf->set_dbusepasswd = -1; + } + free(item[0]); + free(item[1]); + } + } /* items == 2 */ else { + /* items != 2 */ + if(items>0) { + for(i=0; iset_dbhost = 0; + conf->set_dbport = 0; + conf->set_dbname = 0; + conf->set_dbtable = 0; + conf->set_dbuser = 0; + conf->set_dbpasswd = 0; + conf->set_dbusepasswd = 0; + conf->dbpasswd = NULL; + + if(getenv("MPG123_MYSQL_DBHOST")) { + conf->dbhost = getenv("MPG123_MYSQL_DBHOST"); + conf->set_dbhost= -1; + } + if(getenv("MPG123_MYSQL_DBPORT")) { + conf->dbport = atoi(getenv("MPG123_MYSQL_DBPORT")); + conf->set_dbport= -1; + } + if(getenv("MPG123_MYSQL_DBNAME")) { + conf->dbname = getenv("MPG123_MYSQL_DBNAME"); + conf->set_dbname= -1; + } + if(getenv("MPG123_MYSQL_DBTABLE")) { + conf->dbtable = getenv("MPG123_MYSQL_DBTABLE"); + conf->set_dbtable= -1; + } + if(getenv("MPG123_MYSQL_DBUSER")) { + conf->dbuser = getenv("MPG123_MYSQL_DBUSER"); + conf->set_dbuser= -1; + } + if(getenv("MPG123_MYSQL_DBPASSWD")) { + conf->dbpasswd = getenv("MPG123_MYSQL_DBPASSWD"); + conf->set_dbpasswd= -1; + } + if(getenv("MPG123_MYSQL_DBUSEPASSWD")) { + if((atoi(getenv("MPG123_MYSQL_DBUSEPASSWD")) != 0) && (atoi(getenv("MPG123_MYSQL_DBUSEPASSWD")) != 1)) { + /* Wrong number given! */ + fprintf(stderr, "MySQL: $MPG123_MYSQL_DBUSEPASSWD is not set to '0' nor to '1'. Please correct this!\n"); + if(conf->dbpasswd) { + fprintf(stderr, "Will _use_ passwd as it is provided in environment\n"); + conf->dbusepasswd = -1; + } else { + fprintf(stderr, "Will _not use_ passwd as it is not provided in environment\n"); + conf->dbusepasswd = 0; + } + } else { + /* $MPG123_MYSQL_DBUSEPASSWD contains valid integer */ + conf->dbusepasswd = atoi(getenv("MPG123_MYSQL_DBUSEPASSWD")); + } + conf->set_dbusepasswd = -1; + } +} diff -Nur mpg123-0.59r-orig/mysqlsupport.c mpg123-0.59r/mysqlsupport.c --- mpg123-0.59r-orig/mysqlsupport.c Thu Jan 1 01:00:00 1970 +++ mpg123-0.59r/mysqlsupport.c Fri Dec 31 02:58:21 1999 @@ -0,0 +1,426 @@ +/* + * First of all, compile-time default options (configurable through + * mysqlsupport.h) are used. Then there may be a config file (which + * name may be configured in mysqlsupport.h as well; it defaults to + * ~/.mpg123-mysql) which holds additional (or better;) values. Its + * syntax is simple: + * 1. All blank lines are ignored + * 2. All leading and trailing blanks are ignored + * 2. All lines which start with '#' are ignored as well (there may be + * proceeding blanks; the line gets ignored at all if the first non- + * blank character is a '#')... + * 3. All remaining lines are in the form of + * + * without any quotes or so. + * 's are (without the ':'): + * * dbhost: + * this is the host name (either an IP address or its + * real name) + * * dbport: + * Connect through this (int) TCP/IP port to dbhost + * * dbname: + * Use this database name + * * dbtable: + * Use this table. It _has_ to have a special table layout: + * FIXME: Insert table description HERE!!! + * * dbuser: + * Use this user name to connect to MySQL RDBMS. It is also + * used in the 'user' column in the table. + * * dbpasswd: + * Use this password. Because there is no way (just right now) + * to give an empty passwd (""), you need to have a real password + * defined... + * * dbusepasswd: + * If this (int) value is != 0, a passwd will be given to + * authenticate against the RDBMS. If you provide a '0' value, + * no passwd is given (what is different to give an empty + * passwd!!!). + * 4. Anything else is a bug any might be reported to Jan-Benedict Glaw + * ... + * + * The next (and last) step to gain user information is to query for + * environment variables. They might contain exactly the same things you + * may put into your ~/.mpg123.mysql file, but they override all values + * given there. The environment variable's names are + * * MPG123_MYSQL_DBHOST + * * MPG123_MYSQL_DBPORT + * * MPG123_MYSQL_DBNAME + * * MPG123_MYSQL_DBTABLE + * * MPG123_MYSQL_DBUSER + * * MPG123_MYSQL_DBPASSWD + * * MPG123_MYSQL_DBUSEPASSWD + * + * MPG123_MYSQL_DBUSEPASSWD is way special compared to the other + * environment variables: + * + * - passwd is _used_ if + * - MPG123_MYSQL_DBUSEPASSWD != "0" --or-- + * - MPG123_MYSQL_DBUSEPASSWD set but empty + * + * - passwd is _not used_ if + * - MPG123_MYSQL_DBUSEPASSWD == "0" --or-- + * - MPG123_MYSQL_DBUSEPASSWD not set at all + * + * So if you want to have an empty passwd, you have to use it compiled + * into mpg123-mysql, or you may use it by using the environment + * variable (which I recommend to _not_ do since it is rather insecure...) + * + * That's all... + */ + +/* + * char *canonicalize_file_name(char *filename); <--- free icht vergessen! + */ + +#include +#include +#include +#include +#include +#include +#include +#include "mpg123.h" +#include "mysqlsupport.h" + +int dbplaylistpos = 0; +MYSQL mysql_playlist_handle, mysql_update_handle; +char **dbplaylist = NULL; +int dbplaylistcounter; + +struct mysql_mpg123 mysql_support_opts = { + 0, /* int_flag */ + 0, /* query_all */ + 0, /* auto_insert */ + 0, /* auto_delete */ + NULL, /* query_string */ + 0, /* have_playlist_handle */ + NULL /* conf */ +}; + +void escape_quotes(char *src, char *dst, char *quote) { + char *i, *j; + + for(i=src, j=dst; *i != '\0'; i++) { + *j = *i; + if(strncmp(j, quote, 1) == 0) { + ++j; + *j = *i; + } + ++j; + } + *j = '\0'; +} + +int mysql_connect_to(void){ + /* FIXME: Use mysql_error */ + if(mysql_init(&mysql_playlist_handle) == NULL) { + fprintf(stderr, "MySQL: Could not allocate memory for handle!\n"); + return 0; + } + + /* FIXME: Use mysql_error */ + if(mysql_real_connect(&mysql_playlist_handle, + mysql_support_opts.conf->dbhost, + mysql_support_opts.conf->dbuser, + mysql_support_opts.conf->dbusepasswd ? mysql_support_opts.conf->dbpasswd : NULL, + mysql_support_opts.conf->dbname, + mysql_support_opts.conf->dbport, + NULL, + 0) == NULL) { + fprintf(stderr, "MySQL: %s\n", mysql_error(&mysql_playlist_handle)); + return 0; + } + + mysql_support_opts.have_playlist_handle = -1; + return -1; +} + +int mysql_close_playlist_handle(void) { + if(mysql_support_opts.have_playlist_handle) { + mysql_close(&mysql_playlist_handle); + return 0; + } else { + fprintf(stderr, "\nmysql_close_playlist_handle() called, but no handle there!!!\n"); + return -1; + } +} + +int mysql_in_or_decrement(int step, char *fname) { + char *conv_fname; + char *query; + + /* + * If there is no connection there should be no action here. + * But unfortunately this is only a fix to make this patch + * work if there's no mysql support requested at command line. + * This has to be reworked (FIXME) for --auto-insert and + * --auto-delete. + * + * This needs to be reworked: We should have our _own_ db + * connection. No check whether or not there's a general handle + * actually used for the playlist! + */ + + if(!mysql_support_opts.have_playlist_handle) + return -1; + + if((conv_fname = malloc(2*(NAME_MAX+PATH_MAX+2))) == NULL) { + fprintf(stderr, "MySQL: Couldn't get memory to escape from quotes!\n"); + return -1; + } + + escape_quotes(fname,conv_fname, "'"); + + if((query = malloc(2*(NAME_MAX+PATH_MAX+2)+strlen(mysql_support_opts.conf->dbtable)+60)) == NULL) { + fprintf(stderr, "MySQL: Couldn't get memory to build query string!\n"); + free(conv_fname); + return -1; + } + + sprintf(query, "UPDATE %s set rating = rating %+i where path = '%s'", mysql_support_opts.conf->dbtable, step, conv_fname); + + if(param.verbose) + fprintf(stderr, "\nMySQL: %s\n", query); + + mysql_support_opts.int_flag = 0; + + if(mysql_query(&mysql_playlist_handle, query)) { + fprintf(stderr, "MySQL: %s\n",mysql_error(&mysql_playlist_handle)); + return -1; + } + + return 0; +} + +int mysql_do_auto_insert(char *filename) { + MYSQL insert_handle; + char *canonical_filename = NULL; + char *query_string; + + if(!filename) { + fprintf(stderr, "MySQL: mysql_do_auto_insert called without file name! Please report\n" + "this as a bug..."); + return -1; + } + + if(mysql_support_opts.auto_insert) { + canonical_filename = (char *)canonicalize_file_name(filename); + + mysql_init(&insert_handle); + if(mysql_error(&insert_handle)[0] != '\0') { + fprintf(stderr, "MySQL: Failed to do mysql_init().\n"); + fprintf(stderr, "MySQL: %s\n", mysql_error(&insert_handle)); + free(canonical_filename); + return -1; + } + + mysql_real_connect(&insert_handle, + mysql_support_opts.conf->dbhost, + mysql_support_opts.conf->dbuser, + mysql_support_opts.conf->dbpasswd, + mysql_support_opts.conf->dbname, + mysql_support_opts.conf->dbport, + NULL, + 0); + if(mysql_error(&insert_handle)[0] != '\0') { + fprintf(stderr, "MySQL: Failed to do mysql_real_connect().\n"); + fprintf(stderr, "MySQL: %s\n", mysql_error(&insert_handle)); + free(canonical_filename); + return -1; + } + + + free(canonical_filename); + } + /* select? */ + /* query: insert */ + /* close */ + return 0; +} + +int mysql_do_auto_delete(char *filename) { + fprintf(stderr, "\n\nMySQL: delete: ----->%s<-----\n\n", filename); + /* do auto-delete? */ + /* init */ + /* connect */ + /* canonical filename */ + /* select? */ + /* query: */ + /* close */ + return 0; +} + +void mysql_make_playlist(char *where) +{ + MYSQL_RES *files; + MYSQL_ROW row; + char *conv_where; + char *query; + char nullstring = '\0'; + int i = 0; + + fprintf(stderr, "------------------------> mysql_make_playlist() <------------------------\n"); + /* + * If user asks for all files in database we need to have + * an empty search string. As there is no memory allocated + * for *where in this case, we take a locally stored zero- + * terminated string of null size for this job... + */ + if(mysql_support_opts.query_all) + where = &nullstring; + + /* + * Get some amount of memory to clear out quotation marks + * used in the query string to allow to search for them as + * well... + */ + if((conv_where = malloc(2*(strlen(where)+2))) == NULL) { + fprintf(stderr, "MySQL: Couldn't get memory to escape from quotes!\n"); + exit(1); + } + + escape_quotes(where, conv_where, "\""); + + /* Now get some amount of memory to build the actual query + * string + */ + if(!(query = malloc(75 + strlen(mysql_support_opts.conf->dbtable)+strlen(conv_where)))) { + fprintf(stderr, "MySQL: Couldn't get memory to build query string!\n"); + free(conv_where); + exit(1); + } + + sprintf(query, "SELECT path FROM %s WHERE path LIKE \"%%%s%%\" ORDER BY rating DESC", + mysql_support_opts.conf->dbtable, conv_where); + + if(param.verbose) + fprintf(stderr, "MySQL: %s\n", query); + + if(mysql_query(&mysql_playlist_handle, query)) { + fprintf(stderr, "MySQL: %s\n", mysql_error(&mysql_playlist_handle)); + exit(1); + } + + if(!(files = mysql_store_result(&mysql_playlist_handle))) { + fprintf(stderr, "MySQL: Can't store query result to local memory.\n"); + fprintf(stderr, "MySQL: %s\n", mysql_error(&mysql_playlist_handle)); + exit(1); + } + + if(!mysql_num_rows(files)) { + fprintf(stderr, "MySQL: Query got no results!\n"); + exit(1); + } + + while((row = mysql_fetch_row(files))) { + if(!dbplaylist) { + if(!(dbplaylist = malloc(sizeof(char *)))) { + perror("MySQL: Can't get memory to fetch row"); + exit(1); + } + } + + if(!(dbplaylist = realloc(dbplaylist, sizeof(char *) * (i+1)))) { + perror("MySQL: Can't realloc memory"); + exit(1); + } + + if(!(dbplaylist[i] = malloc(strlen(row[0])+1))) { + perror("MySQL: Can't get memory to store file name"); + exit(1); + } + + strcpy(dbplaylist[i++], row[0]); + } + + dbplaylistcounter = i; + + if(param.verbose) + fprintf(stderr, "MySQL: %i file%s found\n", i, i != 1 ? "s" : ""); + + mysql_free_result(files); +} + +char *mysql_get_file(char *where) { + + fprintf(stderr, "------------------------> mysql_get_file(). dbplaylistpos='%i', where='%s' <------------------------\n"); + if(!dbplaylistpos) { + mysql_make_playlist(where); + } + + if(dbplaylistpos < dbplaylistcounter) { + return dbplaylist[dbplaylistpos++]; + } + + return NULL; +} + +void mysql_configure(void) { +/* struct mm_conf mm_config[NR_CONFIGS]; */ +/* + * 0 -- used configuration + * 1 -- command line options + * 2 -- environmental configuration + * 3 -- config file (~/.mpg123-mysql) + * 4 -- config file (/etc/mpg123-mysql) + * 5 -- default configuration + */ + char config_common[] = MYSQL_CONFIG_FILE; + char *config_user = NULL; + int i; + + if(getenv("HOME") && !(config_user = strdup(getenv("HOME")))) + fprintf(stderr, "MySQL: No memory to copy $HOME\n"); + + if(config_user) { + if(!(config_user = realloc(config_user, 4+ strlen(config_user) + strlen(MYSQL_USER_CONFIG_FILE)))) { + /* No memory and config_user == NULL */ + fprintf(stderr, "MySQL: Can't get memory to add user's configuration file name to $HOME path\n"); + } else { + /* Memory is available */ + strcat(config_user, MYSQL_USER_CONFIG_FILE); + } + } + + mysql_config_default( &mm_config[5]); + mysql_config_file(config_common, &mm_config[4]); + mysql_config_file(config_user, &mm_config[3]); + mysql_config_environment( &mm_config[2]); + /* mysql_config_commandline( &mm_config[1]); */ + + for(i=MYSQL_NR_CONFIGS-1; i>0; i--) { +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Reading config: i=%i\n", i); +#endif + if(mm_config[i].set_dbhost) { + mm_config[0].dbhost = mm_config[i].dbhost; + mm_config[0].set_dbhost = mm_config[i].set_dbhost; + } + if(mm_config[i].set_dbport) { + mm_config[0].dbport = mm_config[i].dbport; + mm_config[0].set_dbport = mm_config[i].set_dbport; + } + if(mm_config[i].set_dbname) { + mm_config[0].dbname = mm_config[i].dbname; + mm_config[0].set_dbname = mm_config[i].set_dbname; + } + if(mm_config[i].set_dbtable) { + mm_config[0].dbtable = mm_config[i].dbtable; + mm_config[0].set_dbtable = mm_config[i].set_dbtable; + } + if(mm_config[i].set_dbuser) { + mm_config[0].dbuser = mm_config[i].dbuser; + mm_config[0].set_dbuser = mm_config[i].set_dbuser; + } + if(mm_config[i].set_dbpasswd) { + mm_config[0].dbpasswd = mm_config[i].dbpasswd; + mm_config[0].set_dbpasswd = mm_config[i].set_dbpasswd; + } + if(mm_config[i].set_dbusepasswd) { + mm_config[0].dbusepasswd = mm_config[i].dbusepasswd; + mm_config[0].set_dbusepasswd = mm_config[i].set_dbusepasswd; + } + } + mysql_support_opts.conf = &mm_config[0]; +} + diff -Nur mpg123-0.59r-orig/mysqlsupport.h mpg123-0.59r/mysqlsupport.h --- mpg123-0.59r-orig/mysqlsupport.h Thu Jan 1 01:00:00 1970 +++ mpg123-0.59r/mysqlsupport.h Fri Dec 31 05:28:15 1999 @@ -0,0 +1,78 @@ +#ifndef _MYSQLSUPPORT_H +#define _MYSQLSUPPORT_H + +/* MySQL server host or NULL for localhost */ +#define MYSQL_HOST NULL +/* MySQL login name or NULL for none */ +#define MYSQL_USER NULL +/* MySQL password or NULL for none */ +#define MYSQL_PASSWD NULL +/* MySQL database to be used (must not be NULL) */ +#define MYSQL_DB NULL +/* MySQL table to be used */ +#define MYSQL_TABLE NULL + +/* Commpn configuration file */ +#define MYSQL_CONFIG_FILE "/etc/mpg123-mysql" +/* Per-user configuration file (in $HOME/ ) */ +#define MYSQL_USER_CONFIG_FILE "/.mpg123-mysql" + +/* values for rating increment and decrement */ +#define MYSQL_INCREMENT 2 +#define MYSQL_DECREMENT (-3) + +/* nothing has usually to be changed below */ + +#include +#include +#include +#include + +#define MYSQL_SUPPORT_VERSION "0.4" +#define MYSQL_IMPROVED_SUPPORT_VERSION "19991231051850" +#define MYSQL_NR_CONFIGS 6 + +/* #define MYSQL_DEBUG */ + +struct mm_conf { + char *dbhost; + int set_dbhost; + unsigned int dbport; /* Yes, this is arch specific. ...but MySQL docs tell to do so;( */ + int set_dbport; + char *dbname; + int set_dbname; + char *dbtable; + int set_dbtable; + char *dbuser; + int set_dbuser; + char *dbpasswd; + int set_dbpasswd; + int dbusepasswd; + int set_dbusepasswd; +}; + +struct mysql_mpg123 { + int int_flag; + int query_all; + int auto_insert; + int auto_delete; + char *query_string; + int have_playlist_handle; + struct mm_conf *conf; +}; + +extern struct mysql_mpg123 mysql_support_opts; +extern struct mm_conf mm_config[]; +extern void mysql_configure(void); +extern void mysql_config_default(struct mm_conf *); +extern void mysql_config_file(char *, struct mm_conf *); +extern void mysql_config_environment(struct mm_conf *); +extern int mysql_connect_to(void); +extern int mysql_close_playlist_handle(void); +extern int mysql_in_or_decrement(int, char*); +extern void mysql_make_playlist(char *); +extern char *mysql_get_file(char *); +extern int mysql_do_auto_insert(char *); /* -1 if error, 0 if file is in DB afterwards */ +extern int mysql_do_auto_delete(char *); /* -1 if error, 0 if file is no longer in DB afterwards */ + +#endif /* !_MYSQLSUPPORT_H */