changeset 148:4e9d0fd93fb6

- in saving icon file for twitter, proper extension is used. - pointers to hash tables are organized as an array. - removed unused code. - resolved redundant code with hash table array.
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Thu, 24 Jul 2008 21:00:34 +0900
parents 3abee459c81c
children 0594a81d967d
files pidgin-twitter.c pidgin-twitter.h
diffstat 2 files changed, 180 insertions(+), 145 deletions(-) [+]
line wrap: on
line diff
--- a/pidgin-twitter.c	Thu Jul 24 06:40:41 2008 +0900
+++ b/pidgin-twitter.c	Thu Jul 24 21:00:34 2008 +0900
@@ -26,12 +26,12 @@
 #define NUM_REGP 10
 static GRegex *regp[NUM_REGP];
 static gboolean suppress_oops = FALSE;
-static GHashTable *icon_data_by_user  = NULL; // twitter
-static GHashTable *icon_data_by_user2 = NULL; // wassr
-static GHashTable *icon_data_by_user3 = NULL; // identi.ca
+static GHashTable *icon_hash[3]; /* twitter, wassr, identica. */
 static GHashTable *conv_hash = NULL;
+
 static GList *statuseslist = NULL;
 static GList *postedlist = NULL;
+
 static gchar *wassr_post = NULL;
 static gchar *identica_post = NULL;
 
@@ -90,7 +90,7 @@
     gchar *head, *tail;     /* head and tail of html */
     gchar *begin, *end;     /* begin:<  end:> */
     gchar *html, *str;      /* copied src and str to be returned */
-//    gchar *vis1, *vis2;     /* begin and end of address part */
+/*    gchar *vis1, *vis2; */     /* begin and end of address part */
     gchar *startp;          /* starting point marker */
     gchar **tagp;           /* tag iterator */
     gchar *tmp, *tmp2;      /* scratches */
@@ -511,7 +511,7 @@
 
     PurpleConversation *conv = (PurpleConversation *)data;
     if(!conv)
-        return FALSE; //cease fetch
+        return FALSE; /* cease fetch */
 
     const char *screen_name =
         purple_prefs_get_string(OPT_SCREEN_NAME_TWITTER);
