diff -Nur mpg123-0.59r-orig/ChangeLog.jbglaw mpg123-0.59r/ChangeLog.jbglaw --- mpg123-0.59r-orig/ChangeLog.jbglaw Thu Jan 1 01:00:00 1970 +++ mpg123-0.59r/ChangeLog.jbglaw Sat Jan 15 11:08:24 2000 @@ -0,0 +1,116 @@ +Jan-Benedict Glaw , Hamsterweg 3, 33335 Gütersloh, Germany + + +1999122503: + - Fixed broken "Interrupt!" for all songs played after one + that has actually been interrupted. + - Fixed possible buffer overflows during query creation. + +19991226030 + - Fixed remaining possible buffer overflows while creating + query strings. + - Fixed broken -Q and -QQ options (by adding --queryall option). + - Pro-forma added --auto-add and --auto-remove. + - Fixed possibility of recursively #include'ing mysqlsupport.h + by adding standard "#ifndef _MYSQLSUPPORT_H; #define ..; ...; + #ifndef"... + +19991226181848: + - Re-ordered call to mysql_connect_to to allow connection + _only_ if we need to. + - Re-ordered code for building playlist to allow both + command line given file names _and_ paths from database. + - Fixed short bug in mysql_in_and_decrement to not crash + if there's no database connection. + +19991227022320: + - Removed unused *MYSQL struct + - Sadly we now SIGSEGVault;( + - Query strings are now _only_ written is param.verbose is set + +19991228033303: + - Moved all (okay, most...) mysql-specific options into a + struct to ease maintainance + - mpg123-mysql is now capable of _only_ playing command line + given MP3s by adding another option (have_playlist_handle) + to that mentioned struct... + - We now close the playlist connection on program exit properly;) + - Added some more debugging stuff (-> needs to be removed at some + give time...) + - Framework for auto-inserting/auto-removing files should now + be complete + +19991228134618: + - Added framework for different users + - Very super-alpha support (framework...) for a config file + +19991228170317: + - Bug-fixed a sure SIGSEGV-fault at startup when trying to read + the config file + - Added config file support (-> but not functional right now) + - Bug-fixed a sure SIGSEGV-fault at startup when trying to read + the config file + - Added config file support (-> but not functional right now) + +19991228202715: + - Config-Support: Configuration through compile-time options + work like before. Configuration through config file doesn't + work yet, but configuration through environment variables + works just like a charm;) It's completely configurable through + the environment yet! But passwd's in environment variables are + not very safe;( + +19991229004707: + - Started to code --auto-insert function. Seems to be okay so + far, but I'm some lines of code away to do the actual query... + - Cleande all that mysql related stuff. We now use 0 and -1 + to show up "fail" and "okay". The advantage: + if(flag) ...; + and + if(!flag) ...; + will now work;) It's much more readable! + - most bugs seem to be gone away;-> + +19991230232653: + - Don't know which fixes I did;) + - Configurable now by + - /etc/mp123-mysql + - ~/.mpg123-mysql + - environment variables + - conmiled-in defaults + - Seems to work + +19991231051850: + - First public release;) + - Tons of cleanups + - Configuration process can now easily be extended + +20000104135330: + - Many cleanups + - SQL UPDATEs now use user=dbtableuser + - It compiles & runs again;) (-> it didn't any longer after + changins some important things...) + - Return values of some older mysql support functions are + corrected + +20000106053316: + - dbtableuser (aka playlist;) is now implemented for --auto-update + - some segfaults removed;) + - made updating the rating value conditional + - added --auto-update and --mysql + +20000108103113: + - added configuration through command line + - worked around a bug in getlopt.c:performoption(): + you really have to provide a variables address even if + you only want a function to be called. Grrrrr.... + - Compiles and works again;) + +20000115083348: + - fixed bug in my_canonicalize_filename() + - mysql_increment_or_decrement() now fully functional (fixed + datableuser use) + +20000115110703: + - --auto-insert, --auto-update and --auto-delete are now + fully functional;) 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 Sat Jan 8 07:42:49 2000 @@ -121,7 +121,7 @@ -DUSE_3DNOW -DREAD_MMAP -DOSS -DTERM_CONTROL\ -Wall -O2 -m486 \ -fomit-frame-pointer -funroll-all-loops \ - -finline-functions -ffast-math' \ + -finline-functions -ffast-math -g' \ mpg123-make linux-i486: @@ -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/TODO.jbglaw mpg123-0.59r/TODO.jbglaw --- mpg123-0.59r-orig/TODO.jbglaw Thu Jan 1 01:00:00 1970 +++ mpg123-0.59r/TODO.jbglaw Sat Jan 15 11:07:38 2000 @@ -0,0 +1,19 @@ +Jan-Benedict Glaw , Hamsterweg 3, 33335 Gütersloh, Germany + + + +mpg123-mysql patch +================== + +TODO +~~~~ +- Add URL support for database paths (Don't check any URL when inserting + it into playlist...) + +- Extend query options: + - allow Artist/Title/Album/Year/Origin search + - hold any ID3 tags in DB + +- Fix configuration througt config files, as there mustn't be any blanks + +- Need to look through compile-time defaults set in mysqlsupport.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 Thu Jan 13 12:44:29 2000 @@ -27,6 +27,10 @@ #include #endif +#ifdef __FreeBSD__ +#include +#endif + #include "mpg123.h" #include "getlopt.h" #include "buffer.h" @@ -34,6 +38,14 @@ #include "version.h" +/* domi: header for MySQL support */ +#include "mysqlsupport.h" +/* + * Since there is something I consider to be a bug in the + * getlongopt routines, we need to have this ugly variable;( + */ +long dummy; + static void usage(char *dummy); static void long_usage(char *); static void print_title(void); @@ -90,6 +102,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_opts.int_flag = -1; } #endif @@ -322,6 +337,14 @@ } if (loptind < argc) return (argv[loptind++]); + + /* domi: get playlist entries from database, if + * query parameter (Q) was given + */ + if(mysql_opts.query_string || mysql_opts.query_all) { + return mysql_get_file(mysql_opts.query_string); + } + return (NULL); } @@ -509,6 +532,23 @@ {'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_opts.query_string, 0}, + {'A', "all", 0, 0, &mysql_opts.query_all, -1}, + {0, "auto-update", 0, 0, &mysql_opts.auto_update, -1}, + {0, "auto-insert", 0, 0, &mysql_opts.auto_insert, -1}, + {0, "auto-delete", 0, 0, &mysql_opts.auto_delete, -1}, + {0, "mysql", 0, 0, &mysql_opts.mysql, -1}, + {0, "dbhost", GLO_ARG | GLO_CHAR, &mm_set_dbhost, &dummy, 0}, + {0, "dbport", GLO_ARG | GLO_NUM, &mm_set_dbport, &dummy, 0}, + {0, "dbname", GLO_ARG | GLO_CHAR, &mm_set_dbname, &dummy, 0}, + {0, "dbtable", GLO_ARG | GLO_CHAR, &mm_set_dbtable, &dummy, 0}, + {0, "dbuser", GLO_ARG | GLO_CHAR, &mm_set_dbuser, &dummy, 0}, + {0, "dbtableuser", GLO_ARG | GLO_CHAR, &mm_set_dbtableuser, &dummy, 0}, + {0, "dbpasswd", GLO_ARG | GLO_CHAR, &mm_set_dbpasswd, &dummy, 0}, + {0, "dbusepasswd", GLO_ARG | GLO_NUM, &mm_set_dbusepasswd, &dummy, 0}, + /* '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 +820,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 +856,14 @@ exit (1); } - if (loptind >= argc && !listname && !frontend_type) + /* Get DB host, user name, passwd, table, ... */ + mysql_configure(); +#ifdef MYSQL_DEBUG + mysql_dump_configuration(); +#endif + + /* domi: take the database as the source for playlist optionally */ + if (loptind >= argc && !listname && !frontend_type && !mysql_opts.query_string && !mysql_opts.query_all) usage(NULL); #if !defined(WIN32) && !defined(GENERIC) @@ -906,6 +957,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 +1079,9 @@ term_restore(); #endif + if(mysql_increment_or_decrement(mysql_opts.int_flag ? MYSQL_DECREMENT : MYSQL_INCREMENT, fname) && param.verbose) + fprintf(stderr, "MySQL: There was a problem updating the rating value for file '%s'\n", fname); + if (!param.quiet) { /* * This formula seems to work at least for @@ -1093,7 +1156,9 @@ cdr_close(); break; } - + + /* Exiting */ + return 0; } @@ -1103,6 +1168,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 +1202,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 +1253,20 @@ 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-update Automatically updates the actual file's rating value\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," --mysql Activates all four options above for general-purpose use;)\n"); + fprintf(o," --dbhost Use this computer as MySQL server\n"); + fprintf(o," --dbport Use this port to connect to MySQL Server\n"); + fprintf(o," --dbname Use this database name\n"); + fprintf(o," --dbtable Use this table\n"); + fprintf(o," --dbuser Use this user name\n"); + fprintf(o," --dbtableuser Use this user name for table entries (aka playlist;)\n"); + fprintf(o," --dbpasswd Use this passwd for database server\n"); + fprintf(o," --dbusepasswd n=1: use passwd at all n=0: don't use a passwd at all\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 Sat Jan 8 09:50:21 2000 @@ -0,0 +1,465 @@ +/* + * 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->dbtableuser = NULL; + conf->set_dbtableuser = -1; + conf->dbpasswd = NULL; + conf->set_dbpasswd = -1; + conf->dbusepasswd = 1; + conf->set_dbusepasswd = -1; +} + +void mm_set_dbhost(char *arg) { + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbhost = arg; + mm_config[MYSQL_CONFIG_ENVIRONMENT].set_dbhost = -1; +} +void mm_set_dbport(char *arg) { + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbport = atoi(arg); + mm_config[MYSQL_CONFIG_ENVIRONMENT].set_dbhost = -1; + if(mm_config[MYSQL_CONFIG_ENVIRONMENT].dbport != 1 && + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbport != 0) { + fprintf(stderr, "MySQL: Bogus dbport value! Please use only 0 or 1!\n"); + fprintf(stderr, "MySQL: Setting dboprt to 1\n"); + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbport = -1; + } +} +void mm_set_dbname(char *arg) { + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbname = arg; + mm_config[MYSQL_CONFIG_ENVIRONMENT].set_dbname = -1; +} +void mm_set_dbtable(char *arg) { + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbtable = arg; + mm_config[MYSQL_CONFIG_ENVIRONMENT].set_dbtable = -1; +} +void mm_set_dbuser(char *arg) { + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbuser = arg; + mm_config[MYSQL_CONFIG_ENVIRONMENT].set_dbuser = -1; +} +void mm_set_dbtableuser(char *arg) { + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbtableuser = arg; + mm_config[MYSQL_CONFIG_ENVIRONMENT].set_dbtableuser = -1; +} +void mm_set_dbpasswd(char *arg) { + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbpasswd = arg; + mm_config[MYSQL_CONFIG_ENVIRONMENT].set_dbpasswd = -1; +} +void mm_set_dbusepasswd(char *arg) { + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbusepasswd = atoi(arg); + mm_config[MYSQL_CONFIG_ENVIRONMENT].set_dbusepasswd = -1; + if(mm_config[MYSQL_CONFIG_ENVIRONMENT].dbusepasswd != 1 && + mm_config[MYSQL_CONFIG_ENVIRONMENT].dbusepasswd != 0) { + fprintf(stderr, "MySQL: Bogus dbusepasswd value! Please use only 0 or 1!\n"); + fprintf(stderr, "MySQL: Setting dbusepasswd to 1\n"); + mm_config[MYSQL_CONFIG_ENVIRONMENT].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_dbtableuser = 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 MYSQL_DEBUG + fprintf(stderr, "MySQL: Got config line with %i token\n", items); +#endif + if(items == 2) { + if(strcmp(item[0], "dbhost") == 0) { +#ifdef MYSQL_DEBUG + 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 MYSQL_DEBUG + fprintf(stderr, "MySQL: 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 MYSQL_DEBUG + 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 MYSQL_DEBUG + 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 MYSQL_DEBUG + 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], "dbtableuser") == 0) { +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Recognized dbtableuser=%s\n", item[1]); +#endif + if(conf->set_dbtableuser) { + fprintf(stderr, "MySQL: Why do you use several 'dbtableuser ...' lines in config file '%s'?\n", filename); + free(conf->dbtableuser); + } + conf->dbtableuser = item[1]; + conf->set_dbtableuser = -1; + free(item[0]); + continue; + } + if(strcmp(item[0], "dbpasswd") == 0) { +#ifdef MYSQL_DEBUG + 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 MYSQL_DEBUG + 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_dbtableuser = 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; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Found MPG123_MYSQL_DBHOST=%s in environment\n", conf->dbhost); +#endif + } + if(getenv("MPG123_MYSQL_DBPORT")) { + conf->dbport = atoi(getenv("MPG123_MYSQL_DBPORT")); + conf->set_dbport= -1; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Found MPG123_MYSQL_DBPORT=%i in environment\n", conf->dbport); +#endif + } + if(getenv("MPG123_MYSQL_DBNAME")) { + conf->dbname = getenv("MPG123_MYSQL_DBNAME"); + conf->set_dbname= -1; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Found MPG123_MYSQL_DBNAME=%s in environment\n", conf->dbname); +#endif + } + if(getenv("MPG123_MYSQL_DBTABLE")) { + conf->dbtable = getenv("MPG123_MYSQL_DBTABLE"); + conf->set_dbtable= -1; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Found MPG123_MYSQL_DBTABLE=%s in environment\n", conf->dbtable); +#endif + } + if(getenv("MPG123_MYSQL_DBUSER")) { + conf->dbuser = getenv("MPG123_MYSQL_DBUSER"); + conf->set_dbuser= -1; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Found MPG123_MYSQL_DBUSER=%s in environment\n", conf->dbuser); +#endif + } + if(getenv("MPG123_MYSQL_DBTABLEUSER")) { + conf->dbtableuser = getenv("MPG123_MYSQL_DBTABLEUSER"); + conf->set_dbtableuser= -1; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Found MPG123_MYSQL_DBTABLEUSER=%s in environment\n", conf->dbtableuser); +#endif + } + if(getenv("MPG123_MYSQL_DBPASSWD")) { + conf->dbpasswd = getenv("MPG123_MYSQL_DBPASSWD"); + conf->set_dbpasswd= -1; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Found MPG123_MYSQL_DBPASSWD=%s in environment\n", conf->dbpasswd); +#endif + } + if(getenv("MPG123_MYSQL_DBUSEPASSWD")) { +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Found MPG123_MYSQL_DBUSEPASSWD in environment\n"); +#endif + 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, "MySQL: Will _use_ passwd as it is provided in environment\n"); + conf->dbusepasswd = -1; + } else { + fprintf(stderr, "MySQL: 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")); +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Found MPG123_MYSQL_DBUSEPASSWD=%i in environment\n", conf->dbusepasswd); +#endif + } + conf->set_dbusepasswd = -1; + } +} + +#ifdef MYSQL_DEBUG +void mysql_dump_configuration(void) { + fprintf(stderr, "MySQL: dbhost = \"%s\"\n", mysql_opts.conf->dbhost); + fprintf(stderr, "MySQL: set_dbhost = \"%i\"\n", mysql_opts.conf->set_dbhost); + fprintf(stderr, "MySQL: dbport = \"%i\"\n", mysql_opts.conf->dbport); + fprintf(stderr, "MySQL: set_dbport = \"%i\"\n", mysql_opts.conf->set_dbport); + fprintf(stderr, "MySQL: dbname = \"%s\"\n", mysql_opts.conf->dbname); + fprintf(stderr, "MySQL: set_dbname = \"%i\"\n", mysql_opts.conf->set_dbname); + fprintf(stderr, "MySQL: dbtable = \"%s\"\n", mysql_opts.conf->dbtable); + fprintf(stderr, "MySQL: set_dbtable = \"%i\"\n", mysql_opts.conf->set_dbtable); + fprintf(stderr, "MySQL: dbuser = \"%s\"\n", mysql_opts.conf->dbuser); + fprintf(stderr, "MySQL: set_dbuser = \"%i\"\n", mysql_opts.conf->set_dbuser); + fprintf(stderr, "MySQL: dbtableuser = \"%s\"\n", mysql_opts.conf->dbtableuser); + fprintf(stderr, "MySQL: set_dbtableuser = \"%i\"\n", mysql_opts.conf->set_dbtableuser); + fprintf(stderr, "MySQL: dbpasswd = \"%s\"\n", mysql_opts.conf->dbpasswd); + fprintf(stderr, "MySQL: set_dbpasswd = \"%i\"\n", mysql_opts.conf->set_dbpasswd); + fprintf(stderr, "MySQL: dbusepasswd = \"%i\"\n", mysql_opts.conf->dbusepasswd); + fprintf(stderr, "MySQL: set_dbusepasswd = \"%i\"\n", mysql_opts.conf->set_dbusepasswd); + return; +} +#endif + +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); + } + } + + /* Initialize configuration tables */ + 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]); */ + + /* Check for --mysql option */ + if(mysql_opts.mysql) { + mysql_opts.query_all = -1; + mysql_opts.auto_insert = -1; + mysql_opts.auto_update = -1; + mysql_opts.auto_delete = -1; + } + + /* Merge all configuration tables */ + 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; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Setting mm_config[0].dbhost=\"%s\" from mm_config[%i].dbhost\n", mm_config[i].dbhost, i); +#endif + } + if(mm_config[i].set_dbport) { + mm_config[0].dbport = mm_config[i].dbport; + mm_config[0].set_dbport = mm_config[i].set_dbport; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Setting mm_config[0].dbport=\"%i\" from mm_config[%i].dbport\n", mm_config[i].dbport, i); +#endif + } + if(mm_config[i].set_dbname) { + mm_config[0].dbname = mm_config[i].dbname; + mm_config[0].set_dbname = mm_config[i].set_dbname; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Setting mm_config[0].dbname=\"%s\" from mm_config[%i].dbname\n", mm_config[i].dbname, i); +#endif + } + if(mm_config[i].set_dbtable) { + mm_config[0].dbtable = mm_config[i].dbtable; + mm_config[0].set_dbtable = mm_config[i].set_dbtable; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Setting mm_config[0].dbtable=\"%s\" from mm_config[%i].dbtable\n", mm_config[i].dbtable, i); +#endif + } + if(mm_config[i].set_dbuser) { + mm_config[0].dbuser = mm_config[i].dbuser; + mm_config[0].set_dbuser = mm_config[i].set_dbuser; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Setting mm_config[0].dbuser=\"%s\" from mm_config[%i].dbuser\n", mm_config[i].dbuser, i); +#endif + } + if(mm_config[i].set_dbtableuser) { + mm_config[0].dbtableuser = mm_config[i].dbtableuser; + mm_config[0].set_dbtableuser = mm_config[i].set_dbtableuser; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Setting mm_config[0].dbtableuser=\"%s\" from mm_config[%i].dbtableuser\n", mm_config[i].dbtableuser, i); +#endif + } + if(mm_config[i].set_dbpasswd) { + mm_config[0].dbpasswd = mm_config[i].dbpasswd; + mm_config[0].set_dbpasswd = mm_config[i].set_dbpasswd; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Setting mm_config[0].dbpasswd=\"%s\" from mm_config[%i].dbpasswd\n", mm_config[i].dbpasswd, i); +#endif + } + if(mm_config[i].set_dbusepasswd) { + mm_config[0].dbusepasswd = mm_config[i].dbusepasswd; + mm_config[0].set_dbusepasswd = mm_config[i].set_dbusepasswd; +#ifdef MYSQL_DEBUG + fprintf(stderr, "MySQL: Setting mm_config[0].dbusepasswd=\"%i\" from mm_config[%i].dbusepasswd\n", mm_config[i].dbusepasswd, i); +#endif + } + } + + mysql_opts.conf = &mm_config[0]; +} 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 Sat Jan 15 11:05:34 2000 @@ -0,0 +1,576 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "mpg123.h" +#include "mysqlsupport.h" + +int dbplaylistpos = 0; +char **dbplaylist = NULL; +int dbplaylistcounter; +int mysql_have_playlist_handle = 0; + +struct mysql_mpg123 mysql_opts = { + 0, /* int_flag */ + 0, /* query_all */ + 0, /* auto_update */ + 0, /* auto_insert */ + 0, /* auto_delete */ + 0, /* mysql */ + NULL, /* query_string */ + {}, /* handle */ + NULL /* conf */ +}; + +/* + * This function is to be removed right after I removed their + * crappy use from other functions! + */ +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'; +} + +/* + * char *my_canonicalize_filename(char *filename) + * + * Use: + * Returns the canonical file name of "filename". + * + * Return Value: + * - NULL on error + * - Canonical file name else + * + * Problems: + * - Grrr... Each system uses its own internal version + * of something like "canonicalize_filename" or "realpath", + * but they are all to be used in defferent ways so this + * is at all some kind of a large select statement;( + */ +char *my_canonicalize_filename(char *filename) { + char *local_return; +#if defined __USE_GNU + static char *last_filename = NULL; + + if(last_filename) + free(last_filename); + + local_return = last_filename = canonicalize_file_name(filename); +#else +# if defined __USE_BSD || defined __USE_XOPEN_EXTENDED + static char last_filename[MAXPATHLEN]; + char *temp; + + temp = realpath(filename, last_filename); + + local_return = (temp? last_filename: NULL); +# else +# warning "Your architecture does not provide relapath()" +# warning "nor canonicalize_file_name(). Please report this" +# warning "to Jan-Benedict Glaw to find" +# warning "a solution. I'll return a pointer to the original" +# warning "parameter but this is maybe a really bad idea but" +# warning "we will see wheather or not this is okay for you;)" + local_return = filename; +# endif +#endif +#ifdef MYSQL_DEBUG + if(param.verbose) { + fprintf(stderr, "MySQL: In my_canonicalize_filename():\n"); + fprintf(stderr, "MySQL: \tGot:\t'%s'\n", filename); + fprintf(stderr, "MySQL: \tGave:\t'%s'\n", local_return? local_return: ""); + } +#endif + return local_return; +} + +int mysql_connect_handle(void){ + /* 0 if okay, (-1) or error */ + + if(!mysql_opts.conf->dbname) + return -1; + if(!mysql_opts.conf->dbtable) + return -1; + if(!mysql_opts.conf->dbhost) + return -1; + + if(!mysql_init(&mysql_opts.handle)) { + fprintf(stderr, "MySQL: In mysql_connect_handle():\n"); + fprintf(stderr, "MySQL: \t%s\n", mysql_error(&mysql_opts.handle)); + return -1; + } + + if(!mysql_real_connect(&mysql_opts.handle, + mysql_opts.conf->dbhost, + mysql_opts.conf->dbuser, + mysql_opts.conf->dbusepasswd? mysql_opts.conf->dbpasswd: NULL, + mysql_opts.conf->dbname, + mysql_opts.conf->dbport, + NULL, + 0)) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_connect_handle():\n"); + fprintf(stderr, "MySQL: \t%s\n", mysql_error(&mysql_opts.handle)); + } + return -1; + } + + return 0; +} + +void mysql_close_handle(void) { + mysql_close(&mysql_opts.handle); +} + +/* + * int mysql_check_file(char *filename) + * + * Use: + * - Check wheather or not "filename" is inserted (with the actually used + * "dbtableuser" user name) or not + * Return: + * - 0 if file is inserted + * - (-1) if file is not inserted or if any problem occured + * Bugs: + * - Ugly return values... + * - Not yet completely implemented + * - Leaks memory;) + */ +int mysql_check_file(char *filename) { + char *query, *end; + MYSQL_RES *result; + + if(!filename) + return -1; + if(strlen(filename) == 0) + return -1; + if(!mysql_opts.conf->dbtable) + return -1; + + if(!(query = end = (char *)malloc(60 + + 2 * strlen(filename) + + (mysql_opts.conf->dbtableuser? + 2 * strlen(mysql_opts.conf->dbtableuser): + 6) + + strlen(mysql_opts.conf->dbtable) + ))) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_check_file():\n"); + fprintf(stderr, "MySQL: \tCouldn't get memory for query string\n"); + } + return -1; + } + + end += sprintf(end, "SELECT * FROM %s WHERE path='", mysql_opts.conf->dbtable); + end += mysql_escape_string(end, filename, strlen(filename)); + *end++ = '\''; + *end = 0; + end += sprintf(end, " AND user="); + if(mysql_opts.conf->dbtableuser) { + *end++ = '\''; + end += mysql_escape_string(end, mysql_opts.conf->dbtableuser, strlen(mysql_opts.conf->dbtableuser)); + *end++ = '\''; + } else + end += sprintf(end, "NULL"); + *end++ = 0; + + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_check_file():\n"); + fprintf(stderr, "MySQL: \t%s\n", query); + } + + if(mysql_connect_handle()) { + free(query); + return -1; + } + + if(mysql_query(&mysql_opts.handle, query)) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_check_file():\n"); + fprintf(stderr, "MySQL: \t%s\n", mysql_error(&mysql_opts.handle)); + } + free(query); + return -1; + } + + if(!(result = mysql_store_result(&mysql_opts.handle))) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_check_file():\n"); + fprintf(stderr, "MySQL: \t%s\n", mysql_error(&mysql_opts.handle)); + } + free(query); + return -1; + } + + free(query); + + if(mysql_num_rows(result) > 0) { + mysql_close_handle(); + if(param.verbose) + fprintf(stderr, "MySQL: \tFile is there\n"); + return 0; + } else { + mysql_close_handle(); + if(param.verbose) + fprintf(stderr, "MySQL: \tFile is NOT there\n"); + return -1; + } +} + +int mysql_increment_or_decrement(int step, char *filename) { + /* 0 if okay, (-1) on error */ + + char *query, *end; + char *our_filename; + + mysql_opts.int_flag = 0; + fprintf(stderr, "\n"); + + if(!mysql_opts.auto_update) + return 0; + + if(!(our_filename = my_canonicalize_filename(filename))) + return -1; + + if(strlen(our_filename) == 0) { + fprintf(stderr, "MySQL: In mysql_in_or_decrement():\n"); + fprintf(stderr, "MySQL: \tCalled with NULL filename\n"); + return -1; + } + if(mysql_check_file(our_filename)) + return -1; + + if(mysql_connect_handle()) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_in_or_decrement():\n"); + fprintf(stderr, "MySQL: \tFailed to connect to RDBMS\n"); + } + return -1; + } + + if(!(mysql_opts.conf->dbtable)) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_in_or_decrement():\n"); + fprintf(stderr, "MySQL: \tThere is no dbtable set. You _need_ to do that!!!\n"); + } + mysql_close_handle(); + return -1; + } + + if(!(query = end = (char *)malloc(100 + + 2 * strlen(our_filename) + + strlen(mysql_opts.conf->dbtable) + + (mysql_opts.conf->dbtableuser? + 2 * strlen(mysql_opts.conf->dbtableuser): + 6) + ))) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_in_or_decrement():\n"); + fprintf(stderr, "MaSQL: \tCouldn't get memory for query string\n"); + } + mysql_close_handle(); + return -1; + } + + end += sprintf(query, "UPDATE %s SET rating=rating%+i WHERE user=", + mysql_opts.conf->dbtable, + step); + + if(mysql_opts.conf->dbtableuser) { + *end++ = '\''; + end += mysql_escape_string(end, mysql_opts.conf->dbtableuser, strlen(mysql_opts.conf->dbtableuser)); + *end++ = '\''; + } else + end += sprintf(end, "NULL"); + + end += sprintf(end, " AND path='"); + + end += mysql_escape_string(end, our_filename, strlen(our_filename)); + *end++ = '\''; + *end++ = 0; + + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_increment_or_decrement():\n"); + fprintf(stderr, "MySQL: \t%s\n", query); + } + + if(mysql_query(&mysql_opts.handle, query)) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_in_or_decrement():\n"); + fprintf(stderr, "MySQL: \tProblem during query:\n"); + fprintf(stderr, "MySQL: \t%s\n", mysql_error(&mysql_opts.handle)); + } + free(query); + mysql_close_handle(); + return -1; + } + + mysql_close_handle(); + free(query); + + return 0; +} + +int mysql_do_auto_insert(char *filename) { + char *canonical_filename; + char *query, *end; + + if(!mysql_opts.auto_insert) + return 0; + + if(!filename) + return -1; + + if(strlen(filename) == 0) + return -1; + + if(!(canonical_filename = my_canonicalize_filename(filename))) + return -1; + + if(!mysql_check_file(canonical_filename)) + return 0; /* already in DB */ + + if(mysql_connect_handle()) + return -1; + + if(!(query = end = (char *)malloc(100 + + 2 * strlen(canonical_filename) + + strlen(mysql_opts.conf->dbtable) + + (mysql_opts.conf->dbtableuser? + 2 * strlen(mysql_opts.conf->dbtableuser): + 6) + ))) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_do_auto_insert():\n"); + fprintf(stderr, "MySQL: \tCouldn't get memory for query string\n"); + } + mysql_close_handle(); + return -1; + } + + end += sprintf(query, "INSERT INTO %s (rating, user, path) VALUES (0, ", mysql_opts.conf->dbtable); + + if(mysql_opts.conf->dbtableuser) { + *end++ = '\''; + end += mysql_escape_string(end, mysql_opts.conf->dbtableuser, strlen(mysql_opts.conf->dbtableuser)); + *end++ = '\''; + } else + end += sprintf(end, "NULL"); + + end += sprintf(end, ", "); + + *end++ = '\''; + end += mysql_escape_string(end, canonical_filename, strlen(canonical_filename)); + *end++ = '\''; + end += sprintf(end, ")"); + + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_do_auto_insert():\n"); + fprintf(stderr, "MySQL: \t%s\n", query); + } + + if(mysql_query(&mysql_opts.handle, query)) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_do_auto_insert():\n"); + fprintf(stderr, "MySQL: \tProblem during query:\n"); + fprintf(stderr, "MySQL: \t%s\n", mysql_error(&mysql_opts.handle)); + } + free(query); + mysql_close_handle(); + return -1; + } + + free(query); + mysql_close_handle(); + return 0; +} + +int mysql_do_auto_delete(char *filename) { + char *query, *end; + + if(!mysql_opts.auto_delete) + return 0; + + if(!filename) + return -1; + + if(strlen(filename) == 0) + return -1; + + if(mysql_check_file(filename)) + return 0; /* wasn't in DB */ + + if(mysql_connect_handle()) + return -1; + + if(!(query = end = (char *)malloc(100 + + 2 * strlen(filename) + + strlen(mysql_opts.conf->dbtable) + + (mysql_opts.conf->dbtableuser? + 2 * strlen(mysql_opts.conf->dbtableuser): + 6) + ))) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_do_auto_delete():\n"); + fprintf(stderr, "MySQL: \tCouldn't get memory for query string\n"); + } + mysql_close_handle(); + return -1; + } + + end += sprintf(query, "DELETE FROM %s WHERE user=", mysql_opts.conf->dbtable); + + if(mysql_opts.conf->dbtableuser) { + *end++ = '\''; + end += mysql_escape_string(end, mysql_opts.conf->dbtableuser, strlen(mysql_opts.conf->dbtableuser)); + *end++ = '\''; + } else + end += sprintf(end, "NULL"); + + end += sprintf(end, " AND path="); + + *end++ = '\''; + end += mysql_escape_string(end, filename, strlen(filename)); + *end++ = '\''; + *end = 0; + + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_do_auto_delete():\n"); + fprintf(stderr, "MySQL: \t%s\n", query); + } + + if(mysql_query(&mysql_opts.handle, query)) { + if(param.verbose) { + fprintf(stderr, "MySQL: In mysql_do_auto_delete():\n"); + fprintf(stderr, "MySQL: \tProblem during query:\n"); + fprintf(stderr, "MySQL: \t%s\n", mysql_error(&mysql_opts.handle)); + } + free(query); + mysql_close_handle(); + return -1; + } + + free(query); + mysql_close_handle(); + 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; + + /* + * 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_opts.query_all) + where = &nullstring; + + if(mysql_connect_handle()) + return; + + /* + * 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_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_opts.conf->dbtable, conv_where); + + if(param.verbose) + fprintf(stderr, "MySQL: %s\n", query); + + if(mysql_query(&mysql_opts.handle, query)) { + fprintf(stderr, "MySQL: %s\n", mysql_error(&mysql_opts.handle)); + exit(1); + } + + if(!(files = mysql_store_result(&mysql_opts.handle))) { + fprintf(stderr, "MySQL: Can't store query result to local memory.\n"); + fprintf(stderr, "MySQL: %s\n", mysql_error(&mysql_opts.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); + mysql_close_handle(); + + return; +} + +char *mysql_get_file(char *where) { + if(!dbplaylistpos) { + mysql_make_playlist(where); + } + + if(dbplaylistpos < dbplaylistcounter) { + return dbplaylist[dbplaylistpos++]; + } + + return NULL; +} 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 Sat Jan 15 11:08:46 2000 @@ -0,0 +1,93 @@ +#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) + +#define MYSQL_DEBUG + +/* nothing has usually to be changed below */ + +#include +#include +#include +#include + +#define MYSQL_SUPPORT_VERSION "0.4" +#define MYSQL_IMPROVED_SUPPORT_VERSION "20000115110703" +#define MYSQL_NR_CONFIGS 6 +#define MYSQL_CONFIG_ENVIRONMENT 1 + +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 *dbtableuser; + int set_dbtableuser; + char *dbpasswd; + int set_dbpasswd; + int dbusepasswd; + int set_dbusepasswd; +}; + +struct mysql_mpg123 { + int int_flag; + int query_all; + int auto_update; + int auto_insert; + int auto_delete; + int mysql; + char *query_string; + MYSQL handle; + struct mm_conf *conf; +}; + +extern struct mysql_mpg123 mysql_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_increment_or_decrement(int, char*); /* -1 on error, 0 if okay */ +extern int mysql_do_auto_insert(char *); /* -1 on error, 0 if file is in DB afterwards */ +extern int mysql_do_auto_delete(char *); /* -1 on error, 0 if file is no longer in DB afterwards */ +extern void mysql_make_playlist(char *); +extern char *mysql_get_file(char *); +#ifdef MYSQL_DEBUG +extern void mysql_dump_configuration(void); +#endif +/* Config related functions... */ +extern void mm_set_dbhost(char *arg); +extern void mm_set_dbport(char *arg); +extern void mm_set_dbname(char *arg); +extern void mm_set_dbtable(char *arg); +extern void mm_set_dbuser(char *arg); +extern void mm_set_dbtableuser(char *arg); +extern void mm_set_dbpasswd(char *arg); +extern void mm_set_dbusepasswd(char *arg); + +#endif /* !_MYSQLSUPPORT_H */