PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/xchat-gnome-0.26.2/plugins/url_scraper/urlscraper.c

#
C | 236 lines | 183 code | 51 blank | 2 comment | 16 complexity | 484e753dbb9487888f244ccd20f8355b MD5 | raw file
Possible License(s): GPL-2.0
  1. #include <config.h>
  2. #include <glib/gi18n.h>
  3. #include <sys/types.h>
  4. #include <regex.h>
  5. #include <gtk/gtk.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <gconf/gconf-client.h>
  9. #include <time.h>
  10. #include "xchat-plugin.h"
  11. #define PVERSION "0.2"
  12. #define URLREGEX "(ht|f)tps?://[~a-z0-9./_=#%&?,-]+[a-z0-9]+"
  13. #define EMAILREGEX "[a-z0-9.+_-]+@([0-9a-z-]+\\.)+[a-z]+"
  14. static xchat_plugin *ph; // Plugin handle.
  15. static regex_t *email; // Regex that matches e-mail addresses.
  16. static regex_t *url; // Regex that matches urls.
  17. static int urls, history; // Current total in the scraper and max history.
  18. static gboolean timestamps; // Show timestamps?
  19. static GtkWidget *window;
  20. static GtkListStore *list_store;
  21. void url_open (GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *column, gpointer user_data);
  22. void xchat_plugin_get_info (char **plugin_name, char **plugin_desc, char **plugin_version, void **reserved);
  23. int xchat_plugin_init (xchat_plugin *plugin_handle, char **plugin_name, char **plugin_desc, char **plugin_version, char *arg);
  24. int xchat_plugin_deinit (void);
  25. static gboolean delete_cb (GtkWidget *widget, GdkEvent *event, gpointer user_data)
  26. {
  27. return TRUE;
  28. }
  29. static void make_window ()
  30. {
  31. GtkWidget *treeview, *scrolled;
  32. GtkTreeViewColumn *nick_col, *chan_col, *url_col, *time_col;
  33. GtkCellRenderer *nick_rend, *chan_rend, *url_rend, *time_rend;
  34. window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  35. gtk_window_set_title (GTK_WINDOW (window), _("xchat URL scraper"));
  36. gtk_window_set_default_size (GTK_WINDOW(window), 400, 400);
  37. g_signal_connect (G_OBJECT(window), "delete-event", G_CALLBACK(delete_cb), 0);
  38. list_store = gtk_list_store_new (5, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
  39. scrolled = gtk_scrolled_window_new (NULL, NULL);
  40. gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(scrolled),
  41. GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
  42. treeview = gtk_tree_view_new ();
  43. gtk_tree_view_set_model (GTK_TREE_VIEW(treeview), GTK_TREE_MODEL(list_store));
  44. time_rend = gtk_cell_renderer_text_new ();
  45. time_col = gtk_tree_view_column_new_with_attributes (_("Time"), time_rend, "text", 0, NULL);
  46. gtk_tree_view_column_set_visible (time_col, timestamps);
  47. gtk_tree_view_column_set_resizable (time_col, TRUE);
  48. nick_rend = gtk_cell_renderer_text_new ();
  49. nick_col = gtk_tree_view_column_new_with_attributes (_("Nick"), nick_rend, "text", 1, NULL);
  50. gtk_tree_view_column_set_resizable (nick_col, TRUE);
  51. chan_rend = gtk_cell_renderer_text_new ();
  52. chan_col = gtk_tree_view_column_new_with_attributes (_("Channel"), chan_rend, "text", 2, NULL);
  53. gtk_tree_view_column_set_resizable (chan_col, TRUE);
  54. url_rend = gtk_cell_renderer_text_new ();
  55. g_object_set (G_OBJECT(url_rend), "ellipsize", PANGO_ELLIPSIZE_END, NULL);
  56. url_col = gtk_tree_view_column_new_with_attributes (_("URL"), url_rend, "text", 3, NULL);
  57. gtk_tree_view_column_set_resizable (url_col, TRUE);
  58. gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), time_col);
  59. gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), nick_col);
  60. gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), chan_col);
  61. gtk_tree_view_append_column (GTK_TREE_VIEW(treeview), url_col);
  62. gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(treeview), TRUE);
  63. gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW(scrolled), treeview);
  64. gtk_container_add (GTK_CONTAINER(window), scrolled);
  65. g_signal_connect (G_OBJECT(treeview), "row-activated", G_CALLBACK(url_open), NULL);
  66. g_object_set (G_OBJECT(treeview), "enable-search", FALSE, NULL);
  67. gtk_widget_show_all (window);
  68. }
  69. static void add_match (char **word, regmatch_t match, gboolean isurl)
  70. {
  71. int len;
  72. const char *chan;
  73. time_t footime;
  74. struct tm *time_struct;
  75. char *url_match, time_str[9];
  76. GtkTreeIter iter;
  77. len = match.rm_eo - match.rm_so;
  78. url_match = malloc (len + 1);
  79. memset (url_match, 0, len + 1);
  80. strncpy (url_match, word[2] + match.rm_so, len);
  81. chan = xchat_get_info (ph, "channel");
  82. if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL(list_store), &iter)) {
  83. char *entry;
  84. do {
  85. gtk_tree_model_get (GTK_TREE_MODEL(list_store), &iter, 3, &entry, -1);
  86. if (strcmp (entry, url_match) == 0) {
  87. free (url_match);
  88. return;
  89. }
  90. } while (gtk_tree_model_iter_next (GTK_TREE_MODEL(list_store), &iter));
  91. }
  92. if (urls >= history) {
  93. gtk_tree_model_get_iter_first (GTK_TREE_MODEL(list_store), &iter);
  94. gtk_list_store_remove (list_store, &iter);
  95. }
  96. else
  97. urls++;
  98. /* Get time stamp. */
  99. footime = time (NULL);
  100. time_struct = localtime (&footime);
  101. sprintf (time_str, "%02d:%02d:%02d",
  102. time_struct->tm_hour, time_struct->tm_min, time_struct->tm_sec);
  103. gtk_list_store_append (list_store, &iter);
  104. gtk_list_store_set (list_store, &iter,
  105. 0, time_str, 1, word[1], 2, chan, 3, url_match, 4, isurl, -1);
  106. }
  107. static int grabURL (char **word, void *userdata)
  108. {
  109. regmatch_t match;
  110. if (regexec (url, word[2], 1, &match, REG_NOTBOL | REG_NOTEOL) == 0)
  111. add_match (word, match, TRUE);
  112. else if (regexec (email, word[2], 1, &match, REG_NOTBOL | REG_NOTEOL) == 0)
  113. add_match (word, match, FALSE);
  114. return XCHAT_EAT_NONE;
  115. }
  116. void xchat_plugin_get_info (char **plugin_name,
  117. char **plugin_desc,
  118. char **plugin_version,
  119. void **reserved)
  120. {
  121. *plugin_name = _("URL Scraper");
  122. *plugin_desc = _("Grabs URLs and puts them in a separate window for easy viewing.");
  123. *plugin_version = PVERSION;
  124. if (reserved)
  125. *reserved = NULL;
  126. }
  127. void url_open (GtkTreeView *treeview, GtkTreePath *path,
  128. GtkTreeViewColumn *column, gpointer user_data)
  129. {
  130. gchar *cur_url = NULL;
  131. gboolean isurl;
  132. GtkTreeModel *model;
  133. GtkTreeSelection *selection;
  134. GError *err = NULL;
  135. GtkTreeIter iter;
  136. model = gtk_tree_view_get_model (treeview);
  137. selection = gtk_tree_view_get_selection (treeview);
  138. if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
  139. gtk_tree_model_get (model, &iter, 3, &cur_url, 4, &isurl, -1);
  140. if (isurl)
  141. gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (treeview)),
  142. cur_url, gtk_get_current_event_time (), &err);
  143. if (err) {
  144. g_warning ("Unable to open %s: %s", cur_url, err->message);
  145. g_error_free (err);
  146. }
  147. }
  148. }
  149. int xchat_plugin_init (xchat_plugin *plugin_handle,
  150. char **plugin_name,
  151. char **plugin_desc,
  152. char **plugin_version,
  153. char *arg)
  154. {
  155. GConfClient *client = gconf_client_get_default ();
  156. ph = plugin_handle;
  157. xchat_plugin_get_info (plugin_name, plugin_desc, plugin_version, NULL);
  158. url = malloc (sizeof (regex_t));
  159. if (regcomp (url, URLREGEX, REG_ICASE | REG_EXTENDED)) {
  160. xchat_print (ph, _("URL Scraper failed to load: couldn't compile URL regex.\n"));
  161. return 0;
  162. }
  163. email = malloc (sizeof (regex_t));
  164. if (regcomp (email, EMAILREGEX, REG_ICASE | REG_EXTENDED)) {
  165. xchat_print (ph, _("URL Scraper failed to load: couldn't compile e-mail regex.\n"));
  166. return 0;
  167. }
  168. urls = 0;
  169. /* Set our prefs from GConf. */
  170. history = gconf_client_get_int (client, "/apps/xchat/plugins/urlscraper/history", NULL);
  171. timestamps = gconf_client_get_bool (client, "/apps/xchat/plugins/urlscraper/timestamps", NULL);
  172. make_window ();
  173. xchat_hook_print (ph, "Channel Message", XCHAT_PRI_NORM, grabURL, 0);
  174. xchat_hook_print (ph, "Private Message to Dialog", XCHAT_PRI_NORM, grabURL, 0);
  175. xchat_print (ph, _("URL Scraper loaded.\n"));
  176. return 1;
  177. }
  178. int xchat_plugin_deinit (void)
  179. {
  180. gtk_widget_destroy (window);
  181. regfree (url);
  182. regfree (email);
  183. xchat_print (ph, _("URL Scraper unloaded.\n"));
  184. return 1;
  185. }