@@ -817,8 +817,8 @@
         g_free(match);
     }
     else if(which == SENDER) {
-        gchar *match1 = g_match_info_fetch(match_info, 1); //preceding CR|LF
-        gchar *match2 = g_match_info_fetch(match_info, 2); //sender
+        gchar *match1 = g_match_info_fetch(match_info, 1); /*preceding CR|LF*/
+        gchar *match2 = g_match_info_fetch(match_info, 2); /* sender */
         const gchar *format = NULL;
 
         switch(service) {
@@ -842,8 +842,8 @@
         g_free(match2);
     }
     else if(service == wassr_service && which == CHANNEL) {
-        gchar *match1 = g_match_info_fetch(match_info, 1); //before channel
-        gchar *match2 = g_match_info_fetch(match_info, 2); //channel
+        gchar *match1 = g_match_info_fetch(match_info, 1); /*before channel*/
+        gchar *match2 = g_match_info_fetch(match_info, 2); /* channel */
         const gchar *format = CHANNEL_FORMAT_WASSR;
 
         g_snprintf(sub, 128, format, match1 ? match1: "", match2, match2);
@@ -869,14 +869,14 @@
     data->service = service;
 
     regp_id = which; /* for future use --yaz */
-    newstr = g_regex_replace_eval(regp[regp_id],  // compiled regex
-                                  *str, // subject string
-                                  -1,   // length of the subject string
-                                  0,    // start position
-                                  0,    // match options
-                                  eval, // function to be called for each match
-                                  data,   // user data
-                                  NULL);    // error handler
+    newstr = g_regex_replace_eval(regp[regp_id],  /* compiled regex */
+                                  *str,  /* subject string */
+                                  -1,    /* length of the subject string */
+                                  0,     /* start position */
+                                  0,     /* match options */
+                                  eval,  /* function to be called for each match */
+                                  data,  /* user data */
+                                  NULL); /* error handler */
 
     g_free(data); data = NULL;
 
@@ -1128,10 +1128,6 @@
         gint service = get_service_type(conv);
         switch(service) {
         case twitter_service:
-#if 0
-            if(purple_prefs_get_bool(OPT_API_BASE_POST))
-                g_source_remove_by_user_data((gpointer)conv);
-#endif
             detach_from_conv(conv, NULL);
             break;
         case wassr_service:
@@ -1420,7 +1416,7 @@
     /* only attach to twitter conversation window */
     switch(service) {
     case twitter_service:
-        /* api based retrieve */ //xxx should configurable
+        /* api based retrieve */ /* xxx should configurable */
         if(purple_prefs_get_bool(OPT_API_BASE_POST)) {
             get_status_with_api((gpointer)conv);
             g_timeout_add_seconds(
@@ -1456,13 +1452,13 @@
     case twitter_service:
         if(purple_prefs_get_bool(OPT_API_BASE_POST))
             g_source_remove_by_user_data((gpointer)conv);
-        hash = icon_data_by_user;
+        hash = icon_hash[twitter_service];
         break;
     case wassr_service:
-        hash = icon_data_by_user2;
+        hash = icon_hash[wassr_service];
         break;
     case identica_service:
-        hash = icon_data_by_user3;
+        hash = icon_hash[identica_service];
         break;
     default:
         twitter_debug("unknown service\n");
@@ -1594,13 +1590,13 @@
     /* insert icon */
     switch(service) {
     case twitter_service:
-        hash = icon_data_by_user;
+        hash = icon_hash[twitter_service];
         break;
     case wassr_service:
-        hash = icon_data_by_user2;
+        hash = icon_hash[wassr_service];
         break;
     case identica_service:
-        hash = icon_data_by_user3;
+        hash = icon_hash[identica_service];
         break;
     default:
         twitter_debug("unknown service\n");
@@ -1641,13 +1637,13 @@
 
     switch(service) {
     case twitter_service:
-        hash = icon_data_by_user;
+        hash = icon_hash[twitter_service];
         break;
     case wassr_service:
-        hash = icon_data_by_user2;
+        hash = icon_hash[wassr_service];
         break;
     case identica_service:
-        hash = icon_data_by_user3;
+        hash = icon_hash[identica_service];
         break;
     default:
         twitter_debug("unknown service\n");
@@ -1691,18 +1687,18 @@
     gchar *url = NULL;
     gint regp_id = -1;
 
+    if(service == twitter_service) {
+        data = (icon_data *)g_hash_table_lookup(
+            icon_hash[twitter_service], user_name);
+        regp_id = IMAGE_TWITTER;
+    }
+
     if(service == identica_service) {
         data = (icon_data *)g_hash_table_lookup(
-            icon_data_by_user3, user_name);
+            icon_hash[identica_service], user_name);
         regp_id = IMAGE_IDENTICA;
     }
 
-    if(service == twitter_service) {
-        data = (icon_data *)g_hash_table_lookup(
-            icon_data_by_user, user_name);
-        regp_id = IMAGE_TWITTER;
-    }
-
     if(!url_text) {
         if(data) {
             data->requested = FALSE;
@@ -1716,7 +1712,7 @@
     /* setup image url */
     g_regex_match(regp[regp_id], url_text, 0, &match_info);
     if(!g_match_info_matches(match_info)) {
-        twitter_debug("no image found\n");
+        twitter_debug("no image url found\n");
 
         g_match_info_free(match_info);
         if(data) {
@@ -1734,6 +1730,28 @@
     *slash = '\0';
     gchar *tmp = g_strdup_printf("%s/%s", url,
                                  purple_url_encode(slash+1));
+
+    gchar *startp = slash + 1;
+    gchar *ext = NULL;
+    do {
+        ext = strrchr(startp, '.');
+        if(ext) {
+            if(!strcasecmp(ext, ".jpg") || !strcasecmp(ext, ".jpeg")) {
+                data->img_type = "jpg";
+                break;
+            }
+            else if(!strcasecmp(ext, ".png")) {
+                data->img_type = "png";
+                break;
+            }
+            else if(!strcasecmp(ext, ".gif")) {
+                data->img_type = "gif";
+                break;
+            }
+            startp = ext;
+        }
+    } while(ext);
+
     g_free(url);
     url = tmp;
 
@@ -1780,6 +1798,13 @@
     return dest;
 }
 
+static gchar *ext_list[] = {
+    "png",
+    "gif",
+    "jpg",
+    NULL
+};
+
 /* this function will be called when requested icon has been retrieved */
 static void
 got_icon_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
@@ -1799,13 +1824,13 @@
 
     switch(service) {
     case twitter_service:
-        hash = icon_data_by_user;
+        hash = icon_hash[twitter_service];
         break;
     case wassr_service:
-        hash = icon_data_by_user2;
+        hash = icon_hash[wassr_service];
         break;
     case identica_service:
-        hash = icon_data_by_user3;
+        hash = icon_hash[identica_service];
         break;
     default:
         twitter_debug("unknown service\n");
@@ -1820,8 +1845,8 @@
                       user_name, error_message);
         if(data)
             data->requested = FALSE;
+
         goto fin_got_icon_cb;
-        return;
     }
 
     if(data) {
@@ -1833,8 +1858,8 @@
         if(data->icon_id > 0) {
             twitter_debug("%s's icon has already been downloaded\n",
                           user_name);
+
             goto fin_got_icon_cb;
-            return;
         }
     }
 
@@ -1848,6 +1873,7 @@
                                     gdk_pixbuf_get_rowstride(pixbuf) *
                                     gdk_pixbuf_get_height(pixbuf),
                                     user_name);
+
     if(!data) {
         twitter_debug("allocate icon_data (shouldn't be called)\n");
         data = g_new0(icon_data, 1);
@@ -1867,13 +1893,16 @@
 
         switch(service) {
         case twitter_service:
-            filename = g_strdup_printf("%s_twitter.gif", user_name);
+            filename = g_strdup_printf("%s_twitter.%s",
+                                       user_name, data->img_type);
             break;
         case wassr_service:
-            filename = g_strdup_printf("%s_wassr.png", user_name);
+            filename = g_strdup_printf("%s_wassr.%s",
+                                       user_name, data->img_type);
             break;
         case identica_service:
-            filename = g_strdup_printf("%s_identica.png", user_name);
+            filename = g_strdup_printf("%s_identica.%s",
+                                       user_name, data->img_type);
             break;
         default:
             twitter_debug("unknown service\n");
@@ -1910,16 +1939,16 @@
 
     switch(service) {
     case twitter_service:
-        hash = icon_data_by_user;
+        hash = icon_hash[twitter_service];
         suffix = "twitter";
         break;
     case wassr_service:
-        hash = icon_data_by_user2;
+        hash = icon_hash[wassr_service];
         suffix = "wassr";
         break;
     case identica_service:
         suffix = "identica";
-        hash = icon_data_by_user3;
+        hash = icon_hash[identica_service];
         break;
     default:
         twitter_debug("unknown service\n");
@@ -1941,52 +1970,49 @@
     /* check if saved file exists */
     if(suffix) {
         gchar *filename = NULL;
-
-        filename = g_strdup_printf("%s_%s.gif", user_name, suffix);
-        path = g_build_filename(
-            purple_prefs_get_string(OPT_ICON_DIR), filename, NULL);
-
-        if(!g_file_test(path, G_FILE_TEST_EXISTS)) {
-            g_free(path);
-            filename = g_strdup_printf("%s_%s.png", user_name, suffix);
-            path = g_build_filename(
-                purple_prefs_get_string(OPT_ICON_DIR), filename, NULL);
-        }
-
-        g_free(filename);
-    }
-
-    twitter_debug("path = %s\n", path);
-
-    /* make image from file, if file exists */
-    if(g_file_test(path, G_FILE_TEST_EXISTS)) {
-        gchar *imgdata = NULL;
-        size_t len;
-        GError *err = NULL;
-        GdkPixbuf *pixbuf = NULL;
-
-        if (!g_file_get_contents(path, &imgdata, &len, &err)) {
-            twitter_debug("Error reading %s: %s\n",
-                               path, err->message);
-            g_error_free(err);
-        }
-
-        pixbuf = make_scaled_pixbuf(imgdata, len);
-
-        if(pixbuf) {
-            data->icon_id =
-                purple_imgstore_add_with_id(pixbuf,
-                                            gdk_pixbuf_get_rowstride(pixbuf) *
-                                            gdk_pixbuf_get_height(pixbuf),
-                                            user_name);
-
-            twitter_debug("icon data has been loaded from file\n");
-            insert_requested_icon(user_name, service);
-        }
-
-        g_free(path);
-        return;
-    }
+        gchar **extp;
+
+        for(extp = ext_list; *extp; extp++) {
+            filename = g_strdup_printf("%s_%s.%s", user_name, suffix, *extp);
+            path = g_build_filename(purple_prefs_get_string(OPT_ICON_DIR),
+                                    filename, NULL);
+
+            twitter_debug("path = %s\n", path);
+
+            /* make image from file, if file exists */
+            if(g_file_test(path, G_FILE_TEST_EXISTS)) {
+                gchar *imgdata = NULL;
+                size_t len;
+                GError *err = NULL;
+                GdkPixbuf *pixbuf = NULL;
+
+                if (!g_file_get_contents(path, &imgdata, &len, &err)) {
+                    twitter_debug("Error reading %s: %s\n",
+                                  path, err->message);
+                    g_error_free(err);
+                }
+
+                pixbuf = make_scaled_pixbuf(imgdata, len);
+
+                if(pixbuf) {
+                    data->icon_id =
+                        purple_imgstore_add_with_id(
+                            pixbuf,
+                            gdk_pixbuf_get_rowstride(pixbuf) *
+                            gdk_pixbuf_get_height(pixbuf),
+                            user_name);
+
+                    data->img_type = *extp;
+
+                    twitter_debug("icon data has been loaded from file\n");
+                    insert_requested_icon(user_name, service);
+                }
+
+                g_free(path);
+                return;
+            }
+        } /* for */
+    } /* suffix */
 
     /* Return if user's icon has been requested already. */
     if(data->requested)
@@ -1994,10 +2020,7 @@
     else
         data->requested = TRUE;
 
-
-    /* Create the URL of the user's icon.
-     * See http://twitter.g.hatena.ne.jp/ikko615/20080107/1199703400
-     */
+    /* Create the URL for an user's icon. */
     switch(service) {
     case twitter_service:
         url = g_strdup_printf("http://twitter.com/%s", user_name);
@@ -2046,13 +2069,13 @@
 
     switch(service) {
     case twitter_service:
-        hash = icon_data_by_user;
+        hash = icon_hash[twitter_service];
         break;
     case wassr_service:
-        hash = icon_data_by_user2;
+        hash = icon_hash[wassr_service];
         break;
     case identica_service:
-        hash = icon_data_by_user3;
+        hash = icon_hash[identica_service];
         break;
     default:
         twitter_debug("unknown service\n");
@@ -2062,6 +2085,7 @@
     if(hash)
         data = (icon_data *)g_hash_table_lookup(hash, user_name);
 
+    /* proper place to allocate icon_data */
     if(!data) {
         data = g_new0(icon_data, 1);
         g_hash_table_insert(hash, g_strdup(user_name), data);
@@ -2072,7 +2096,8 @@
 
 static gboolean
 displaying_im_cb(PurpleAccount *account, const char *who, char **message,
-                 PurpleConversation *conv, PurpleMessageFlags flags, void *unused)
+                 PurpleConversation *conv, PurpleMessageFlags flags,
+                 void *unused)
 {
     GtkIMHtml *imhtml;
     GtkTextBuffer *text_buffer;
@@ -2143,13 +2168,13 @@
 
     switch(service) {
     case twitter_service:
-        hash = icon_data_by_user;
+        hash = icon_hash[twitter_service];
         break;
     case wassr_service:
-        hash = icon_data_by_user2;
+        hash = icon_hash[wassr_service];
         break;
     case identica_service:
-        hash = icon_data_by_user3;
+        hash = icon_hash[identica_service];
         break;
     default:
         twitter_debug("unknown service\n");
@@ -2228,10 +2253,11 @@
                     account = purple_buddy_get_account(b);
                     if (is_twitter_account(account, name)) {
                         PurpleConversation *gconv;
-                        gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account);
+                        gconv = purple_find_conversation_with_account(
+                            PURPLE_CONV_TYPE_IM, name, account);
                         if (!gconv) {
-                            gconv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
-                                                            account, name);
+                            gconv = purple_conversation_new(
+                                PURPLE_CONV_TYPE_IM, account, name);
                         }
                     }
                 }
@@ -2254,6 +2280,8 @@
 static gboolean
 load_plugin(PurplePlugin *plugin)
 {
+    int i;
+
     /* connect to signal */
     purple_signal_connect(purple_conversations_get_handle(), "writing-im-msg",
                           plugin, PURPLE_CALLBACK(writing_im_cb), NULL);
@@ -2288,16 +2316,15 @@
     regp[IMAGE_IDENTICA] = g_regex_new(P_IMAGE_IDENTICA, 0, 0, NULL);
     regp[IMAGE_TWITTER]  = g_regex_new(P_IMAGE_TWITTER, 0, 0, NULL);
 
-
-    icon_data_by_user = g_hash_table_new_full(g_str_hash, g_str_equal,
+    for(i = twitter_service; i <= identica_service; i++) {
+        icon_hash[i] = g_hash_table_new_full(g_str_hash, g_str_equal,
                                               g_free, NULL);
-    icon_data_by_user2 = g_hash_table_new_full(g_str_hash, g_str_equal,
-                                              g_free, NULL);
-    icon_data_by_user3 = g_hash_table_new_full(g_str_hash, g_str_equal,
-                                              g_free, NULL);
+    }
+
     conv_hash = g_hash_table_new_full(g_direct_hash, g_direct_equal,
                                               NULL, NULL);
 
+
     /* attach counter to the existing twitter window */
     if(purple_prefs_get_bool(OPT_COUNTER)) {
         attach_to_window();
@@ -2328,13 +2355,20 @@
     if(data->request_list) {
         twitter_debug("somehow, request_list != NULL\n");
     }
-
-    return;
+}
+
+static void
+cleanup_hash_entry_func(gpointer key, gpointer value, gpointer user_data)
+{
+    remove_marks_func(key, value, user_data);
+    cancel_fetch_func(key, value, user_data);
 }
 
 static gboolean
 unload_plugin(PurplePlugin *plugin)
 {
+    int i;
+
     twitter_debug("called\n");
 
     /* disconnect from signal */
@@ -2364,25 +2398,20 @@
                              plugin, PURPLE_CALLBACK(signed_on_cb));
 
     /* unreference regp */
-    int i;
     for(i = 0; i < NUM_REGP; i++) {
         g_regex_unref(regp[i]);
     }
 
     /* remove mark list in each hash entry */
-    g_hash_table_foreach(icon_data_by_user, (GHFunc)remove_marks_func, NULL);
-    g_hash_table_foreach(icon_data_by_user2, (GHFunc)remove_marks_func, NULL);
-    g_hash_table_foreach(icon_data_by_user3, (GHFunc)remove_marks_func, NULL);
-
     /* cancel request that has not been finished yet */
-    g_hash_table_foreach(icon_data_by_user, (GHFunc)cancel_fetch_func, NULL);
-    g_hash_table_foreach(icon_data_by_user2, (GHFunc)cancel_fetch_func, NULL);
-    g_hash_table_foreach(icon_data_by_user3, (GHFunc)cancel_fetch_func, NULL);
-
-    /* destroy hash table for icon_data */
-    g_hash_table_destroy(icon_data_by_user); //XXX all memory freed? --yaz
-    g_hash_table_destroy(icon_data_by_user2);
-    g_hash_table_destroy(icon_data_by_user3);
+    for(i = twitter_service; i <= identica_service; i++) {
+        /* delete mark list and stop requeset for each hash table */
+        g_hash_table_foreach(icon_hash[i],
+                             (GHFunc)cleanup_hash_entry_func, NULL);
+        /* destroy hash table for icon_data */
+        g_hash_table_destroy(icon_hash[i]);
+    }
+
     g_hash_table_destroy(conv_hash);
 
     /* detach from twitter window */
@@ -2435,13 +2464,13 @@
 icon_size_prefs_cb(const char *name, PurplePrefType type,
                    gconstpointer val, gpointer data)
 {
+    int i;
+
     /* invalidate icon cache */
-    g_hash_table_foreach(icon_data_by_user,
-                         (GHFunc)invalidate_icon_data_func, NULL);
-    g_hash_table_foreach(icon_data_by_user2,
-                         (GHFunc)invalidate_icon_data_func, NULL);
-    g_hash_table_foreach(icon_data_by_user3,
-                         (GHFunc)invalidate_icon_data_func, NULL);
+    for(i = twitter_service; i <= identica_service; i++) {
+        g_hash_table_foreach(icon_hash[i],
+                             (GHFunc)invalidate_icon_data_func, NULL);
+    }
 }
 
 static void
@@ -2549,7 +2578,7 @@
     g_signal_connect(e, "toggled",
                      G_CALLBACK(bool_toggled_cb), &e);
 
-    purple_prefs_connect_callback(plugin, OPT_API_BASE_POST, // xxx divide?
+    purple_prefs_connect_callback(plugin, OPT_API_BASE_POST, /* xxx divide? */
                                   api_base_post_cb, NULL);
 
     e = GTK_WIDGET(gtk_builder_get_object (builder, "account_api_password"));
@@ -2625,7 +2654,7 @@
                                  purple_prefs_get_bool(OPT_COUNTER));
     g_signal_connect(e, "toggled",
                      G_CALLBACK(bool_toggled_cb), &e);
-    purple_prefs_connect_callback(plugin, OPT_COUNTER, //xxx
+    purple_prefs_connect_callback(plugin, OPT_COUNTER, /* xxx */
                                   counter_prefs_cb, NULL);
 
     e = GTK_WIDGET(gtk_builder_get_object (builder, "utility_pseudo"));
--- a/pidgin-twitter.h	Thu Jul 24 06:40:41 2008 +0900
+++ b/pidgin-twitter.h	Thu Jul 24 21:00:34 2008 +0900
@@ -39,7 +39,7 @@
 
 /* service id */
 enum {
-    unknown_service = 0,
+    unknown_service = -1,
     twitter_service,
     wassr_service,
     identica_service
@@ -47,10 +47,11 @@
 
 /* container to hold icon data */
 typedef struct _icon_data {
-    gint icon_id;        // image id
-    gboolean requested;  // TRUE if download icon has been requested
-    GList *request_list; // marker list
-    PurpleUtilFetchUrlData *fetch_data;          // icon fetch data
+    gint icon_id;           /* image id */
+    gboolean requested;     /* TRUE if download icon has been requested */
+    GList *request_list;    /* marker list */
+    PurpleUtilFetchUrlData *fetch_data; /* icon fetch data */
+    const gchar *img_type;  /* image type */
 } icon_data;
 
 /* used by got_icon_cb */
@@ -194,7 +195,7 @@
 static gboolean load_plugin(PurplePlugin *plugin);
 static gboolean unload_plugin(PurplePlugin *plugin);
 static void counter_prefs_cb(const char *name, PurplePrefType type, gconstpointer val, gpointer data);
-//static PurplePluginPrefFrame *get_plugin_pref_frame(PurplePlugin *plugin);
+
 static void init_plugin(PurplePlugin *plugin);
 static void remove_marks_func(gpointer key, gpointer value, gpointer user_data);
 static void cancel_fetch_func(gpointer key, gpointer value, gpointer user_data);
@@ -207,4 +208,9 @@
 static gboolean get_status_with_api(gpointer data);
 static void read_timestamp(const char *str, struct tm *res);
 
+static void strip_markup(gchar **str, gboolean escape);
+static gchar *strip_html_markup(const gchar *src);
+static GtkWidget *prefs_get_frame(PurplePlugin *plugin);
+
+
 #endif