# HG changeset patch # User Nathan Walp # Date 1182056961 0 # Node ID af0b9c6cbeb809dd51a437e4129b057101e04a1b # Parent f88c2a41200d8fa9d1bbb26c3e0a3fc3f11ca772# Parent 428a3418bce51936141224344eac25194f78c6fa merge of 'a044da71f197bdd564f0d38ebb02798e06d1997f' and 'e64c6a26887b59ce7ad568ea1c551938e673c7a0' diff -r f88c2a41200d -r af0b9c6cbeb8 ChangeLog.API --- a/ChangeLog.API Sun Jun 17 04:50:18 2007 +0000 +++ b/ChangeLog.API Sun Jun 17 05:09:21 2007 +0000 @@ -13,8 +13,6 @@ UIs can now use better scheduling for whole-second timers. For example, clients based on the glib event loop can now use g_timeout_add_seconds. - * gtk_imhtml_setup_entry - * pidgin_create_window * purple_blist_node_get_type * purple_conversation_do_command * purple_conversation_get_extended_menu @@ -22,8 +20,6 @@ This is for UIs to use to ensure only one copy is running. * purple_dbus_is_owner * purple_image_data_calculate_filename - * pidgin_retrieve_user_info, shows immediate feedback when getting - information about a user. * purple_timeout_add_seconds Callers should prefer this to purple_timeout_add for timers longer than 1 second away. Be aware of the rounding, though. @@ -31,8 +27,7 @@ Callers should prefer this to purple_timeout_add for timers longer than 1 second away. Be aware of the rounding, though. * purple_xfer_get_remote_user - * gtk_imhtml_animation_new - Can be used for inserting an animated image into an IMHTML. + * purple_pounces_get_all_for_ui Changed: * The documentation of the following functions now properly @@ -68,6 +63,14 @@ GLists. The passed list is still not modified or freed. Pidgin: + Added: + * gtk_imhtml_setup_entry + * pidgin_create_window + * pidgin_retrieve_user_info, shows immediate feedback when getting + information about a user. + * gtk_imhtml_animation_new + Can be used for inserting an animated image into an IMHTML. + Changed: * pidgin_append_menu_action returns the menuitem added to the menu. * pidgin_separator returns the separator added to the menu. diff -r f88c2a41200d -r af0b9c6cbeb8 finch/gntft.c --- a/finch/gntft.c Sun Jun 17 04:50:18 2007 +0000 +++ b/finch/gntft.c Sun Jun 17 05:09:21 2007 +0000 @@ -411,7 +411,7 @@ size_str = purple_str_size_to_units(purple_xfer_get_size(xfer)); remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer)); - kbsec = g_strdup_printf(_("%.2f KB/s"), kbps); + kbsec = g_strdup_printf(_("%.2f KiB/s"), kbps); gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS, g_ascii_dtostr(prog_str, sizeof(prog_str), purple_xfer_get_progress(xfer) * 100.)); diff -r f88c2a41200d -r af0b9c6cbeb8 finch/gntpounce.c --- a/finch/gntpounce.c Sun Jun 17 04:50:18 2007 +0000 +++ b/finch/gntpounce.c Sun Jun 17 05:09:21 2007 +0000 @@ -141,8 +141,8 @@ gnt_tree_remove_all(GNT_TREE(dialog->tree)); - for (pounces = purple_pounces_get_all(); pounces != NULL; - pounces = g_list_next(pounces)) + for (pounces = purple_pounces_get_all_for_ui(FINCH_UI); pounces != NULL; + pounces = g_list_delete_link(pounces, pounces)) { add_pounce_to_treeview(GNT_TREE(dialog->tree), pounces->data); } diff -r f88c2a41200d -r af0b9c6cbeb8 finch/plugins/Makefile.am --- a/finch/plugins/Makefile.am Sun Jun 17 04:50:18 2007 +0000 +++ b/finch/plugins/Makefile.am Sun Jun 17 05:09:21 2007 +0000 @@ -28,7 +28,7 @@ endif # PLUGINS -EXTRA_DIST = +EXTRA_DIST = pietray.py AM_CPPFLAGS = \ -DDATADIR=\"$(datadir)\" \ diff -r f88c2a41200d -r af0b9c6cbeb8 finch/plugins/pietray.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/finch/plugins/pietray.py Sun Jun 17 05:09:21 2007 +0000 @@ -0,0 +1,183 @@ +#!/usr/bin/env python + +# This is a dbus script to show a docklet for Finch. This should work +# for any 'compatible' purple client. +# +# By 'compatible', I mean any client that sets and updates the +# "unseen-count" data on the conversations. +# +# It allows doing the following things: +# - It allows changing status. +# - It shows the current status and info about unread messages in +# the tooltip. +# - It can blink on unread IM/Chat messages, and it allows canging +# the preference for that. +# +# It requires GTK+ 2.10 or above, since it uses GtkStatusIcon. +# +# Sadrul + +import pygtk +pygtk.require("2.0") +import gtk +import dbus, gobject, dbus.glib +import os # to get the pkg-config output + +bus = dbus.SessionBus() +obj = bus.get_object( + "im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject") +purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface") + +def pack_image_label(menu, image, label): + item = gtk.ImageMenuItem(label) + if image: + img = gtk.Image() + img.set_from_stock(image, 1) + item.set_image(img) + menu.append(item) + return item + +def activate_primitive_status(item, status): + saved = purple.PurpleSavedstatusFindTransientByTypeAndMessage(status, "") + if not saved: + saved = purple.PurpleSavedstatusNew("", status) + purple.PurpleSavedstatusActivate(saved) + +def activate_popular_status(item, time): + saved = purple.PurpleSavedstatusFindByCreationTime(time) + if saved: + purple.PurpleSavedstatusActivate(saved) + +def generate_status_menu(menu): + item = gtk.MenuItem("Available") + item.connect("activate", activate_primitive_status, 2) + menu.append(item) + + item = gtk.MenuItem("Away") + item.connect("activate", activate_primitive_status, 5) + menu.append(item) + + item = gtk.MenuItem("Invisible") + item.connect("activate", activate_primitive_status, 4) + menu.append(item) + + item = gtk.MenuItem("Offline") + item.connect("activate", activate_primitive_status, 1) + menu.append(item) + + menu.append(gtk.MenuItem()) + + popular = purple.PurpleSavedstatusesGetPopular(10) + for pop in popular: + title = purple.PurpleSavedstatusGetTitle(pop).replace('_', '__') + item = gtk.MenuItem(title) + item.set_data("timestamp", purple.PurpleSavedstatusGetCreationTime(pop)) + item.connect("activate", activate_popular_status, purple.PurpleSavedstatusGetCreationTime(pop)) + menu.append(item) + +def toggle_pref(item, pref): + purple.PurplePrefsSetBool(pref, item.get_active()) + +def popup_menu(icon, button, tm, none): + menu = gtk.Menu() + + item = gtk.CheckMenuItem("Blink for unread IM") + item.set_active(purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/im")) + item.connect("activate", toggle_pref, "/plugins/dbus/docklet/blink/im") + menu.append(item) + + item = gtk.CheckMenuItem("Blink for unread Chats") + item.set_active(purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/chat")) + item.connect("activate", toggle_pref, "/plugins/dbus/docklet/blink/chat") + menu.append(item) + + menu.append(gtk.MenuItem()) + + #item = pack_image_label(menu, None, "Change Status...") + item = gtk.MenuItem("Change Status...") + menu.append(item) + submenu = gtk.Menu() + item.set_submenu(submenu) + generate_status_menu(submenu) + + menu.show_all() + menu.popup(None, None, None, button, tm) + +def get_status_message(): + status = purple.PurpleSavedstatusGetCurrent() + msg = purple.PurpleSavedstatusGetMessage(status) + if msg and len(msg) > 0: + text = msg + " " + else: + text = "" + text = text + "(" + { + 2: "Available", + 5: "Away", + 4: "Invisible", + 1: "Offline" + }[purple.PurpleSavedstatusGetType(status)] + ")" + return text + +def detect_unread_conversations(): + im = purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/im") + chat = purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/chat") + tooltip = "" + blink = False + if im and chat: + convs = purple.PurpleGetConversations() + elif im: + convs = purple.PurpleGetIms() + elif chat: + convs = purple.PurpleGetChats() + else: + convs = None + for conv in convs: + count = purple.PurpleConversationGetData(conv, "unseen-count") + if count and count > 0: + blink = True + tooltip = tooltip + "\n" + purple.PurpleConversationGetName(conv) + " (" + str(count) + ")" + t.set_from_file(path + "/share/pixmaps/pidgin.png") + if blink: + # I hate this icon + # t.set_from_file(path + "/share/pixmaps/pidgin/tray/22/tray-message.png") + tooltip = "\nUnread Messages:" + tooltip + # There's going to be some way to expose the client's display name in 2.1.0. + # Use that instead of hardcoding Finch here. + t.set_tooltip("Finch: " + get_status_message() + tooltip) + t.set_blinking(blink) + +def conversation_updated(conv, type): + detect_unread_conversations() + +def savedstatus_changed(new, old): + # Change the icon for status perhaps? + detect_unread_conversations() + +def init_prefs(): + if not purple.PurplePrefsExists("/plugins/dbus/docklet/blink"): + purple.PurplePrefsAddNone("/plugins") + purple.PurplePrefsAddNone("/plugins/dbus") + purple.PurplePrefsAddNone("/plugins/dbus/docklet") + purple.PurplePrefsAddNone("/plugins/dbus/docklet/blink") + purple.PurplePrefsAddBool("/plugins/dbus/docklet/blink/im", True) + purple.PurplePrefsAddBool("/plugins/dbus/docklet/blink/chat", True) + +pkg = os.popen("pkg-config --variable=prefix pidgin") +path = pkg.readline().rstrip() + +bus.add_signal_receiver(conversation_updated, + dbus_interface="im.pidgin.purple.PurpleInterface", + signal_name="ConversationUpdated") + +bus.add_signal_receiver(savedstatus_changed, + dbus_interface="im.pidgin.purple.PurpleInterface", + signal_name="SavedstatusChanged") + +t = gtk.StatusIcon() +t.connect("popup-menu", popup_menu, None) + +init_prefs() +detect_unread_conversations() + +gtk.main () + diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/blist.c --- a/libpurple/blist.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/blist.c Sun Jun 17 05:09:21 2007 +0000 @@ -35,8 +35,6 @@ #include "value.h" #include "xmlnode.h" -#define PATHSIZE 1024 - static PurpleBlistUiOps *blist_ui_ops = NULL; static PurpleBuddyList *purplebuddylist = NULL; diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/core.c --- a/libpurple/core.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/core.c Sun Jun 17 05:09:21 2007 +0000 @@ -489,13 +489,33 @@ /* We're only going to duplicate a logs symlink. */ if (!strcmp(entry, "logs")) { + char *link; +#if GLIB_CHECK_VERSION(2,4,0) + GError *err = NULL; + + if ((link = g_file_read_link(name, &err)) == NULL) + { + char *name_utf8 = g_filename_to_utf8(name, -1, NULL, NULL, NULL); + purple_debug_error("core", "Error reading symlink %s: %s. Please report this at http://developer.pidgin.im\n", + name_utf8 ? name_utf8 : name, err->message); + g_free(name_utf8); + g_error_free(err); + g_free(name); + g_dir_close(dir); + g_free(status_file); + g_free(old_user_dir); + return FALSE; + } +#else char buf[MAXPATHLEN]; size_t linklen; if ((linklen = readlink(name, buf, sizeof(buf) - 1) == -1)) { + char *name_utf8 = g_filename_to_utf8(name); purple_debug_error("core", "Error reading symlink %s: %s. Please report this at http://developer.pidgin.im\n", - name, strerror(errno)); + name_utf8, strerror(errno)); + g_free(name_utf8); g_free(name); g_dir_close(dir); g_free(status_file); @@ -504,13 +524,18 @@ } buf[linklen] = '\0'; - logs_dir = g_strconcat(user_dir, G_DIR_SEPARATOR_S "logs", NULL); + /* This way we don't have to GLIB_VERSION_CHECK every g_free(link) below. */ + link = g_strdup(buf); +#endif - if (!strcmp(buf, "../.purple/logs") || !strcmp(buf, logs_dir)) + logs_dir = g_build_filename(user_dir, "logs", NULL); + + if (!strcmp(link, "../.purple/logs") || !strcmp(link, logs_dir)) { /* If the symlink points to the new directory, we're * likely just trying again after a failed migration, * so there's no need to fail here. */ + g_free(link); g_free(logs_dir); continue; } @@ -522,12 +547,13 @@ g_unlink(logs_dir); /* Relative links will most likely still be - * valid from ~/.purple, though not it's not + * valid from ~/.purple, though it's not * guaranteed. Oh well. */ - if (symlink(buf, logs_dir)) + if (symlink(link, logs_dir)) { purple_debug_error("core", "Error symlinking %s to %s: %s. Please report this at http://developer.pidgin.im\n", - logs_dir, buf, strerror(errno)); + logs_dir, link, strerror(errno)); + g_free(link); g_free(name); g_free(logs_dir); g_dir_close(dir); @@ -536,6 +562,7 @@ return FALSE; } + g_free(link); g_free(logs_dir); continue; } diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/dbus-analyze-functions.py --- a/libpurple/dbus-analyze-functions.py Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/dbus-analyze-functions.py Sun Jun 17 05:09:21 2007 +0000 @@ -3,7 +3,7 @@ import sys # types translated into "int" -simpletypes = ["int", "gint", "guint", "gboolean"] +simpletypes = ["int", "gint", "guint", "gboolean", "gpointer", "size_t", "gssize", "time_t"] # List "excluded" contains functions that shouldn't be exported via # DBus. If you remove a function from this list, please make sure @@ -119,21 +119,26 @@ def processinput(self, type, name): const = False + unsigned = False if type[0] == "const": type = type[1:] const = True + if type[0] == "unsigned": + type = type[1:] + unsigned = True + if len(type) == 1: # simple types (int, gboolean, etc.) and enums if (type[0] in simpletypes) or ((type[0].startswith("Purple") and not type[0].endswith("Callback"))): - return self.inputsimple(type, name) + return self.inputsimple(type, name, unsigned) # pointers ... if (len(type) == 2) and (type[1] == pointer): # strings if type[0] in ["char", "gchar"]: if const: - return self.inputstring(type, name) + return self.inputstring(type, name, unsigned) else: raise myexception @@ -232,12 +237,18 @@ print "typedef struct _%s %s;" % (type[0], type[0]) self.knowntypes.append(type[0]) - def inputsimple(self, type, name): + def inputsimple(self, type, name, us): self.paramshdr.append("%s %s" % (type[0], name)) - self.inputparams.append(("G_TYPE_INT", name)) + if us: + self.inputparams.append(("G_TYPE_UINT", name)) + else: + self.inputparams.append(("G_TYPE_INT", name)) - def inputstring(self, type, name): - self.paramshdr.append("const char *%s" % name) + def inputstring(self, type, name, us): + if us: + self.paramshdr.append("const unsigned char *%s" % name) + else: + self.paramshdr.append("const char *%s" % name) self.inputparams.append(("G_TYPE_STRING", name)) def inputpurplestructure(self, type, name): @@ -348,15 +359,23 @@ # input parameters - def inputsimple(self, type, name): - self.cdecls.append("\tdbus_int32_t %s;" % name) - self.cparams.append(("INT32", name)) - self.addintype("i", name) + def inputsimple(self, type, name, us): + if us: + self.cdecls.append("\tdbus_int32_t %s;" % name) + self.cparams.append(("INT32", name)) + self.addintype("i", name) + else: + self.cdecls.append("\tdbus_uint32_t %s;" % name) + self.cparams.append(("UINT32", name)) + self.addintype("u", name) - def inputstring(self, type, name): - self.cdecls.append("\tconst char *%s;" % name) + def inputstring(self, type, name, us): + if us: + self.cdecls.append("\tconst unsigned char *%s;" % name) + else: + self.cdecls.append("\tconst char *%s;" % name) self.cparams.append(("STRING", name)) - self.ccode .append("\tNULLIFY(%s);" % name) + self.ccode.append("\t%s = (%s && %s[0]) ? %s : NULL;" % (name,name,name,name)) self.addintype("s", name) def inputhash(self, type, name): diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/dbus-server.c --- a/libpurple/dbus-server.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/dbus-server.c Sun Jun 17 05:09:21 2007 +0000 @@ -120,7 +120,7 @@ if ((id == 0) && (node != NULL)) { purple_debug_warning("dbus", - "Need to register an object with the dbus subsystem.\n"); + "Need to register an object with the dbus subsystem. (If you are not a developer, please ignore this message.)\n"); return 0; } return id; @@ -760,7 +760,7 @@ dbus_message_iter_init_append(signal, &iter); if (purple_dbus_message_append_purple_values(&iter, num_values, values, vargs)) - purple_debug_warning("dbus", "The signal \"%s\" caused some dbus error.\n", name); + purple_debug_warning("dbus", "The signal \"%s\" caused some dbus error. (If you are not a developer, please ignore this message.)\n", name); dbus_connection_send(purple_dbus_connection, signal, NULL); @@ -797,8 +797,18 @@ void purple_dbus_uninit(void) { - /* Surely we must do SOME kind of uninitialization? */ + DBusError error; + if (!purple_dbus_connection) + return; + dbus_error_init(&error); + dbus_connection_unregister_object_path(purple_dbus_connection, DBUS_PATH_PURPLE); + dbus_bus_release_name(purple_dbus_connection, DBUS_SERVICE_PURPLE, &error); + dbus_error_free(&error); + dbus_connection_unref(purple_dbus_connection); + purple_dbus_connection = NULL; + purple_signals_disconnect_by_handle(purple_dbus_get_handle()); g_free(init_error); init_error = NULL; } + diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/internal.h --- a/libpurple/internal.h Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/internal.h Sun Jun 17 05:09:21 2007 +0000 @@ -111,16 +111,10 @@ # include #endif -#ifndef MAXPATHLEN -# define MAXPATHLEN 1024 -#endif - #ifndef HOST_NAME_MAX # define HOST_NAME_MAX 255 #endif -#define PATHSIZE 1024 - #include #if !GLIB_CHECK_VERSION(2,4,0) # define G_MAXUINT32 ((guint32) 0xffffffff) diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/plugins/startup.py --- a/libpurple/plugins/startup.py Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/plugins/startup.py Sun Jun 17 05:09:21 2007 +0000 @@ -25,6 +25,13 @@ import dbus import os +if len(sys.argv) == 1: + print "Usage:", sys.argv[0], """ [arguments] + +Example: + """, sys.argv[0], "pidgin -d -c /my/home" + sys.exit(1) + home = os.path.expanduser('~/.purple/') for arg in range(1, len(sys.argv[1:])): if sys.argv[arg] == "-c": diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/pounce.c --- a/libpurple/pounce.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/pounce.c Sun Jun 17 05:09:21 2007 +0000 @@ -1014,6 +1014,20 @@ return pounces; } +GList *purple_pounces_get_all_for_ui(const char *ui) +{ + GList *list = NULL, *iter; + g_return_val_if_fail(ui != NULL, NULL); + + for (iter = pounces; iter; iter = iter->next) { + PurplePounce *pounce = iter->data; + if (pounce->ui_type && strcmp(pounce->ui_type, ui) == 0) + list = g_list_prepend(list, pounce); + } + list = g_list_reverse(list); + return list; +} + static void free_pounce_handler(gpointer user_data) { diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/pounce.h --- a/libpurple/pounce.h Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/pounce.h Sun Jun 17 05:09:21 2007 +0000 @@ -343,6 +343,17 @@ GList *purple_pounces_get_all(void); /** + * Returns a list of registered buddy pounces for the ui-type. + * + * @param ui The ID of the UI using the core. + * + * @return The list of buddy pounces. The list should be freed by + * the caller when it's no longer used. + * @since 2.1.0 + */ +GList *purple_pounces_get_all_for_ui(const char *ui); + +/** * Returns the buddy pounce subsystem handle. * * @return The subsystem handle. diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/protocols/oscar/oscar.c --- a/libpurple/protocols/oscar/oscar.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/protocols/oscar/oscar.c Sun Jun 17 05:09:21 2007 +0000 @@ -2827,6 +2827,7 @@ va_list ap; guint16 reason; char *destn; + PurpleNotifyUserInfo *user_info; va_start(ap, fr); reason = (guint16) va_arg(ap, unsigned int); @@ -2836,12 +2837,12 @@ if (destn == NULL) return 1; + user_info = purple_notify_user_info_new(); buf = g_strdup_printf(_("User information not available: %s"), (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); - if (!purple_conv_present_error(destn, purple_connection_get_account((PurpleConnection*)od->gc), buf)) { - g_free(buf); - buf = g_strdup_printf(_("User information for %s unavailable:"), destn); - purple_notify_error(od->gc, NULL, buf, (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason.")); - } + purple_notify_user_info_add_pair(user_info, NULL, buf); + purple_notify_userinfo(od->gc, destn, user_info, NULL, NULL); + purple_notify_user_info_destroy(user_info); + purple_conv_present_error(destn, purple_connection_get_account(od->gc), buf); g_free(buf); return 1; diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/protocols/qq/group_im.c --- a/libpurple/protocols/qq/group_im.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/protocols/qq/group_im.c Sun Jun 17 05:09:21 2007 +0000 @@ -341,7 +341,7 @@ read_packet_dw(data, cursor, data_len, &(im_group->member_uid)); read_packet_w(data, cursor, data_len, &unknown); /* 0x0001? */ read_packet_w(data, cursor, data_len, &(im_group->msg_seq)); - read_packet_dw(data, cursor, data_len, (guint32 *) & (im_group->send_time)); + read_packet_time(data, cursor, data_len, &im_group->send_time); read_packet_dw(data, cursor, data_len, &unknown4); /* versionID */ /* * length includes font_attr diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/protocols/qq/login_logout.c --- a/libpurple/protocols/qq/login_logout.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/protocols/qq/login_logout.c Sun Jun 17 05:09:21 2007 +0000 @@ -181,7 +181,7 @@ /* 031-032: server listening port */ bytes += read_packet_w(data, &cursor, len, &lrop.server_port); /* 033-036: login time for current session */ - bytes += read_packet_dw(data, &cursor, len, (guint32 *) &lrop.login_time); + bytes += read_packet_time(data, &cursor, len, &lrop.login_time); /* 037-062: 26 bytes, unknown */ bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown1, 26); /* 063-066: unknown server1 ip address */ @@ -203,7 +203,7 @@ /* 123-126: login IP of last session */ bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.last_client_ip, 4); /* 127-130: login time of last session */ - bytes += read_packet_dw(data, &cursor, len, (guint32 *) &lrop.last_login_time); + bytes += read_packet_time(data, &cursor, len, &lrop.last_login_time); /* 131-138: 8 bytes unknown */ bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown6, 8); diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/protocols/qq/packet_parse.c --- a/libpurple/protocols/qq/packet_parse.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/protocols/qq/packet_parse.c Sun Jun 17 05:09:21 2007 +0000 @@ -65,6 +65,19 @@ } } +/* read four bytes as "time_t" from buf, + * return the number of bytes read if succeeds, otherwise return -1 + * This function is a wrapper around read_packet_dw() to avoid casting. */ +gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t) +{ + guint32 time; + gint ret = read_packet_dw(buf, cursor, buflen, &time); + if (ret != -1 ) { + *t = time; + } + return ret; +} + /* read datalen bytes from buf, * return the number of bytes read if succeeds, otherwise return -1 */ gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen) { diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/protocols/qq/packet_parse.h --- a/libpurple/protocols/qq/packet_parse.h Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/protocols/qq/packet_parse.h Sun Jun 17 05:09:21 2007 +0000 @@ -39,6 +39,7 @@ gint read_packet_b(guint8 *buf, guint8 **cursor, gint buflen, guint8 *b); gint read_packet_w(guint8 *buf, guint8 **cursor, gint buflen, guint16 *w); gint read_packet_dw(guint8 *buf, guint8 **cursor, gint buflen, guint32 *dw); +gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t); gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen); gint create_packet_b(guint8 *buf, guint8 **cursor, guint8 b); gint create_packet_w(guint8 *buf, guint8 **cursor, guint16 w); diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/protocols/yahoo/yahoo_doodle.c --- a/libpurple/protocols/yahoo/yahoo_doodle.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/protocols/yahoo/yahoo_doodle.c Sun Jun 17 05:09:21 2007 +0000 @@ -491,7 +491,8 @@ /* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */ - yahoo_doodle_command_send_shutdown(gc, wb->who); + if (gc) + yahoo_doodle_command_send_shutdown(gc, wb->who); g_free(wb->proto_data); } diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/protocols/zephyr/ZLocations.c --- a/libpurple/protocols/zephyr/ZLocations.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/protocols/zephyr/ZLocations.c Sun Jun 17 05:09:21 2007 +0000 @@ -36,7 +36,8 @@ return (Z_SendLocation(LOGIN_CLASS, LOGIN_USER_FLUSH, ZAUTH, "")); } -static char host[MAXHOSTNAMELEN], mytty[MAXPATHLEN]; +static char host[MAXHOSTNAMELEN]; +static char *mytty = NULL; static int reenter = 0; Code_t Z_SendLocation(class, opcode, auth, format) @@ -87,21 +88,20 @@ } #ifndef X_DISPLAY_MISSING if ((display = getenv("DISPLAY")) && *display) { - (void) strncpy(mytty, display, sizeof(mytty)); + mytty = g_strdup(display); } else { #endif #ifdef WIN32 - strncpy(mytty, "WinPurple", sizeof(mytty)); + mytty = g_strdup("WinPurple"); #else ttyp = ttyname(0); if (ttyp && *ttyp) { p = strchr(ttyp + 1, '/'); - strcpy(mytty, (p) ? p + 1 : ttyp); + mytty = g_strdup((p) ? p + 1 : ttyp); } else { - strncpy(mytty, "unknown", sizeof(mytty)); + mytty = g_strdup("unknown"); } #endif - mytty[sizeof(mytty)-1] = '\0'; #ifndef X_DISPLAY_MISSING } #endif @@ -114,7 +114,6 @@ bptr[1][strlen(bptr[1])-1] = '\0'; bptr[2] = mytty; - if ((retval = ZSendList(¬ice, bptr, 3, auth)) != ZERR_NONE) return (retval); diff -r f88c2a41200d -r af0b9c6cbeb8 libpurple/util.c --- a/libpurple/util.c Sun Jun 17 04:50:18 2007 +0000 +++ b/libpurple/util.c Sun Jun 17 05:09:21 2007 +0000 @@ -66,8 +66,8 @@ unsigned long data_len; }; -static char custom_home_dir[MAXPATHLEN]; -static char home_dir[MAXPATHLEN] = ""; +static char *custom_user_dir = NULL; +static char *home_dir = NULL; PurpleMenuAction * purple_menu_action_new(const char *label, PurpleCallback callback, gpointer data, @@ -2396,27 +2396,22 @@ const char * purple_user_dir(void) { - if (custom_home_dir != NULL && *custom_home_dir) { - strcpy ((char*) &home_dir, (char*) &custom_home_dir); - } else if (!*home_dir) { - const gchar *hd = purple_home_dir(); - - if (hd) { - g_strlcpy((char*) &home_dir, hd, sizeof(home_dir)); - g_strlcat((char*) &home_dir, G_DIR_SEPARATOR_S ".purple", - sizeof(home_dir)); - } - } + if (custom_user_dir != NULL) + return custom_user_dir; + else if (!home_dir) + home_dir = g_build_filename(purple_home_dir(), ".purple", NULL); return home_dir; } void purple_util_set_user_dir(const char *dir) { - if (dir != NULL && strlen(dir) > 0) { - g_strlcpy((char*) &custom_home_dir, dir, - sizeof(custom_home_dir)); - } + g_free(custom_user_dir); + + if (dir != NULL && *dir) + custom_user_dir = g_strdup(dir); + else + custom_user_dir = NULL; } int purple_build_dir (const char *path, int mode) @@ -3135,7 +3130,7 @@ char * purple_str_size_to_units(size_t size) { - static const char *size_str[4] = { "bytes", "KB", "MB", "GB" }; + static const char *size_str[4] = { "bytes", "KiB", "MiB", "GiB" }; float size_mag; int size_index = 0; diff -r f88c2a41200d -r af0b9c6cbeb8 pidgin/gtkft.c --- a/pidgin/gtkft.c Sun Jun 17 04:50:18 2007 +0000 +++ b/pidgin/gtkft.c Sun Jun 17 05:09:21 2007 +0000 @@ -130,7 +130,7 @@ kbps = (elapsed > 0 ? (kb_sent / elapsed) : 0); if (kbsec != NULL) { - *kbsec = g_strdup_printf(_("%.2f KB/s"), kbps); + *kbsec = g_strdup_printf(_("%.2f KiB/s"), kbps); } if (time_elapsed != NULL) diff -r f88c2a41200d -r af0b9c6cbeb8 pidgin/gtkmain.c --- a/pidgin/gtkmain.c Sun Jun 17 04:50:18 2007 +0000 +++ b/pidgin/gtkmain.c Sun Jun 17 05:09:21 2007 +0000 @@ -372,6 +372,7 @@ " -c, --config=DIR use DIR for config files\n" " -d, --debug print debugging messages to stdout\n" " -h, --help display this help and exit\n" + " -m, --multiple do not ensure single instance\n" " -n, --nologin don't automatically login\n" " -l, --login[=NAME] automatically login (optional argument NAME specifies\n" " account(s) to use, separated by commas)\n" @@ -431,6 +432,7 @@ gboolean opt_login = FALSE; gboolean opt_nologin = FALSE; gboolean opt_version = FALSE; + gboolean opt_si = TRUE; /* Check for single instance? */ char *opt_config_dir_arg = NULL; char *opt_login_arg = NULL; char *opt_session_arg = NULL; @@ -457,6 +459,7 @@ {"debug", no_argument, NULL, 'd'}, {"help", no_argument, NULL, 'h'}, {"login", optional_argument, NULL, 'l'}, + {"multiple", no_argument, NULL, 'm'}, {"nologin", no_argument, NULL, 'n'}, {"session", required_argument, NULL, 's'}, {"version", no_argument, NULL, 'v'}, @@ -570,7 +573,7 @@ opterr = 1; while ((opt = getopt_long(argc, argv, #ifndef _WIN32 - "c:dhnl::s:v", + "c:dhmnl::s:v", #else "c:dhnl::v", #endif @@ -602,6 +605,9 @@ case 'v': /* version */ opt_version = TRUE; break; + case 'm': /* do not ensure single instance. */ + opt_si = FALSE; + break; case '?': /* show terse help */ default: show_usage(argv[0], TRUE); @@ -728,7 +734,7 @@ abort(); } - if (!purple_core_ensure_single_instance()) { + if (opt_si && !purple_core_ensure_single_instance()) { purple_core_quit(); #ifdef HAVE_SIGNAL_H g_free(segfault_message); diff -r f88c2a41200d -r af0b9c6cbeb8 pidgin/gtkpounce.c --- a/pidgin/gtkpounce.c Sun Jun 17 04:50:18 2007 +0000 +++ b/pidgin/gtkpounce.c Sun Jun 17 05:09:21 2007 +0000 @@ -215,8 +215,8 @@ gtk_list_store_clear(dialog->model); - for (pounces = purple_pounces_get_all(); pounces != NULL; - pounces = g_list_next(pounces)) + for (pounces = purple_pounces_get_all_for_ui(PIDGIN_UI); pounces != NULL; + pounces = g_list_delete_link(pounces, pounces)) { add_pounce_to_treeview(dialog->model, pounces->data); } diff -r f88c2a41200d -r af0b9c6cbeb8 pidgin/gtkutils.c --- a/pidgin/gtkutils.c Sun Jun 17 04:50:18 2007 +0000 +++ b/pidgin/gtkutils.c Sun Jun 17 05:09:21 2007 +0000 @@ -525,7 +525,7 @@ { PurplePluginProtocolInfo *prpl_info; const char *protoname = NULL; - char buf[MAXPATHLEN]; + char *tmp; char *filename = NULL; GdkPixbuf *pixbuf; @@ -541,12 +541,14 @@ * Status icons will be themeable too, and then it will look up * protoname from the theme */ - g_snprintf(buf, sizeof(buf), "%s.png", protoname); + tmp = g_strconcat(protoname, ".png", NULL); filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols", size == PIDGIN_PRPL_ICON_SMALL ? "16" : size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48", - buf, NULL); + tmp, NULL); + g_free(tmp); + pixbuf = gdk_pixbuf_new_from_file(filename, NULL); g_free(filename);