From 9ae0abe3414ea26f83fe3e01a37c3cd4819a82b9 Mon Sep 17 00:00:00 2001 From: Thomas White Date: Fri, 17 Jul 2009 12:46:27 +0100 Subject: Initial import --- src/listcache.c | 615 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 615 insertions(+) create mode 100644 src/listcache.c (limited to 'src/listcache.c') diff --git a/src/listcache.c b/src/listcache.c new file mode 100644 index 0000000..a895ff8 --- /dev/null +++ b/src/listcache.c @@ -0,0 +1,615 @@ +/* + * listcache.c + * + * Contact list caching + * + * (c) 2002-2005 Thomas White + * Part of TuxMessenger - GTK+-based MSN Messenger client + * + * This package is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 dated June, 1991. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this package; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#include "contactlist.h" +#include "debug.h" +#include "options.h" +#include "routines.h" +#include "mainwindow.h" +#include "xml.h" +#include "msnprotocol.h" +#include "addcontact.h" +#include "error.h" + +static char *listcache_tag = NULL; +static char *listcache_mfn = NULL; +static char *listcache_ubxdata = NULL; +static unsigned int listcache_invalid = FALSE; + +static char *listcache_file() { + + char *filename; + char *done; + + filename = routines_glob("~/.tuxmessenger/"); + done = malloc(strlen(filename)+11); + strcpy(done, filename); + free(filename); + strcat(done, "list.cache"); + + return done; + +} + +/* Called to record the friendly name for later caching */ +void listcache_setmfn(const char *mfn) { + + if ( listcache_mfn != NULL ) { + free(listcache_mfn); + } + + listcache_mfn = strdup(mfn); + +} + +const char *listcache_getmfn() { + + if ( listcache_mfn == NULL ) { + return ""; + } + + return listcache_mfn; + +} + +void listcache_setcsm(const char *csm) { + + const char *template; + + if ( listcache_ubxdata != NULL ) { + free(listcache_ubxdata); + } + + template = ""; + listcache_ubxdata = xml_setblock(template, strlen(template), "Data", "PSM", csm); + +} + +static char *listcache_getcsm_internal(int entities) { + + char *result; + + if ( listcache_ubxdata == NULL ) { + return strdup(""); + } + + result = xml_getblock(listcache_ubxdata, strlen(listcache_ubxdata), "Data", "PSM", entities); + if ( result == NULL ) { + return strdup(""); + } + + return result; + +} + +char *listcache_getcsm() { + return listcache_getcsm_internal(0); +} + +char *listcache_getcsm_noentities() { + return listcache_getcsm_internal(1); +} + +static int listcache_processline(char *line) { + + char *token = routines_lindex(line, 0); + + if ( strcmp(token, "FL") == 0 ) { + + char *username = routines_lindex(line, 1); + char *friendlyname = routines_lindex(line, 2); + char *guid = routines_lindex(line, 3); + if ( username == NULL ) { + return -1; + } + if ( strlen(guid) == 0 ) { + free(guid); + guid = NULL; + } + if ( strlen(friendlyname) == 0 ) { + /* This would be a bad thing. */ + free(friendlyname); + friendlyname = NULL; + } + contactlist_fldetails(CONTACT_SOURCE_CACHE, username, friendlyname, 0, NULL, ONLINE_FLN, guid); + free(username); + free(friendlyname); + + } else if ( strcmp(token, "AL") == 0 ) { + + char *username = routines_lindex(line, 1); + char *friendlyname = routines_lindex(line, 2); + if ( username == NULL ) { + return -1; + } + if ( strlen(friendlyname) == 0 ) { + free(friendlyname); + friendlyname = NULL; + } + contactlist_aldetails(CONTACT_SOURCE_CACHE, username, friendlyname, ONLINE_FLN); + free(username); + if ( friendlyname != NULL ) { + free(friendlyname); + } + + } else if ( strcmp(token, "BL") == 0 ) { + + char *username = routines_lindex(line, 1); + char *friendlyname = routines_lindex(line, 2); + if ( username == NULL ) { + return -1; + } + if ( strlen(friendlyname) == 0 ) { + free(friendlyname); + friendlyname = NULL; + } + contactlist_bldetails(CONTACT_SOURCE_CACHE, username, friendlyname, ONLINE_FLN); + free(username); + if ( friendlyname != NULL ) { + free(friendlyname); + } + + } else if ( strcmp(token, "RL") == 0 ) { + + char *username = routines_lindex(line, 1); + char *friendlyname = routines_lindex(line, 2); + if ( username == NULL ) { + return -1; + } + if ( strlen(friendlyname) == 0 ) { + free(friendlyname); + friendlyname = NULL; + } + contactlist_rldetails(CONTACT_SOURCE_CACHE, username, friendlyname, ONLINE_FLN); + free(username); + if ( friendlyname != NULL ) { + free(friendlyname); + } + + } else if ( strcmp(token, "PL") == 0 ) { + + char *username = routines_lindex(line, 1); + char *friendlyname = routines_lindex(line, 2); + if ( username == NULL ) { + return -1; + } + if ( strlen(friendlyname) == 0 ) { + free(friendlyname); + friendlyname = NULL; + } + contactlist_pldetails(CONTACT_SOURCE_CACHE, username, friendlyname, ONLINE_FLN); + addcontact_added(username, friendlyname); + + free(username); + if ( friendlyname != NULL ) { + free(friendlyname); + } + + } else if ( strcmp(token, "BLP") == 0 ) { + debug_print("LC: Got BLP from cache.\n"); + } else if ( strcmp(token, "GTC") == 0 ) { + debug_print("LC: Got GTC from cache.\n"); + } else if ( strcmp(token, "MFN") == 0 ) { + + char *mfn = routines_lindex(line, 1); + debug_print("LC: Got MFN from cache.\n"); + mainwindow_setmfn(mfn); + listcache_setmfn(mfn); + free(mfn); + + } else if ( strcmp(token, "CSM") == 0 ) { + + /* See also listcache_loadtag_internal() */ + char *csm_text; + char *csm = routines_lindexend(line, 1); + msnprotocol_setcsm(csm); + + csm_text = listcache_getcsm(); + mainwindow_setcsm(csm_text); + free(csm_text); + + free(csm); + debug_print("LC: Got CSM from cache.\n"); + + } else { + free(token); + return -1; + } + + free(token); + return 0; + +} + +static FILE *listcache_loadtag_internal() { + + FILE *fh; + char *line; + char *rval; + char *cachefile; + int done = 0; + + cachefile = listcache_file(); + + fh = fopen(cachefile, "r"); + free(cachefile); + if ( fh == NULL ) { + debug_print("LC: Error opening list cache file.\n"); + return NULL; + } + + line = malloc(1024); + assert(line != NULL); + + /* Check this cache file is right for the username. Bin it if not... */ + rval = fgets(line, 1023, fh); + if ( ferror(fh) || (rval == NULL) ) { + debug_print("LC: Error retrieving list cache username.\n"); + return NULL; + } + if ( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; /* Cut off trailing newline. */ + } + debug_print("LC: list.cache file is for user '%s' ", line); + if ( strcmp(line, options_username()) == 0 ) { + debug_print("- good.\n"); + } else { + + debug_print("- wrong. Deleting...\n"); + free(line); + fclose(fh); + cachefile = listcache_file(); + fh = fopen(listcache_file(), "w"); + free(cachefile); + return NULL; + + } + + /* Get the SYN tag. */ + rval = fgets(line, 1023, fh); + if ( ferror(fh) || (rval == NULL) ) { + debug_print("LC: Error retrieving SYN tag.\n"); + free(line); + fclose(fh); + return NULL; + } + if ( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; /* Cut off trailing newline. */ + } + if ( listcache_tag != NULL ) { + free(listcache_tag); + } + listcache_tag = strdup(line); + + /* Because there doesn't seem to be a way to retrieve the CSM, the CSM also + needs to be read from the cache file at this point. Yuk. */ + while ( rval && !done ) { + + rval = fgets(line, 1023, fh); + if ( rval != NULL ) { + + char *token; + + if ( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; /* Cut off trailing newline. */ + } + + token = routines_lindex(line, 0); + + if ( strcmp(token, "CSM") == 0 ) { + + /* See also listcache_processline() */ + char *csm_text; + char *csm = routines_lindexend(line, 1); + msnprotocol_setcsm(csm); + + csm_text = listcache_getcsm(); + mainwindow_setcsm(csm_text); + free(csm_text); + + free(csm); + debug_print("LC: Got CSM from cache.\n"); + done = 1; + + } + + free(token); + + } + + } + + free(line); + + return fh; + +} + +char *listcache_loadtag() { + + FILE *fh; + + if ( listcache_invalid ) { + debug_print("LC: Cache invalid - not loading.\n"); + return "0 0"; + } + + fh = listcache_loadtag_internal(); + if ( fh != NULL ) { + fclose(fh); + return listcache_tag; + } + + return "0 0"; + +} + +/* Throws the cached contact list at contactlist.c. Returns the tag to send with SYN. + (Actually, this return value is never actually used...) */ +char *listcache_load() { + + FILE *fh; + char *line; + char *rval = "boing"; + int whoops = 0; + + line = malloc(1024); + assert(line != NULL); + + if ( listcache_invalid ) { + debug_print("LC: Cache invalid - not loading.\n"); + return "0 0"; + } + + fh = listcache_loadtag_internal(); + if ( fh == NULL ) { + return "0 0"; + } + + while ( rval && !whoops ) { + rval = fgets(line, 1023, fh); + if ( rval != NULL ) { + if ( line[strlen(line)-1] == '\n' ) { + line[strlen(line)-1] = '\0'; /* Cut off trailing newline. */ + } + whoops = listcache_processline(line); + } + } + if ( ferror(fh) || whoops ) { + debug_print("LC: Error reading list cache file - re-requesting list.\n"); + contactlist_clear(); + return "0 0"; + } + + fclose(fh); + free(line); + + return listcache_tag; + +} + +/* Called to record the most recent tag returned by SYN, to be saved with the list at the next listcache_save */ +void listcache_settag(const char *tag) { + + if ( listcache_tag != NULL ) { + + if ( strcmp(tag, listcache_tag) != 0 ) { + /* Tag has changed, so invalidate the lists ready for the new version.*/ + contactlist_clear(); + } + + free(listcache_tag); + + } + + listcache_tag = strdup(tag); + +} + +/* Save the contact data (from contactlist.c) out to disk. */ +void listcache_save() { + + FILE *fh; + int rval = 0; + char *tag_newline; + char *mfn; + char *cachefile; + + cachefile = listcache_file(); + + fh = fopen(cachefile, "w"); + if ( chmod(cachefile, S_IRUSR | S_IWUSR) != 0 ) { + error_report("Couldn't set permissions on contact list cache file!"); + } + free(cachefile); + + if ( fh == NULL ) { + debug_print("LC: Error opening list cache file.\n"); + return; + } + + /* Record the username */ + tag_newline = malloc(strlen(options_username())+2); + assert(tag_newline != NULL); + strcpy(tag_newline, options_username()); + tag_newline[strlen(tag_newline)+1] = '\0'; + tag_newline[strlen(tag_newline)] = '\n'; + if ( fputs(tag_newline, fh) == EOF ) { + rval = -1; + } + free(tag_newline); + + /* Record the SYN tag */ + tag_newline = malloc(strlen(listcache_tag)+2); + assert(tag_newline != NULL); + strcpy(tag_newline, listcache_tag); + tag_newline[strlen(tag_newline)+1] = '\0'; + tag_newline[strlen(tag_newline)] = '\n'; + if ( fputs(tag_newline, fh) == EOF ) { + rval = -1; + } + free(tag_newline); + + /* CSM has to be saved before anything else, since listcache_loadtag_internal loads + the file as far as the CSM, ignoring everything else, then passes the file + handle to the main parser without resetting the pointer. */ + if ( rval == 0 ) { + + char *csm_text = listcache_getcsm_noentities(); + if ( csm_text != NULL ) { + + /* Record CSM */ + char *csm = malloc(strlen(csm_text)+7); + strcpy(csm, "CSM "); + strcat(csm, csm_text); + csm[strlen(csm)+1] = '\0'; + csm[strlen(csm)] = '\n'; + if ( fputs(csm, fh) == EOF ) { + rval = -1; + } + free(csm); + free(csm_text); + + } + + } + + if ( rval == 0 ) { + + char *blp_newline; + + /* Record the value of BLP */ + blp_newline = malloc(6+strlen(options_blp())); + assert(blp_newline != NULL); + + strcpy(blp_newline, "BLP "); + strcat(blp_newline, options_blp()); + blp_newline[strlen(blp_newline)+1] = '\0'; + blp_newline[strlen(blp_newline)] = '\n'; + if ( fputs(blp_newline, fh) == EOF ) { + rval = -1; + } + free(blp_newline); + + } + + if ( rval == 0 ) { + + char *gtc_newline; + + /* Record the value of GTC */ + gtc_newline = malloc(6+strlen(options_gtc())); + assert(gtc_newline != NULL); + + strcpy(gtc_newline, "GTC "); + strcat(gtc_newline, options_gtc()); + gtc_newline[strlen(gtc_newline)+1] = '\0'; + gtc_newline[strlen(gtc_newline)] = '\n'; + if ( fputs(gtc_newline, fh) == EOF ) { + rval = -1; + } + free(gtc_newline); + + } + + if ( rval == 0 ) { + + if ( listcache_mfn != NULL ) { + + /* Record friendly name */ + mfn = malloc(strlen(listcache_mfn)+7); + strcpy(mfn, "MFN "); + strcat(mfn, listcache_mfn); + mfn[strlen(mfn)+1] = '\0'; + mfn[strlen(mfn)] = '\n'; + if ( fputs(mfn, fh) == EOF ) { + rval = -1; + } + free(mfn); + + } + + } + + if ( rval == 0 ) { + rval = contactlist_dumplist(fh, "FL"); + } + if ( rval == 0 ) { + rval = contactlist_dumplist(fh, "RL"); + } + if ( rval == 0 ) { + rval = contactlist_dumplist(fh, "AL"); + } + if ( rval == 0 ) { + rval = contactlist_dumplist(fh, "BL"); + } + if ( rval == 0 ) { + rval = contactlist_dumplist(fh, "PL"); + } + + if ( rval == 0 ) { + debug_print("LC: Saved contacts to cache.\n"); + } else { + + char *cachefile; + + debug_print("LC: Error saving contacts to cache.\n"); + fclose(fh); + /* Attempt to truncate the cache file for safety next time. */ + cachefile = listcache_file(); + fh = fopen(cachefile, "w"); + free(cachefile); + + } + + fclose(fh); + listcache_invalid = FALSE; + +} + +int listcache_checktag(const char *tag) { + + if ( strcmp(tag, listcache_tag) == 0 ) { + return 1; + } + + return 0; + +} + +/* Mark the contents of the cache as invalid, for example, after changing the local username. */ +void listcache_invalidate() { + listcache_invalid = TRUE; +} -- cgit v1.2.3