# HG changeset patch # User Richard Laager # Date 1192330183 0 # Node ID 7deceebc696edf55e83ef2631bdbb6fd7312e3df # Parent 957556ba7b38909d8cde16c68985517947c8ea7c# Parent 5e46cdf9ef2b7f58c3d53da9b0f52df3ba8effa8 merge of '44d5142a2e45fb899043fbf65242432eceffafdc' and '49d0219884ede2c6c571f2df73e29dffa86f54ad' diff -r 957556ba7b38 -r 7deceebc696e COPYRIGHT --- a/COPYRIGHT Sat Oct 13 17:46:15 2007 +0000 +++ b/COPYRIGHT Sun Oct 14 02:49:43 2007 +0000 @@ -196,6 +196,7 @@ Akuke Kok Konstantin Korikov Cole Kowalski +Matt Kramer Gary Kramlich Jan Kratochvil Andrej Krivulčík diff -r 957556ba7b38 -r 7deceebc696e ChangeLog --- a/ChangeLog Sat Oct 13 17:46:15 2007 +0000 +++ b/ChangeLog Sun Oct 14 02:49:43 2007 +0000 @@ -31,6 +31,8 @@ * Pidgin's display is now saved with the command line for session restoration. (David Mohr) * ICQ Birthday notifications are shown as buddy list emblems. + * Plugin actions are now available from the docklet context menu + in addition to the Tool menu of the buddy list. version 2.2.1 (09/29/2007): http://developer.pidgin.im/query?status=closed&milestone=2.2.1 diff -r 957556ba7b38 -r 7deceebc696e Doxyfile.in --- a/Doxyfile.in Sat Oct 13 17:46:15 2007 +0000 +++ b/Doxyfile.in Sun Oct 14 02:49:43 2007 +0000 @@ -457,7 +457,8 @@ # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. -EXCLUDE = +EXCLUDE = libpurple/purple-client.h \ + libpurple/purple-client-bindings.h # The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories # that are symbolic links (a Unix filesystem feature) are excluded from the input. @@ -857,7 +858,7 @@ # feature is still experimental and incomplete at the # moment. -GENERATE_XML = NO +GENERATE_XML = YES # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be @@ -1160,7 +1161,7 @@ # not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT). # If 0 is used for the depth value (the default), the graph is not depth-constrained. -MAX_DOT_GRAPH_DEPTH = 0 +MAX_DOT_GRAPH_DEPTH = 2 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, which results in a white background. diff -r 957556ba7b38 -r 7deceebc696e Makefile.am --- a/Makefile.am Sat Oct 13 17:46:15 2007 +0000 +++ b/Makefile.am Sun Oct 14 02:49:43 2007 +0000 @@ -48,6 +48,13 @@ if HAVE_DOXYGEN @echo "Running doxygen..." @doxygen +if HAVE_XSLTPROC + @echo "Generating devhelp index..." + @xsltproc doxy2devhelp.xsl doc/xml/index.xml > doc/html/pidgin.devhelp + @echo "(Symlink doc/html to ~/.local/share/gtk-doc/html/pidgin to make devhelp see the documentation)" +else + @echo "Not generating devhelp index: xsltproc was not found by configure" +endif else @echo "doxygen was not found during configure. Aborting." @echo; diff -r 957556ba7b38 -r 7deceebc696e configure.ac --- a/configure.ac Sat Oct 13 17:46:15 2007 +0000 +++ b/configure.ac Sun Oct 14 02:49:43 2007 +0000 @@ -2101,6 +2101,10 @@ [AC_HELP_STRING([--enable-dot], [enable graphs in doxygen via 'dot'])], enable_dot="$enableval", enable_dot="yes") +AC_ARG_ENABLE(devhelp, + [AC_HELP_STRING([--enable-devhelp], + [enable building index for devhelp documentation browser])], + enable_devhelp="$enableval", enable_devhelp="yes") if test "x$enable_doxygen" = xyes; then AC_CHECK_PROG(DOXYGEN, doxygen, true, false) @@ -2120,14 +2124,28 @@ AC_DEFINE_UNQUOTED(HAVE_DOT, 1, [whether or not we have dot]) fi fi + + if test "x$enable_devhelp" = "xyes"; then + AC_CHECK_PROG(XSLTPROC, xsltproc, true, false) + + if test $XSLTPROC = false; then + enable_devhelp="no"; + AC_MSG_WARN([*** xsltproc not found; devhelp index will not be created]) + else + AC_DEFINE_UNQUOTED(HAVE_XSLTPROC, 1, [whether or not we have xsltproc for devhelp index]) + fi + fi fi else enable_dot="no" + enable_devhelp="no" fi AC_SUBST(enable_doxygen) AC_SUBST(enable_dot) +AC_SUBST(enable_devhelp) AM_CONDITIONAL(HAVE_DOXYGEN, test "x$enable_doxygen" = "xyes") +AM_CONDITIONAL(HAVE_XSLTPROC, test "x$enable_devhelp" = "xyes") AC_ARG_ENABLE(debug, [AC_HELP_STRING([--enable-debug], [compile with debugging support])], , enable_debug=no) diff -r 957556ba7b38 -r 7deceebc696e doxy2devhelp.xsl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doxy2devhelp.xsl Sun Oct 14 02:49:43 2007 +0000 @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + .html + + + + + + + + + + + + + + + + .html# + + + + + + + + + + + .html# + + + + diff -r 957556ba7b38 -r 7deceebc696e finch/gntnotify.c --- a/finch/gntnotify.c Sat Oct 13 17:46:15 2007 +0000 +++ b/finch/gntnotify.c Sun Oct 14 02:49:43 2007 +0000 @@ -194,6 +194,7 @@ PurpleAccount *account = purple_connection_get_account(gc); GString *message = g_string_new(NULL); void *ret; + static int key = 0; if (!detailed) { @@ -212,7 +213,7 @@ to = g_strdup_printf("%s (%s)", tos ? *tos : purple_account_get_username(account), purple_account_get_protocol_name(account)); - gnt_tree_add_row_after(GNT_TREE(emaildialog.tree), GINT_TO_POINTER(time(NULL)), + gnt_tree_add_row_after(GNT_TREE(emaildialog.tree), GINT_TO_POINTER(++key), gnt_tree_create_row(GNT_TREE(emaildialog.tree), to, froms ? *froms : "[Unknown sender]", *subjects), @@ -360,7 +361,8 @@ i = 0; for (iter = results->columns; iter; iter = iter->next) { - gnt_tree_set_column_title(GNT_TREE(tree), i, iter->data); + PurpleNotifySearchColumn *column = iter->data; + gnt_tree_set_column_title(GNT_TREE(tree), i, column->title); i++; } diff -r 957556ba7b38 -r 7deceebc696e libpurple/plugins/log_reader.c --- a/libpurple/plugins/log_reader.c Sat Oct 13 17:46:15 2007 +0000 +++ b/libpurple/plugins/log_reader.c Sun Oct 14 02:49:43 2007 +0000 @@ -28,6 +28,19 @@ NAME_GUESS_THEM }; +/* Some common functions. */ +static int get_month(const char *month) +{ + int iter; + const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; + for (iter = 0; months[iter]; iter++) { + if (strcmp(month, months[iter]) == 0) + break; + } + return iter; +} + /***************************************************************************** * Adium Logger * @@ -114,7 +127,7 @@ continue; } - rd = fread(contents, 56, 1, handle) == 0; + rd = fread(contents, 1, 56, handle) == 0; fclose(handle); contents[rd] = '\0'; @@ -176,7 +189,7 @@ continue; } - rd = fread(contents, 13, 1, handle); + rd = fread(contents, 1, 13, handle); fclose(handle); contents[rd] = '\0'; @@ -1348,36 +1361,7 @@ * daylight savings time. */ tm.tm_isdst = -1; - - /* Ugly hack, in case current locale - * is not English. This code is taken - * from log.c. - */ - if (strcmp(month, "Jan") == 0) { - tm.tm_mon= 0; - } else if (strcmp(month, "Feb") == 0) { - tm.tm_mon = 1; - } else if (strcmp(month, "Mar") == 0) { - tm.tm_mon = 2; - } else if (strcmp(month, "Apr") == 0) { - tm.tm_mon = 3; - } else if (strcmp(month, "May") == 0) { - tm.tm_mon = 4; - } else if (strcmp(month, "Jun") == 0) { - tm.tm_mon = 5; - } else if (strcmp(month, "Jul") == 0) { - tm.tm_mon = 6; - } else if (strcmp(month, "Aug") == 0) { - tm.tm_mon = 7; - } else if (strcmp(month, "Sep") == 0) { - tm.tm_mon = 8; - } else if (strcmp(month, "Oct") == 0) { - tm.tm_mon = 9; - } else if (strcmp(month, "Nov") == 0) { - tm.tm_mon = 10; - } else if (strcmp(month, "Dec") == 0) { - tm.tm_mon = 11; - } + tm.tm_mon = get_month(month); data = g_new0( struct trillian_logger_data, 1); @@ -1439,7 +1423,7 @@ file = g_fopen(data->path, "rb"); fseek(file, data->offset, SEEK_SET); - data->length = fread(read, data->length, 1, file); + data->length = fread(read, 1, data->length, file); fclose(file); if (read[data->length-1] == '\n') { @@ -1938,7 +1922,7 @@ contents = g_malloc(data->length + 2); fseek(file, data->offset, SEEK_SET); - data->length = fread(contents, data->length, 1, file); + data->length = fread(contents, 1, data->length, file); fclose(file); contents[data->length] = '\n'; @@ -2111,168 +2095,54 @@ #define AMSN_LOG_CONV_END "|\"LRED[You have closed the window on " #define AMSN_LOG_CONV_EXTRA "01 Aug 2001 00:00:00]" -/* `log_dir`/username@hotmail.com/logs/buddyname@hotmail.com.log */ -/* `log_dir`/username@hotmail.com/logs/Month Year/buddyname@hotmail.com.log */ -static GList *amsn_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account) +static GList *amsn_logger_parse_file(char *filename, const char *sn, PurpleAccount *account) { GList *list = NULL; - struct amsn_logger_data *data; - const char *logdir; - char *username; - char *log_path; - char *buddy_log; - char *filename; - GDir *dir; - const char *name; GError *error; char *contents; + struct amsn_logger_data *data; PurpleLog *log; - GList *files = NULL; - GList *f; - - logdir = purple_prefs_get_string("/plugins/core/log_reader/amsn/log_directory"); - - /* By clearing the log directory path, this logger can be (effectively) disabled. */ - if (!logdir || !*logdir) - return NULL; - - /* aMSN only works with MSN/WLM */ - if (strcmp(account->protocol_id, "prpl-msn")) - return NULL; - - username = g_strdup(purple_normalize(account, account->username)); - buddy_log = g_strdup_printf("%s.log", purple_normalize(account, sn)); - log_path = g_build_filename(logdir, username, "logs", NULL); - - /* First check in the top-level */ - filename = g_build_filename(log_path, buddy_log, NULL); - if (g_file_test(filename, G_FILE_TEST_EXISTS)) - files = g_list_prepend(files, filename); - else - g_free(filename); - - /* Check in previous months */ - dir = g_dir_open(log_path, 0, NULL); - if (dir) { - while ((name = g_dir_read_name(dir)) != NULL) { - filename = g_build_filename(log_path, name, buddy_log, NULL); - if (g_file_test(filename, G_FILE_TEST_EXISTS)) - files = g_list_prepend(files, filename); - else - g_free(filename); - } - g_dir_close(dir); - } - - g_free(log_path); - - /* New versions use 'friendlier' directory names */ - purple_util_chrreplace(username, '@', '_'); - purple_util_chrreplace(username, '.', '_'); - - log_path = g_build_filename(logdir, username, "logs", NULL); - - /* First check in the top-level */ - filename = g_build_filename(log_path, buddy_log, NULL); - if (g_file_test(filename, G_FILE_TEST_EXISTS)) - files = g_list_prepend(files, filename); - else - g_free(filename); - - /* Check in previous months */ - dir = g_dir_open(log_path, 0, NULL); - if (dir) { - while ((name = g_dir_read_name(dir)) != NULL) { - filename = g_build_filename(log_path, name, buddy_log, NULL); - if (g_file_test(filename, G_FILE_TEST_EXISTS)) - files = g_list_prepend(files, filename); - else - g_free(filename); - } - g_dir_close(dir); - } - - g_free(log_path); - g_free(username); - g_free(buddy_log); - - /* Loop through files looking for logs */ - for(f = g_list_first(files); f; f = g_list_next(f)) { - filename = f->data; - purple_debug_info("aMSN logger", "Reading %s\n", filename); - error = NULL; - if (!g_file_get_contents(filename, &contents, NULL, &error)) { - purple_debug_error("aMSN logger", - "Couldn't read file %s: %s \n", filename, - (error && error->message) ? - error->message : "Unknown error"); - if (error) - g_error_free(error); - } else { - char *c = contents; - gboolean found_start = FALSE; - char *start_log = c; - int offset = 0; - struct tm tm; - while (c && *c) { - if (purple_str_has_prefix(c, AMSN_LOG_CONV_START)) { - char month[4]; - if (sscanf(c + strlen(AMSN_LOG_CONV_START), - "%u %3s %u %u:%u:%u", - &tm.tm_mday, (char*)&month, &tm.tm_year, - &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { - found_start = FALSE; - purple_debug_error("aMSN logger", - "Error parsing start date for %s\n", - filename); - } else { - const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL}; - tm.tm_year -= 1900; - - /* Let the C library deal with - * daylight savings time. - */ - tm.tm_isdst = -1; - - /* Ugly hack, in case current locale - * is not English. This code is taken - * from log.c. - */ - for (tm.tm_mon = 0; months[tm.tm_mon]; tm.tm_mon++) { - if (strcmp(month, months[tm.tm_mon]) == 0) - break; - } - found_start = TRUE; - offset = c - contents; - start_log = c; - } - } else if (purple_str_has_prefix(c, AMSN_LOG_CONV_END) && found_start) { - data = g_new0(struct amsn_logger_data, 1); - data->path = g_strdup(filename); - data->offset = offset; - data->length = c - start_log - + strlen(AMSN_LOG_CONV_END) - + strlen(AMSN_LOG_CONV_EXTRA); - log = purple_log_new(PURPLE_LOG_IM, sn, account, NULL, mktime(&tm), NULL); - log->logger = amsn_logger; - log->logger_data = data; - list = g_list_prepend(list, log); + + purple_debug_info("aMSN logger", "Reading %s\n", filename); + error = NULL; + if (!g_file_get_contents(filename, &contents, NULL, &error)) { + purple_debug_error("aMSN logger", + "Couldn't read file %s: %s \n", filename, + (error && error->message) ? + error->message : "Unknown error"); + if (error) + g_error_free(error); + } else { + char *c = contents; + gboolean found_start = FALSE; + char *start_log = c; + int offset = 0; + struct tm tm; + while (c && *c) { + if (purple_str_has_prefix(c, AMSN_LOG_CONV_START)) { + char month[4]; + if (sscanf(c + strlen(AMSN_LOG_CONV_START), + "%u %3s %u %u:%u:%u", + &tm.tm_mday, (char*)&month, &tm.tm_year, + &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) { found_start = FALSE; - - purple_debug_info("aMSN logger", - "Found log for %s:" - " path = (%s)," - " offset = (%d)," - " length = (%d)\n", - sn, data->path, data->offset, data->length); + purple_debug_error("aMSN logger", + "Error parsing start date for %s\n", + filename); + } else { + tm.tm_year -= 1900; + + /* Let the C library deal with + * daylight savings time. + */ + tm.tm_isdst = -1; + tm.tm_mon = get_month(month); + + found_start = TRUE; + offset = c - contents; + start_log = c; } - c = strstr(c, "\n"); - c++; - } - - /* I've seen the file end without the AMSN_LOG_CONV_END bit */ - if (found_start) { + } else if (purple_str_has_prefix(c, AMSN_LOG_CONV_END) && found_start) { data = g_new0(struct amsn_logger_data, 1); data->path = g_strdup(filename); data->offset = offset; @@ -2292,12 +2162,112 @@ " length = (%d)\n", sn, data->path, data->offset, data->length); } - g_free(contents); + c = strstr(c, "\n"); + c++; + } + + /* I've seen the file end without the AMSN_LOG_CONV_END bit */ + if (found_start) { + data = g_new0(struct amsn_logger_data, 1); + data->path = g_strdup(filename); + data->offset = offset; + data->length = c - start_log + + strlen(AMSN_LOG_CONV_END) + + strlen(AMSN_LOG_CONV_EXTRA); + log = purple_log_new(PURPLE_LOG_IM, sn, account, NULL, mktime(&tm), NULL); + log->logger = amsn_logger; + log->logger_data = data; + list = g_list_prepend(list, log); + found_start = FALSE; + + purple_debug_info("aMSN logger", + "Found log for %s:" + " path = (%s)," + " offset = (%d)," + " length = (%d)\n", + sn, data->path, data->offset, data->length); } + g_free(contents); + } + + return list; +} + +/* `log_dir`/username@hotmail.com/logs/buddyname@hotmail.com.log */ +/* `log_dir`/username@hotmail.com/logs/Month Year/buddyname@hotmail.com.log */ +static GList *amsn_logger_list(PurpleLogType type, const char *sn, PurpleAccount *account) +{ + GList *list = NULL; + const char *logdir; + char *username; + char *log_path; + char *buddy_log; + char *filename; + GDir *dir; + const char *name; + + logdir = purple_prefs_get_string("/plugins/core/log_reader/amsn/log_directory"); + + /* By clearing the log directory path, this logger can be (effectively) disabled. */ + if (!logdir || !*logdir) + return NULL; + + /* aMSN only works with MSN/WLM */ + if (strcmp(account->protocol_id, "prpl-msn")) + return NULL; + + username = g_strdup(purple_normalize(account, account->username)); + buddy_log = g_strdup_printf("%s.log", purple_normalize(account, sn)); + log_path = g_build_filename(logdir, username, "logs", NULL); + + /* First check in the top-level */ + filename = g_build_filename(log_path, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = amsn_logger_parse_file(filename, sn, account); + else g_free(filename); + + /* Check in previous months */ + dir = g_dir_open(log_path, 0, NULL); + if (dir) { + while ((name = g_dir_read_name(dir)) != NULL) { + filename = g_build_filename(log_path, name, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); + g_free(filename); + } + g_dir_close(dir); } - g_list_free(files); + g_free(log_path); + + /* New versions use 'friendlier' directory names */ + purple_util_chrreplace(username, '@', '_'); + purple_util_chrreplace(username, '.', '_'); + + log_path = g_build_filename(logdir, username, "logs", NULL); + + /* First check in the top-level */ + filename = g_build_filename(log_path, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); + g_free(filename); + + /* Check in previous months */ + dir = g_dir_open(log_path, 0, NULL); + if (dir) { + while ((name = g_dir_read_name(dir)) != NULL) { + filename = g_build_filename(log_path, name, buddy_log, NULL); + if (g_file_test(filename, G_FILE_TEST_EXISTS)) + list = g_list_concat(list, amsn_logger_parse_file(filename, sn, account)); + g_free(filename); + } + g_dir_close(dir); + } + + g_free(log_path); + g_free(username); + g_free(buddy_log); return list; } @@ -2331,7 +2301,7 @@ g_return_val_if_fail(file != NULL, g_strdup("")); fseek(file, data->offset, SEEK_SET); - data->length = fread(contents, data->length, 1, file); + data->length = fread(contents, 1, data->length, file); fclose(file); contents[data->length] = '\n'; diff -r 957556ba7b38 -r 7deceebc696e libpurple/protocols/bonjour/buddy.c --- a/libpurple/protocols/bonjour/buddy.c Sat Oct 13 17:46:15 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.c Sun Oct 14 02:49:43 2007 +0000 @@ -62,9 +62,11 @@ } void -set_bonjour_buddy_value(BonjourBuddy* buddy, const char *record_key, const char *value, uint32_t len){ +set_bonjour_buddy_value(BonjourBuddy* buddy, const char *record_key, const char *value, guint32 len){ gchar **fld = NULL; + g_return_if_fail(record_key != NULL); + if (!strcmp(record_key, "1st")) fld = &buddy->first; else if(!strcmp(record_key, "email")) diff -r 957556ba7b38 -r 7deceebc696e libpurple/protocols/bonjour/buddy.h --- a/libpurple/protocols/bonjour/buddy.h Sat Oct 13 17:46:15 2007 +0000 +++ b/libpurple/protocols/bonjour/buddy.h Sun Oct 14 02:49:43 2007 +0000 @@ -83,7 +83,7 @@ /** * Sets a value in the BonjourBuddy struct, destroying the old value */ -void set_bonjour_buddy_value(BonjourBuddy *buddy, const char *record_key, const char *value, uint32_t len); +void set_bonjour_buddy_value(BonjourBuddy *buddy, const char *record_key, const char *value, guint32 len); /** * Check if all the compulsory buddy data is present. diff -r 957556ba7b38 -r 7deceebc696e libpurple/protocols/simple/simple.c --- a/libpurple/protocols/simple/simple.c Sat Oct 13 17:46:15 2007 +0000 +++ b/libpurple/protocols/simple/simple.c Sun Oct 14 02:49:43 2007 +0000 @@ -80,14 +80,15 @@ static gboolean process_register_response(struct simple_account_data *sip, struct sipmsg *msg, struct transaction *tc); static void send_notify(struct simple_account_data *sip, struct simple_watcher *); -static void send_publish(struct simple_account_data *sip); +static void send_open_publish(struct simple_account_data *sip); +static void send_closed_publish(struct simple_account_data *sip); static void do_notifies(struct simple_account_data *sip) { GSList *tmp = sip->watcher; purple_debug_info("simple", "do_notifies()\n"); if((sip->republish != -1) || sip->republish < time(NULL)) { if(purple_account_get_bool(sip->account, "dopublish", TRUE)) { - send_publish(sip); + send_open_publish(sip); } } @@ -1020,7 +1021,7 @@ case 200: if(sip->registerstatus < SIMPLE_REGISTER_COMPLETE) { /* registered */ if(purple_account_get_bool(sip->account, "dopublish", TRUE)) { - send_publish(sip); + send_open_publish(sip); } } sip->registerstatus = SIMPLE_REGISTER_COMPLETE; @@ -1072,7 +1073,7 @@ static void process_incoming_notify(struct simple_account_data *sip, struct sipmsg *msg) { gchar *from; gchar *fromhdr; - gchar *tmp2; + gchar *basicstatus_data; xmlnode *pidf; xmlnode *basicstatus = NULL, *tuple, *status; gboolean isonline = FALSE; @@ -1085,8 +1086,9 @@ if(!pidf) { purple_debug_info("simple", "process_incoming_notify: no parseable pidf\n"); + purple_prpl_got_user_status(sip->account, from, "offline", NULL); + send_sip_response(sip->gc, msg, 200, "OK", NULL); g_free(from); - send_sip_response(sip->gc, msg, 200, "OK", NULL); return; } @@ -1101,27 +1103,28 @@ return; } - tmp2 = xmlnode_get_data(basicstatus); + basicstatus_data = xmlnode_get_data(basicstatus); - if(!tmp2) { + if(!basicstatus_data) { purple_debug_info("simple", "process_incoming_notify: no basic data found\n"); xmlnode_free(pidf); g_free(from); return; } - if(strstr(tmp2, "open")) { + if(strstr(basicstatus_data, "open")) isonline = TRUE; - } + - g_free(tmp2); - - if(isonline) purple_prpl_got_user_status(sip->account, from, "available", NULL); - else purple_prpl_got_user_status(sip->account, from, "offline", NULL); + if(isonline) + purple_prpl_got_user_status(sip->account, from, "available", NULL); + else + purple_prpl_got_user_status(sip->account, from, "offline", NULL); xmlnode_free(pidf); + g_free(from); + g_free(basicstatus_data); - g_free(from); send_sip_response(sip->gc, msg, 200, "OK", NULL); } @@ -1188,28 +1191,27 @@ return doc; } - - -static gchar* gen_pidf(struct simple_account_data *sip) { +static gchar* gen_pidf(struct simple_account_data *sip, gboolean open) { gchar *doc = g_strdup_printf("\n" "\n" "\n" "\n" - "open\n" + "%s\n" "\n" "%s\n" "\n" "", sip->username, sip->servername, - sip->status); + (open == TRUE) ? "open" : "closed", + (open == TRUE) ? sip->status : ""); return doc; } static void send_notify(struct simple_account_data *sip, struct simple_watcher *watcher) { - gchar *doc = watcher->needsxpidf ? gen_xpidf(sip) : gen_pidf(sip); + gchar *doc = watcher->needsxpidf ? gen_xpidf(sip) : gen_pidf(sip, TRUE); gchar *hdr = watcher->needsxpidf ? "Event: presence\r\nContent-Type: application/xpidf+xml\r\n" : "Event: presence\r\nContent-Type: application/pidf+xml\r\n"; send_sip_request(sip->gc, "NOTIFY", watcher->name, watcher->name, hdr, doc, &watcher->dialog, NULL); g_free(doc); @@ -1223,9 +1225,9 @@ return TRUE; } -static void send_publish(struct simple_account_data *sip) { +static void send_open_publish(struct simple_account_data *sip) { gchar *uri = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); - gchar *doc = gen_pidf(sip); + gchar *doc = gen_pidf(sip, TRUE); send_sip_request(sip->gc, "PUBLISH", uri, uri, "Expires: 600\r\nEvent: presence\r\n" "Content-Type: application/pidf+xml\r\n", @@ -1235,6 +1237,18 @@ g_free(doc); } +static void send_closed_publish(struct simple_account_data *sip) { + gchar *uri = g_strdup_printf("sip:%s@%s", sip->username, sip->servername); + gchar *doc = gen_pidf(sip, FALSE); + send_sip_request(sip->gc, "PUBLISH", uri, uri, + "Expires: 600\r\nEvent: presence\r\n" + "Content-Type: application/pidf+xml\r\n", + doc, NULL, process_publish_response); + /*sip->republish = time(NULL) + 500;*/ + g_free(uri); + g_free(doc); +} + static void process_incoming_subscribe(struct simple_account_data *sip, struct sipmsg *msg) { const char *from_hdr = sipmsg_find_header(msg, "From"); gchar *from = parse_from(from_hdr); @@ -1738,7 +1752,14 @@ if(sip) { /* unregister */ if (sip->registerstatus == SIMPLE_REGISTER_COMPLETE) + { + if(purple_account_get_bool(sip->account, + "dopublish", + TRUE)) + send_closed_publish(sip); + do_register_exp(sip, 0); + } connection_free_all(sip); if (sip->query_data != NULL) diff -r 957556ba7b38 -r 7deceebc696e libpurple/prpl.h --- a/libpurple/prpl.h Sat Oct 13 17:46:15 2007 +0000 +++ b/libpurple/prpl.h Sun Oct 14 02:49:43 2007 +0000 @@ -226,11 +226,17 @@ void (*tooltip_text)(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full); /** - * This must be implemented, and must add at least the offline - * and online states. + * Returns a list of #PurpleStatusType which exist for this account; + * this must be implemented, and must add at least the offline and + * online states. */ GList *(*status_types)(PurpleAccount *account); + /** + * Returns a list of #PurpleMenuAction structs, which represent extra + * actions to be shown in (for example) the right-click menu for @a + * node. + */ GList *(*blist_node_menu)(PurpleBlistNode *node); GList *(*chat_info)(PurpleConnection *); GHashTable *(*chat_info_defaults)(PurpleConnection *, const char *chat_name); @@ -258,6 +264,10 @@ void (*set_info)(PurpleConnection *, const char *info); unsigned int (*send_typing)(PurpleConnection *, const char *name, PurpleTypingState state); + /** + * Should arrange for purple_notify_userinfo() to be called with + * @a who's user info. + */ void (*get_info)(PurpleConnection *, const char *who); void (*set_status)(PurpleAccount *account, PurpleStatus *status); @@ -287,8 +297,13 @@ /** new user registration */ void (*register_user)(PurpleAccount *); - /* get "chat buddy" info and away message */ + /** Deprecated and vestigal; use #get_cb_real_name and #get_info + * instead. + */ void (*get_cb_info)(PurpleConnection *, int, const char *who); + /** Also deprecated and vestigal; use #get_cb_real_name and + * #status_text instead. + */ void (*get_cb_away)(PurpleConnection *, int, const char *who); /** save/store buddy's alias on server list/roster */ @@ -348,9 +363,12 @@ /* room list serialize */ char *(*roomlist_room_serialize)(PurpleRoomlistRoom *room); - /* Remove the user from the server. (This is only at the bottom to keep binary compatibility.) - * The account can either be connected or disconnected. After the removal is finished, - * the connection will stay open and has to be closed! + /** Remove the user from the server. The account can either be + * connected or disconnected. After the removal is finished, the + * connection will stay open and has to be closed! + */ + /* This is here rather than next to register_user for API compatibility + * reasons. */ void (*unregister_user)(PurpleAccount *, PurpleAccountUnregistrationCb cb, void *user_data); diff -r 957556ba7b38 -r 7deceebc696e libpurple/util.c --- a/libpurple/util.c Sat Oct 13 17:46:15 2007 +0000 +++ b/libpurple/util.c Sun Oct 14 02:49:43 2007 +0000 @@ -2565,6 +2565,8 @@ purple_debug_info("util", "Writing file %s\n", filename_full); + g_return_val_if_fail((size >= -1), FALSE); + filename_temp = g_strdup_printf("%s.save", filename_full); /* Remove an old temporary file, if one exists */ @@ -2590,7 +2592,7 @@ } /* Write to file */ - real_size = (size == -1) ? strlen(data) : size; + real_size = (size == -1) ? strlen(data) : (size_t) size; byteswritten = fwrite(data, 1, real_size, file); /* Close file */ diff -r 957556ba7b38 -r 7deceebc696e pidgin/gtkconv.c --- a/pidgin/gtkconv.c Sat Oct 13 17:46:15 2007 +0000 +++ b/pidgin/gtkconv.c Sun Oct 14 02:49:43 2007 +0000 @@ -6519,6 +6519,7 @@ AtkObject *accessibility_obj; /* I think this is a little longer than it needs to be but I'm lazy. */ char *style; + gboolean bold = FALSE; if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM) im = PURPLE_CONV_IM(conv); @@ -6552,7 +6553,7 @@ gtk_list_store_set(gtkconv->infopane_model, &(gtkconv->infopane_iter), CONV_TEXT_COLUMN, markup, -1); /* XXX seanegan Why do I have to do this? */ - gtk_widget_queue_draw(gtkconv->infopane); + gtk_widget_queue_draw(gtkconv->infopane); if (title != markup) g_free(markup); @@ -6571,31 +6572,41 @@ style = "color=\"#c4a000\""; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_NICK) { atk_object_set_description(accessibility_obj, _("Nick Said")); - style = "color=\"#204a87\" weight=\"bold\""; + style = "color=\"#cc0000\""; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT) { atk_object_set_description(accessibility_obj, _("Unread Messages")); - style = "color=\"#cc0000\" weight=\"bold\""; + if (gtkconv->active_conv->type == PURPLE_CONV_TYPE_CHAT) + style = "color=\"#204a87\" weight=\"bold\""; + else + style = "color=\"#cc0000\" weight=\"bold\""; } else if (gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) { atk_object_set_description(accessibility_obj, _("New Event")); - style = "color=\"#888a85\" weight=\"bold\""; + style = "color=\"#888a85\""; } else { - style = ""; + style = NULL; } + + if (gtkconv->unseen_state == PIDGIN_UNSEEN_TEXT || + gtkconv->unseen_state == PIDGIN_UNSEEN_NICK || + gtkconv->unseen_state == PIDGIN_UNSEEN_EVENT) + bold = TRUE; - if (*style != '\0') + if (style || bold) { char *html_title,*label; html_title = g_markup_escape_text(title, -1); - label = g_strdup_printf("%s", - style, html_title); + label = g_strdup_printf("%s", + style ? style : "", + bold ? "weight=\"bold\"" : "", + html_title); g_free(html_title); gtk_label_set_markup(GTK_LABEL(gtkconv->tab_label), label); g_free(label); } else gtk_label_set_text(GTK_LABEL(gtkconv->tab_label), title); - + if (pidgin_conv_window_is_active_conversation(conv)) update_typing_icon(gtkconv); diff -r 957556ba7b38 -r 7deceebc696e pidgin/gtknotify.c --- a/pidgin/gtknotify.c Sat Oct 13 17:46:15 2007 +0000 +++ b/pidgin/gtknotify.c Sun Oct 14 02:49:43 2007 +0000 @@ -740,7 +740,7 @@ GtkListStore *model; GtkCellRenderer *renderer; guint col_num; - GList *column; + GList *columniter; guint i; GtkWidget *vbox; @@ -824,11 +824,12 @@ -1, "", renderer, "pixbuf", 0, NULL); i = 1; - for (column = results->columns; column != NULL; column = column->next) { + for (columniter = results->columns; columniter != NULL; columniter = columniter->next) { + PurpleNotifySearchColumn *column = columniter->data; renderer = gtk_cell_renderer_text_new(); gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(treeview), -1, - column->data, renderer, "text", i, NULL); + column->title, renderer, "text", i, NULL); i++; } diff -r 957556ba7b38 -r 7deceebc696e pidgin/gtksound.c --- a/pidgin/gtksound.c Sat Oct 13 17:46:15 2007 +0000 +++ b/pidgin/gtksound.c Sun Oct 14 02:49:43 2007 +0000 @@ -118,12 +118,9 @@ if (conv != NULL && PIDGIN_IS_PIDGIN_CONVERSATION(conv)) { PidginConversation *gtkconv; - PidginWindow *win; gboolean has_focus; gtkconv = PIDGIN_CONVERSATION(conv); - win = gtkconv->win; - has_focus = purple_conversation_has_focus(conv); if (!gtkconv->make_sound || diff -r 957556ba7b38 -r 7deceebc696e pidgin/gtkutils.c --- a/pidgin/gtkutils.c Sat Oct 13 17:46:15 2007 +0000 +++ b/pidgin/gtkutils.c Sun Oct 14 02:49:43 2007 +0000 @@ -1526,6 +1526,8 @@ if (prpl_info && prpl_info->can_receive_file) ft = prpl_info->can_receive_file(gc, who); + else if (prpl_info && prpl_info->send_file) + ft = TRUE; if (im && ft) purple_request_choice(NULL, NULL, @@ -1559,6 +1561,7 @@ _("Set as buddy icon"), DND_BUDDY_ICON, (ft ? _("Send image file") : _("Insert in message")), (ft ? DND_FILE_TRANSFER : DND_IM_IMAGE), NULL); + gdk_pixbuf_unref(pb); return; }