[Commits] [SCM] claws branch, master, updated. 3.9.0-171-g3e1e674
holger at claws-mail.org
holger at claws-mail.org
Sat Apr 6 20:06:14 CEST 2013
The branch master of project "claws" (Claws Mail) has been updated
via 3e1e674b8a73109200e23b0e2520f42e8d63155b (commit)
via 4f1b728770f4356230445fafb28ef9dd35232519 (commit)
from 679dd60ea63ffca15052d8175779d8cc4c87402c (commit)
- Log -----------------------------------------------------------------
commit 3e1e674b8a73109200e23b0e2520f42e8d63155b
Author: Holger Berndt <hb at claws-mail.org>
Date: Sat Apr 6 01:11:06 2013 +0200
Add geolocation plugin
diff --git a/.gitignore b/.gitignore
index dc7e934..228c585 100644
--- a/.gitignore
+++ b/.gitignore
@@ -299,6 +299,13 @@
/src/plugins/gdata/Makefile
/src/plugins/gdata/Makefile.in
/src/plugins/gdata/*.o
+/src/plugins/geolocation/.deps
+/src/plugins/geolocation/*.la
+/src/plugins/geolocation/.libs
+/src/plugins/geolocation/*.lo
+/src/plugins/geolocation/Makefile
+/src/plugins/geolocation/Makefile.in
+/src/plugins/geolocation/*.o
/src/plugins/mailmbox/.deps
/src/plugins/mailmbox/*.la
/src/plugins/mailmbox/.libs
diff --git a/configure.ac b/configure.ac
index 51d0a86..d489268 100644
--- a/configure.ac
+++ b/configure.ac
@@ -993,6 +993,10 @@ AC_ARG_ENABLE(gdata-plugin,
[ --disable-gdata-plugin Do not build gdata plugin],
[enable_gdata_plugin=$enableval], [enable_gdata_plugin=auto])
+AC_ARG_ENABLE(geolocation-plugin,
+ [ --disable-geolocation-plugin Do not build geolocation plugin],
+ [enable_geolocation_plugin=$enableval], [enable_geolocation_plugin=auto])
+
AC_ARG_ENABLE(mailmbox-plugin,
[ --disable-mailmbox-plugin Do not build mailmbox plugin],
[enable_mailmbox_plugin=$enableval], [enable_mailmbox_plugin=auto])
@@ -1069,6 +1073,7 @@ dnl either yes or no, and do the AC_SUBST calls.
dnl Archive: libarchive
dnl Fancy: Webkit, curl, optionally libsoup-gnome
dnl Gdata: libgdata
+dnl Geolocation libchamplain, libsoup
dnl Notification: optionally libnotify libindicate libcanberra_gtk hotkey
dnl Pdf-Viewer: libpoppler
dnl Perl: sed perl
@@ -1096,6 +1101,11 @@ PKG_CHECK_MODULES(WEBKIT, webkit-1.0 >= 1.1.14, HAVE_WEBKIT=yes, HAVE_WEBKIT=no)
AC_SUBST(WEBKIT_LIBS)
AC_SUBST(WEBKIT_CFLAGS)
+dnl libsoup ********************************************************************
+PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4)
+AC_SUBST(LIBSOUP_CFLAGS)
+AC_SUBST(LIBSOUP_LIBS)
+
dnl libsoup-gnome **************************************************************
PKG_CHECK_MODULES(LIBSOUP_GNOME, libsoup-gnome-2.4 >= 2.26, HAVE_LIBSOUP_GNOME=yes, HAVE_LIBSOUP_GNOME=no)
if test x"$HAVE_LIBSOUP_GNOME" = xyes; then
@@ -1272,6 +1282,16 @@ fi
AC_SUBST(CM_NP_HOTKEY_CFLAGS)
AC_SUBST(CM_NP_HOTKEY_LIBS)
+dnl libchamplain ***************************************************************
+CHAMPLAIN_MODULE=champlain-gtk-0.4
+CHAMPLAIN_VERSION=0.4.0
+PKG_CHECK_EXISTS(champlain-gtk-0.6 > 0.6.0,[CHAMPLAIN_MODULE=champlain-gtk-0.6
+ CHAMPLAIN_VERSION=0.6.0], [])
+PKG_CHECK_EXISTS(champlain-gtk-0.8 > 0.8.0,[CHAMPLAIN_MODULE=champlain-gtk-0.8
+ CHAMPLAIN_VERSION=0.8.0], [])
+PKG_CHECK_MODULES(CHAMPLAIN, [$CHAMPLAIN_MODULE >= $CHAMPLAIN_VERSION clutter-gtk-0.10], HAVE_CHAMPLAIN=yes, HAVE_CHAMPLAIN=no)
+AC_SUBST(CHAMPLAIN_CFLAGS)
+AC_SUBST(CHAMPLAIN_LIBS)
dnl Third, we now cross the requested plugins and the available dependencies
dnl If some dependencies are missing and the plugin was explicitely enabled,
@@ -1436,6 +1456,30 @@ else
AC_MSG_RESULT(no)
fi
+if test x"$enable_geolocation_plugin" != xno; then
+ dependencies_missing=""
+
+ if test x"$HAVE_CHAMPLAIN" = xno; then
+ dependencies_missing="libchamplain $dependencies_missing"
+ fi
+
+ if test x"$dependencies_missing" = x; then
+ PLUGINS="$PLUGINS geolocation"
+ AC_MSG_RESULT(yes)
+ elif test x"$enable_geolocation_plugin" = xauto; then
+ AC_MSG_RESULT(no)
+ AC_MSG_WARN("Plugin geolocation will not be built; missing $dependencies_missing")
+ enable_geolocation_plugin=no
+ MISSING_DEPS_PLUGINS="$MISSING_DEPS_PLUGINS geolocation"
+ else
+ AC_MSG_RESULT(no)
+ AC_MSG_ERROR("Plugin geolocation cannot be built; missing $dependencies_missing")
+ fi
+else
+ DISABLED_PLUGINS="$DISABLED_PLUGINS geolocation"
+ AC_MSG_RESULT(no)
+fi
+
AC_MSG_CHECKING([whether to build mailmbox plugin])
if test x"$enable_mailmbox_plugin" != xno; then
PLUGINS="$PLUGINS mailmbox"
@@ -1795,6 +1839,7 @@ AM_CONDITIONAL(BUILD_DEMO_PLUGIN, test x"$enable_demo_plugin" != xno)
AM_CONDITIONAL(BUILD_FANCY_PLUGIN, test x"$enable_fancy_plugin" != xno)
AM_CONDITIONAL(BUILD_FETCHINFO_PLUGIN, test x"$enable_fetchinfo_plugin" != xno)
AM_CONDITIONAL(BUILD_GDATA_PLUGIN, test x"$enable_gdata_plugin" != xno)
+AM_CONDITIONAL(BUILD_GEOLOCATION_PLUGIN, test x"$enable_geolocation_plugin" != xno)
AM_CONDITIONAL(BUILD_MAILMBOX_PLUGIN, test x"$enable_mailmbox_plugin" != xno)
AM_CONDITIONAL(BUILD_NEWMAIL_PLUGIN, test x"$enable_newmail_plugin" != xno)
AM_CONDITIONAL(BUILD_NOTIFICATION_PLUGIN, test x"$enable_notification_plugin" != xno)
@@ -1841,6 +1886,7 @@ src/plugins/demo/Makefile
src/plugins/fancy/Makefile
src/plugins/fetchinfo/Makefile
src/plugins/gdata/Makefile
+src/plugins/geolocation/Makefile
src/plugins/mailmbox/Makefile
src/plugins/newmail/Makefile
src/plugins/notification/Makefile
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
index 17dce52..d440d96 100644
--- a/src/plugins/Makefile.am
+++ b/src/plugins/Makefile.am
@@ -11,6 +11,7 @@ SUBDIRS = \
fancy \
fetchinfo \
gdata \
+ geolocation \
mailmbox \
newmail \
notification \
diff --git a/src/plugins/geolocation/Makefile.am b/src/plugins/geolocation/Makefile.am
new file mode 100644
index 0000000..1c1ae46
--- /dev/null
+++ b/src/plugins/geolocation/Makefile.am
@@ -0,0 +1,31 @@
+plugindir = $(pkglibdir)/plugins
+
+if BUILD_GEOLOCATION_PLUGIN
+plugin_LTLIBRARIES = geolocation.la
+endif
+
+geolocation_la_SOURCES = \
+ geolocation_plugin.c \
+ pixmap_earth.h
+
+geolocation_la_LDFLAGS = \
+ -avoid-version -module \
+ $(GTK_LIBS) \
+ $(LIBSOUP_LIBS) \
+ $(CHAMPLAIN_LIBS)
+
+
+INCLUDES = \
+ -I$(top_srcdir)/src \
+ -I$(top_srcdir)/src/common \
+ -I$(top_builddir)/src/common \
+ -I$(top_srcdir)/src/gtk
+
+AM_CPPFLAGS = \
+ -Wall \
+ $(CLAWS_MAIL_CFLAGS) \
+ $(GLIB_CFLAGS) \
+ $(GTK_CFLAGS) \
+ $(LIBSOUP_CFLAGS) \
+ $(CHAMPLAIN_CFLAGS) \
+ -DLOCALEDIR=\""$(localedir)"\"
diff --git a/src/plugins/geolocation/geolocation_plugin.c b/src/plugins/geolocation/geolocation_plugin.c
new file mode 100644
index 0000000..0860fc3
--- /dev/null
+++ b/src/plugins/geolocation/geolocation_plugin.c
@@ -0,0 +1,903 @@
+/* GeoLocation plugin for Claws-Mail
+ * Copyright (C) 2009 Holger Berndt
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+# include "claws-features.h"
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
+#include "pixmap_earth.h"
+
+#include "common/plugin.h"
+#include "common/version.h"
+#include "common/utils.h"
+#include "common/hooks.h"
+#include "prefs_common.h"
+#include "mimeview.h"
+#include "procheader.h"
+#include "main.h"
+
+#include <libsoup/soup.h>
+
+#include <champlain/champlain.h>
+#include <champlain-gtk/champlain-gtk.h>
+#include <clutter-gtk/clutter-gtk.h>
+
+#include <string.h>
+
+
+/* For now, make extracting the ip address string from the Received header
+ * as simple as possible. This should be made more accurate, some day.
+ * Logic:
+ * Find four 1-3 digit numbers, separated by dots, encosed in word boundaries,
+ * where the word "from" must be ahead, and the word "by" must follow, but must
+ * not be between the "from" and the digits.
+ * The result will be in backreference 2, the individual numbers in 3 to 6 */
+#define EXTRACT_IP_FROM_RECEIVED_HEADER_REGEX "\\bfrom\\b((?!\\bby\\b).)*(\\b(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\b).*\\bby\\b"
+
+#define EXTRACT_LAT_LON_FROM_HOSTIP_RESPONSE_REGEX "<gml:coordinates>(-?[\\d.]+),(-?[\\d.]+)</gml:coordinates>"
+
+#define GEOLOCATION_CONTAINER_NAME "cm_geolocation_container"
+#define GEOLOCATION_CONTAINER_DATA_TOGGLEBUTTON "togglebutton"
+#define GEOLOCATION_CONTAINER_DATA_LABEL "label"
+
+#define GEOLOCATION_TOGGLE_BUTTON_DATA_CB_ID "toggled_cb_id"
+#define GEOLOCATION_TOGGLE_BUTTON_DATA_IP "ip"
+
+#define GEOLOCATION_NOTEBOOK_DATA_MAPWIDGET "mapwidget"
+
+#define GEOLOCATION_MAP_DATA_VIEW "view"
+#define GEOLOCATION_MAP_DATA_ORIGIN_MARKER "originmarker"
+
+#define BUFFSIZE 8192
+
+#define HOSTIP_URL "http://api.hostip.info/"
+
+#define COUNTRY_RESOLVER_SUFFIX "zz.countries.nerd.dk"
+
+
+static gboolean my_messageview_show_hook(gpointer, gpointer);
+static guint hook_messageview_show;
+
+static GRegex *ip_from_received_header_regex = NULL;
+static GRegex *lat_lon_from_hostip_response_regex = NULL;
+
+static GSList *container_list = NULL;
+
+static GHashTable *iso_country_hash = NULL;
+
+static gchar* get_ip_from_received_header(gchar *received)
+{
+ GMatchInfo *match_info;
+ gchar *ip;
+ gchar *n1;
+
+ g_regex_match(ip_from_received_header_regex, received, 0, &match_info);
+ ip = g_match_info_fetch(match_info, 2);
+
+ if (ip) {
+ /* check for loopback and local subnetworks */
+ if(!strcmp(ip, "127.0.0.1")) {
+ g_free(ip);
+ ip = NULL;
+ }
+ else {
+ n1 = g_match_info_fetch(match_info, 3);
+ if(n1) {
+ /* 10.x.x.x */
+ if(!strcmp(n1, "10")) {
+ g_free(ip);
+ ip = NULL;
+ }
+ /* 192.168.x.x */
+ else if(!strcmp(n1, "192")) {
+ gchar *n2;
+ n2 = g_match_info_fetch(match_info, 4);
+ if(n2 && !strcmp(n2, "168")) {
+ g_free(ip);
+ ip = NULL;
+ }
+ }
+ /* 172.16.xx to 172.31.x.x */
+ else if(!strcmp(n1, "172")) {
+ gchar *n2;
+ int i2;
+ n2 = g_match_info_fetch(match_info, 4);
+ if(n2) {
+ i2 = atoi(n2);
+ if((i2 >= 16) && (i2 <= 31)) {
+ g_free(ip);
+ ip = NULL;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ g_match_info_free(match_info);
+ return ip;
+}
+
+enum {
+ H_RECEIVED = 0
+};
+
+static HeaderEntry hentry[] = {
+ {"Received:", NULL, TRUE},
+ {NULL, NULL, FALSE}};
+
+static gchar* get_ip_from_msginfo(MsgInfo *msginfo)
+{
+ gchar *file;
+ struct stat ss;
+ FILE *fp;
+ gchar buf[BUFFSIZE];
+ gint hnum;
+ gchar *hp;
+ gchar *ip;
+ gchar *new_ip;
+
+ file = procmsg_get_message_file_path(msginfo);
+ g_return_val_if_fail(file, NULL);
+
+ if(g_stat(file, &ss) < 0) {
+ FILE_OP_ERROR(file, "stat");
+ return NULL;
+ }
+ if(!S_ISREG(ss.st_mode)) {
+ g_warning("mail file is not a regular file\n");
+ return NULL;
+ }
+
+ if((fp = g_fopen(file, "rb")) == NULL) {
+ FILE_OP_ERROR(file, "fopen");
+ return NULL;
+ }
+
+ ip = NULL;
+ new_ip = NULL;
+ while((hnum = procheader_get_one_field(buf, sizeof(buf), fp, hentry)) != -1) {
+ switch(hnum) {
+ case H_RECEIVED:
+ hp = buf + strlen(hentry[hnum].name);
+ while(*hp == ' ' || *hp == '\t') hp++;
+ new_ip = get_ip_from_received_header(hp);
+ if(new_ip) {
+ g_free(ip);
+ ip = new_ip;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ fclose(fp);
+
+ g_free(file);
+ return ip;
+}
+
+/* inspired by GeoClue */
+static gboolean get_lat_lon_from_ip(const gchar *ip, double *lat, double *lon)
+{
+ gchar *url;
+ GMatchInfo *match_info;
+ gchar *slat;
+ gchar *slon;
+ SoupSession *session;
+ SoupMessage *msg;
+
+ /* fetch data from hostip.info */
+ url = g_strdup_printf("%s?ip=%s", HOSTIP_URL, ip);
+ session = soup_session_async_new();
+ msg = soup_message_new(SOUP_METHOD_GET, url);
+ g_free(url);
+
+ soup_session_send_message(session, msg);
+ g_object_unref(session);
+ if(!SOUP_STATUS_IS_SUCCESSFUL(msg->status_code) || !msg->response_body->data)
+ return FALSE;
+
+ /* extract longitude and latitude from */
+ g_regex_match(lat_lon_from_hostip_response_regex, msg->response_body->data, 0, &match_info);
+ g_object_unref(msg);
+ slon = g_match_info_fetch(match_info, 1);
+ slat = g_match_info_fetch(match_info, 2);
+ g_match_info_free(match_info);
+
+ if(!slat || !slon)
+ return FALSE;
+
+ *lat = g_ascii_strtod(slat, NULL);
+ *lon = g_ascii_strtod(slon, NULL);
+
+ return TRUE;
+}
+
+/* try to look up country */
+static const gchar* get_country_from_ip(const gchar *ip)
+{
+ gchar **tok;
+ gchar *uri;
+ SoupAddress *addr;
+ const gchar *val = NULL;
+
+ tok = g_strsplit_set(ip, ".", 4);
+ if(!(tok[0] && tok[1] && tok[2] && tok[3] && !tok[4])) {
+ g_strfreev(tok);
+ debug_print("GeoLocation plugin: Error parsing ip address '%s'\n", ip);
+ return NULL;
+ }
+ uri = g_strjoin(".", tok[3], tok[2], tok[1], tok[0], COUNTRY_RESOLVER_SUFFIX, NULL);
+ g_strfreev(tok);
+
+ addr = soup_address_new(uri, SOUP_ADDRESS_ANY_PORT);
+ g_free(uri);
+
+ if(soup_address_resolve_sync(addr, NULL) == SOUP_STATUS_OK) {
+ gchar *physical = soup_address_get_physical(addr);
+ val = g_hash_table_lookup(iso_country_hash, physical);
+ }
+
+ g_object_unref(addr);
+ return val;
+}
+
+static GtkWidget* create_map_widget()
+{
+ GtkWidget *map;
+ ChamplainLayer *layer;
+ ChamplainView *view;
+ ClutterActor *origin_marker;
+ ClutterColor orange = { 0xf3, 0x94, 0x07, 0xbb };
+
+ /* create map widget */
+ map = gtk_champlain_embed_new();
+ view = gtk_champlain_embed_get_view(GTK_CHAMPLAIN_EMBED(map));
+ g_object_set(G_OBJECT(view), "scroll-mode", CHAMPLAIN_SCROLL_MODE_KINETIC, "zoom-level", 8, NULL);
+
+ /* mail origin marker */
+ layer = champlain_layer_new();
+ origin_marker = champlain_marker_new_with_text("mail origin", "Serif 14", NULL, NULL);
+ champlain_marker_set_color(CHAMPLAIN_MARKER(origin_marker), &orange);
+ clutter_container_add(CLUTTER_CONTAINER(layer), origin_marker, NULL);
+ champlain_view_add_layer(view, layer);
+
+ clutter_actor_show(CLUTTER_ACTOR(view));
+ clutter_actor_show(CLUTTER_ACTOR(layer));
+ clutter_actor_show(origin_marker);
+
+ g_object_set_data(G_OBJECT(map), GEOLOCATION_MAP_DATA_VIEW, view);
+ g_object_set_data(G_OBJECT(map), GEOLOCATION_MAP_DATA_ORIGIN_MARKER, origin_marker);
+
+ return map;
+}
+
+static int get_notebook_map_page_num(GtkWidget *notebook)
+{
+ GtkWidget *wid;
+ int page_num = 0;
+
+ wid = g_object_get_data(G_OBJECT(notebook), GEOLOCATION_NOTEBOOK_DATA_MAPWIDGET);
+
+ if(!wid) {
+ /* create page */
+ GtkWidget *map;
+ map = create_map_widget();
+ page_num = gtk_notebook_append_page(GTK_NOTEBOOK(notebook), map, NULL);
+ gtk_widget_show_all(map);
+ if(page_num == -1)
+ page_num = 0;
+ else
+ g_object_set_data(G_OBJECT(notebook), GEOLOCATION_NOTEBOOK_DATA_MAPWIDGET, map);
+ }
+ else {
+ /* find page */
+ page_num = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), wid);
+ if(page_num == -1)
+ page_num = 0;
+ }
+
+ return page_num;
+}
+
+static void geolocation_button_toggled_cb(GtkToggleButton *button, gpointer data)
+{
+ if(gtk_toggle_button_get_active(button)) {
+ gchar *ip;
+ double lat, lon;
+ gchar *text = NULL;
+ GtkWidget *container, *label;
+
+ ip = g_object_get_data(G_OBJECT(button), GEOLOCATION_TOGGLE_BUTTON_DATA_IP);
+ container = gtk_widget_get_parent(GTK_WIDGET(button));
+ g_return_if_fail(container);
+ label = g_object_get_data(G_OBJECT(container), GEOLOCATION_CONTAINER_DATA_LABEL);
+ g_return_if_fail(label);
+
+ if(ip && get_lat_lon_from_ip(ip, &lat, &lon)) {
+ GtkWidget *notebook;
+ GtkWidget *map;
+ MessageView *messageview;
+ ClutterActor *view;
+ ClutterActor *origin_marker;
+ gint page_num;
+
+ /* TRANSLATORS: The two numbers are latitude and longitude coordinates */
+ text = g_strdup_printf(_("Found location: (%.2f,%.2f)"), lat, lon);
+ gtk_label_set_text(GTK_LABEL(label), text);
+ debug_print("%s\n", text);
+
+ /* switch to map widget, and center on found location */
+ messageview = data;
+ notebook = messageview->mimeview->mime_notebook;
+ page_num = get_notebook_map_page_num(notebook);
+ map = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), page_num);
+ view = g_object_get_data(G_OBJECT(map), GEOLOCATION_MAP_DATA_VIEW);
+ origin_marker = g_object_get_data(G_OBJECT(map), GEOLOCATION_MAP_DATA_ORIGIN_MARKER);
+ champlain_view_center_on(CHAMPLAIN_VIEW(view), lat, lon);
+ champlain_base_marker_set_position(CHAMPLAIN_BASE_MARKER(origin_marker), lat, lon);
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), page_num);
+ }
+ else {
+ const char *country;
+
+ if(ip && ((country = get_country_from_ip(ip)) != NULL)) {
+ /* TRANSLATORS: The country name is appended to the string */
+ text = g_strconcat(_("Alleged country of origin: "), country, NULL);
+ }
+ else {
+ /* TRANSLATORS: The IP address is appended to the string */
+ text = g_strconcat(_("Could not resolve location of IP address "), ip, NULL);
+ }
+ gtk_label_set_text(GTK_LABEL(label), text);
+ debug_print("%s\n", text);
+ gtk_toggle_button_set_active(button, FALSE);
+ }
+ g_free(text);
+ }
+ else {
+ /* swich to first notebook page */
+ MessageView *messageview;
+ messageview = data;
+ gtk_notebook_set_current_page(GTK_NOTEBOOK(messageview->mimeview->mime_notebook), 0);
+ }
+}
+
+static void container_finalize_cb(gpointer data, GObject *where_the_object_was)
+{
+ container_list = g_slist_remove(container_list, where_the_object_was);
+}
+
+static GtkWidget* get_geolocation_container_from_messageview(MessageView *messageview)
+{
+ GtkWidget *container = NULL;
+ GtkWidget *vbox;
+ GList *children, *walk;
+ GtkWidget *button;
+ gulong *cb_id;
+
+ g_return_val_if_fail(messageview && messageview->mimeview && messageview->mimeview->paned, NULL);
+
+ vbox = gtk_paned_get_child2(GTK_PANED(messageview->mimeview->paned));
+
+ /* check if there is already a geolocation container */
+ children = gtk_container_get_children(GTK_CONTAINER(vbox));
+ for(walk = children; walk; walk = walk->next) {
+ GtkWidget *child = walk->data;
+ if(!strcmp(gtk_widget_get_name(child), GEOLOCATION_CONTAINER_NAME)) {
+ container = child;
+ break;
+ }
+ }
+ g_list_free(children);
+
+ /* if not, create one */
+ if(!container) {
+ GtkWidget *label;
+ GtkWidget *image;
+ GdkPixbuf *pixbuf, *scaled_pixbuf;
+
+ container = gtk_hbox_new(FALSE, 0);
+ gtk_widget_set_name(container, GEOLOCATION_CONTAINER_NAME);
+
+ /* button */
+ pixbuf = gdk_pixbuf_new_from_inline(-1, pixmap_earth, FALSE, NULL);
+ scaled_pixbuf = gdk_pixbuf_scale_simple(pixbuf, 16, 16, GDK_INTERP_BILINEAR);
+ g_object_unref(pixbuf);
+ image = gtk_image_new_from_pixbuf(scaled_pixbuf);
+ gtk_widget_show(image);
+ g_object_unref(scaled_pixbuf);
+ button = gtk_toggle_button_new();
+ gtk_widget_show(button);
+ gtk_container_add(GTK_CONTAINER(button), image);
+ gtk_box_pack_start(GTK_BOX(container), button, FALSE, FALSE, 0);
+ g_object_set_data(G_OBJECT(container), GEOLOCATION_CONTAINER_DATA_TOGGLEBUTTON, button);
+
+ /* label */
+ label = gtk_label_new("");
+ gtk_widget_show(label);
+ gtk_box_pack_start(GTK_BOX(container), label, FALSE, FALSE, 2);
+ g_object_set_data(G_OBJECT(container), GEOLOCATION_CONTAINER_DATA_LABEL, label);
+
+ gtk_box_pack_start(GTK_BOX(vbox), container, FALSE, FALSE, 0);
+
+ /* add new container to list */
+ container_list = g_slist_prepend(container_list, container);
+ g_object_weak_ref(G_OBJECT(container), container_finalize_cb, NULL);
+ }
+ /* if it existed, changed the button callback data */
+ else {
+ /* disconnect old signal handler from button */
+ gulong *id;
+ button = g_object_get_data(G_OBJECT(container), GEOLOCATION_CONTAINER_DATA_TOGGLEBUTTON);
+ g_return_val_if_fail(button, NULL);
+ id = g_object_get_data(G_OBJECT(button), GEOLOCATION_TOGGLE_BUTTON_DATA_CB_ID);
+ g_signal_handler_disconnect(button, *id);
+ }
+
+ /* connect new signal handler to button, and store its id */
+ cb_id = g_new(gulong, 1);
+ *cb_id = g_signal_connect(button, "toggled", G_CALLBACK(geolocation_button_toggled_cb), messageview);
+ g_object_set_data_full(G_OBJECT(button), GEOLOCATION_TOGGLE_BUTTON_DATA_CB_ID, cb_id, g_free);
+
+ return container;
+}
+
+static gboolean my_messageview_show_hook(gpointer source, gpointer data)
+{
+ MessageView *messageview;
+ GtkWidget *container;
+ GtkWidget *button;
+ gchar *ip;
+
+ messageview = source;
+
+ g_return_val_if_fail(messageview, FALSE);
+
+ container = get_geolocation_container_from_messageview(messageview);
+ g_return_val_if_fail(container, FALSE);
+
+ /* make sure toggle button is turned off */
+ button = g_object_get_data(G_OBJECT(container), GEOLOCATION_CONTAINER_DATA_TOGGLEBUTTON);
+ g_return_val_if_fail(button, FALSE);
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) {
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
+ }
+
+ /* do nothing except hiding the button if claws mail is in offline mode */
+ if(prefs_common.work_offline) {
+ gtk_widget_hide(container);
+ return FALSE;
+ }
+
+ /* try to get ip address from message */
+ if(!messageview->msginfo) {
+ debug_print("Warning: Messageview does not have a MsgInfo\n");
+ return FALSE;
+ }
+ ip = get_ip_from_msginfo(messageview->msginfo);
+ if(!ip) {
+ debug_print("Could not get IP address from message\n");
+ gtk_widget_hide(container);
+ }
+ else {
+ GtkWidget *label;
+ debug_print("Found sender ip address: %s\n", ip);
+ label = g_object_get_data(G_OBJECT(container), GEOLOCATION_CONTAINER_DATA_LABEL);
+ if(label) {
+ gchar *text;
+ text = g_strconcat(_("Try to locate sender"), NULL);
+ gtk_label_set_text(GTK_LABEL(label), text);
+ g_free(text);
+ }
+ /* button takes ownership of ip string */
+ g_object_set_data_full(G_OBJECT(button), GEOLOCATION_TOGGLE_BUTTON_DATA_IP, ip, g_free);
+ gtk_widget_show(container);
+ }
+
+ return FALSE;
+}
+
+#define ISO_IN(k,v) g_hash_table_insert(iso_country_hash, (k), (v))
+static void fill_iso_country_hash(void)
+{
+ iso_country_hash = g_hash_table_new(g_str_hash, g_str_equal);
+ ISO_IN("127.0.0.20", _("Andorra"));
+ ISO_IN("127.0.3.16", _("United Arab Emirates"));
+ ISO_IN("127.0.0.4", _("Afghanistan"));
+ ISO_IN("127.0.0.28", _("Antigua And Barbuda"));
+ ISO_IN("127.0.2.148", _("Anguilla"));
+ ISO_IN("127.0.0.8", _("Albania"));
+ ISO_IN("127.0.0.51", _("Armenia"));
+ ISO_IN("127.0.2.18", _("Netherlands Antilles"));
+ ISO_IN("127.0.0.24", _("Angola"));
+ ISO_IN("127.0.0.10", _("Antarctica"));
+ ISO_IN("127.0.0.32", _("Argentina"));
+ ISO_IN("127.0.0.16", _("American Samoa"));
+ ISO_IN("127.0.0.40", _("Austria"));
+ ISO_IN("127.0.0.36", _("Australia"));
+ ISO_IN("127.0.2.21", _("Aruba"));
+ ISO_IN("127.0.0.31", _("Azerbaijan"));
+ ISO_IN("127.0.0.70", _("Bosnia And Herzegovina"));
+ ISO_IN("127.0.0.52", _("Barbados"));
+ ISO_IN("127.0.0.50", _("Bangladesh"));
+ ISO_IN("127.0.0.56", _("Belgium"));
+ ISO_IN("127.0.3.86", _("Burkina Faso"));
+ ISO_IN("127.0.0.100", _("Bulgaria"));
+ ISO_IN("127.0.0.48", _("Bahrain"));
+ ISO_IN("127.0.0.108", _("Burundi"));
+ ISO_IN("127.0.0.204", _("Benin"));
+ ISO_IN("127.0.0.60", _("Bermuda"));
+ ISO_IN("127.0.0.96", _("Brunei Darussalam"));
+ ISO_IN("127.0.0.68", _("Bolivia"));
+ ISO_IN("127.0.0.76", _("Brazil"));
+ ISO_IN("127.0.0.44", _("Bahamas"));
+ ISO_IN("127.0.0.64", _("Bhutan"));
+ ISO_IN("127.0.0.74", _("Bouvet Island"));
+ ISO_IN("127.0.0.72", _("Botswana"));
+ ISO_IN("127.0.0.112", _("Belarus"));
+ ISO_IN("127.0.0.84", _("Belize"));
+ ISO_IN("127.0.0.124", _("Canada"));
+ ISO_IN("127.0.0.166", _("Cocos (Keeling) Islands"));
+ ISO_IN("127.0.0.140", _("Central African Republic"));
+ ISO_IN("127.0.0.178", _("Congo"));
+ ISO_IN("127.0.2.244", _("Switzerland"));
+ ISO_IN("127.0.1.128", _("Cote D'Ivoire"));
+ ISO_IN("127.0.0.184", _("Cook Islands"));
+ ISO_IN("127.0.0.152", _("Chile"));
+ ISO_IN("127.0.0.120", _("Cameroon"));
+ ISO_IN("127.0.0.156", _("China"));
+ ISO_IN("127.0.0.170", _("Colombia"));
+ ISO_IN("127.0.0.188", _("Costa Rica"));
+ ISO_IN("127.0.0.192", _("Cuba"));
+ ISO_IN("127.0.0.132", _("Cape Verde"));
+ ISO_IN("127.0.0.162", _("Christmas Island"));
+ ISO_IN("127.0.0.196", _("Cyprus"));
+ ISO_IN("127.0.0.203", _("Czech Republic"));
+ ISO_IN("127.0.1.20", _("Germany"));
+ ISO_IN("127.0.1.6", _("Djibouti"));
+ ISO_IN("127.0.0.208", _("Denmark"));
+ ISO_IN("127.0.0.212", _("Dominica"));
+ ISO_IN("127.0.0.214", _("Dominican Republic"));
+ ISO_IN("127.0.0.12", _("Algeria"));
+ ISO_IN("127.0.0.218", _("Ecuador"));
+ ISO_IN("127.0.0.233", _("Estonia"));
+ ISO_IN("127.0.3.50", _("Egypt"));
+ ISO_IN("127.0.2.220", _("Western Sahara"));
+ ISO_IN("127.0.0.232", _("Eritrea"));
+ ISO_IN("127.0.2.212", _("Spain"));
+ ISO_IN("127.0.0.231", _("Ethiopia"));
+ ISO_IN("127.0.0.246", _("Finland"));
+ ISO_IN("127.0.0.242", _("Fiji"));
+ ISO_IN("127.0.0.238", _("Falkland Islands (Malvinas)"));
+ ISO_IN("127.0.2.71", _("Micronesia, Federated States Of"));
+ ISO_IN("127.0.0.234", _("Faroe Islands"));
+ ISO_IN("127.0.0.250", _("France"));
+ ISO_IN("127.0.0.249", _("France, Metropolitan"));
+ ISO_IN("127.0.1.10", _("Gabon"));
+ ISO_IN("127.0.3.58", _("United Kingdom"));
+ ISO_IN("127.0.1.52", _("Grenada"));
+ ISO_IN("127.0.1.12", _("Georgia"));
+ ISO_IN("127.0.0.254", _("French Guiana"));
+ ISO_IN("127.0.1.32", _("Ghana"));
+ ISO_IN("127.0.1.36", _("Gibraltar"));
+ ISO_IN("127.0.1.48", _("Greenland"));
+ ISO_IN("127.0.1.14", _("Gambia"));
+ ISO_IN("127.0.1.68", _("Guinea"));
+ ISO_IN("127.0.1.56", _("Guadeloupe"));
+ ISO_IN("127.0.0.226", _("Equatorial Guinea"));
+ ISO_IN("127.0.1.44", _("Greece"));
+ ISO_IN("127.0.0.239", _("South Georgia And The South Sandwich Islands"));
+ ISO_IN("127.0.1.64", _("Guatemala"));
+ ISO_IN("127.0.1.60", _("Guam"));
+ ISO_IN("127.0.2.112", _("Guinea-Bissau"));
+ ISO_IN("127.0.1.72", _("Guyana"));
+ ISO_IN("127.0.1.88", _("Hong Kong"));
+ ISO_IN("127.0.1.78", _("Heard Island And Mcdonald Islands"));
+ ISO_IN("127.0.1.84", _("Honduras"));
+ ISO_IN("127.0.0.191", _("Croatia"));
+ ISO_IN("127.0.1.76", _("Haiti"));
+ ISO_IN("127.0.1.92", _("Hungary"));
+ ISO_IN("127.0.1.104", _("Indonesia"));
+ ISO_IN("127.0.1.116", _("Ireland"));
+ ISO_IN("127.0.1.120", _("Israel"));
+ ISO_IN("127.0.1.100", _("India"));
+ ISO_IN("127.0.0.86", _("British Indian Ocean Territory"));
+ ISO_IN("127.0.1.112", _("Iraq"));
+ ISO_IN("127.0.1.108", _("Iran, Islamic Republic Of"));
+ ISO_IN("127.0.1.96", _("Iceland"));
+ ISO_IN("127.0.1.124", _("Italy"));
+ ISO_IN("127.0.1.132", _("Jamaica"));
+ ISO_IN("127.0.1.144", _("Jordan"));
+ ISO_IN("127.0.1.136", _("Japan"));
+ ISO_IN("127.0.1.148", _("Kenya"));
+ ISO_IN("127.0.1.161", _("Kyrgyzstan"));
+ ISO_IN("127.0.0.116", _("Cambodia"));
+ ISO_IN("127.0.1.40", _("Kiribati"));
+ ISO_IN("127.0.0.174", _("Comoros"));
+ ISO_IN("127.0.2.147", _("Saint Kitts And Nevis"));
+ ISO_IN("127.0.1.152", _("Korea, Democratic People'S Republic Of"));
+ ISO_IN("127.0.1.154", _("Korea, Republic Of"));
+ ISO_IN("127.0.1.158", _("Kuwait"));
+ ISO_IN("127.0.0.136", _("Cayman Islands"));
+ ISO_IN("127.0.1.142", _("Kazakhstan"));
+ ISO_IN("127.0.1.162", _("Lao People'S Democratic Republic"));
+ ISO_IN("127.0.1.166", _("Lebanon"));
+ ISO_IN("127.0.2.150", _("Saint Lucia"));
+ ISO_IN("127.0.1.182", _("Liechtenstein"));
+ ISO_IN("127.0.0.144", _("Sri Lanka"));
+ ISO_IN("127.0.1.174", _("Liberia"));
+ ISO_IN("127.0.1.170", _("Lesotho"));
+ ISO_IN("127.0.1.184", _("Lithuania"));
+ ISO_IN("127.0.1.186", _("Luxembourg"));
+ ISO_IN("127.0.1.172", _("Latvia"));
+ ISO_IN("127.0.1.178", _("Libyan Arab Jamahiriya"));
+ ISO_IN("127.0.1.248", _("Morocco"));
+ ISO_IN("127.0.1.236", _("Monaco"));
+ ISO_IN("127.0.1.242", _("Moldova, Republic Of"));
+ ISO_IN("127.0.1.194", _("Madagascar"));
+ ISO_IN("127.0.2.72", _("Marshall Islands"));
+ ISO_IN("127.0.3.39", _("Macedonia, The Former Yugoslav Republic Of"));
+ ISO_IN("127.0.1.210", _("Mali"));
+ ISO_IN("127.0.0.104", _("Myanmar"));
+ ISO_IN("127.0.1.240", _("Mongolia"));
+ ISO_IN("127.0.1.190", _("Macao"));
+ ISO_IN("127.0.2.68", _("Northern Mariana Islands"));
+ ISO_IN("127.0.1.218", _("Martinique"));
+ ISO_IN("127.0.1.222", _("Mauritania"));
+ ISO_IN("127.0.1.244", _("Montserrat"));
+ ISO_IN("127.0.1.214", _("Malta"));
+ ISO_IN("127.0.1.224", _("Mauritius"));
+ ISO_IN("127.0.1.206", _("Maldives"));
+ ISO_IN("127.0.1.198", _("Malawi"));
+ ISO_IN("127.0.1.228", _("Mexico"));
+ ISO_IN("127.0.1.202", _("Malaysia"));
+ ISO_IN("127.0.1.252", _("Mozambique"));
+ ISO_IN("127.0.2.4", _("Namibia"));
+ ISO_IN("127.0.2.28", _("New Caledonia"));
+ ISO_IN("127.0.2.50", _("Niger"));
+ ISO_IN("127.0.2.62", _("Norfolk Island"));
+ ISO_IN("127.0.2.54", _("Nigeria"));
+ ISO_IN("127.0.2.46", _("Nicaragua"));
+ ISO_IN("127.0.2.16", _("Netherlands"));
+ ISO_IN("127.0.2.66", _("Norway"));
+ ISO_IN("127.0.2.12", _("Nepal"));
+ ISO_IN("127.0.2.8", _("Nauru"));
+ ISO_IN("127.0.2.58", _("Niue"));
+ ISO_IN("127.0.2.42", _("New Zealand"));
+ ISO_IN("127.0.2.0", _("Oman"));
+ ISO_IN("127.0.2.79", _("Panama"));
+ ISO_IN("127.0.2.92", _("Peru"));
+ ISO_IN("127.0.1.2", _("French Polynesia"));
+ ISO_IN("127.0.2.86", _("Papua New Guinea"));
+ ISO_IN("127.0.2.96", _("Philippines"));
+ ISO_IN("127.0.2.74", _("Pakistan"));
+ ISO_IN("127.0.2.104", _("Poland"));
+ ISO_IN("127.0.2.154", _("Saint Pierre And Miquelon"));
+ ISO_IN("127.0.2.100", _("Pitcairn"));
+ ISO_IN("127.0.2.118", _("Puerto Rico"));
+ ISO_IN("127.0.2.108", _("Portugal"));
+ ISO_IN("127.0.2.73", _("Palau"));
+ ISO_IN("127.0.2.88", _("Paraguay"));
+ ISO_IN("127.0.2.122", _("Qatar"));
+ ISO_IN("127.0.2.126", _("Reunion"));
+ ISO_IN("127.0.2.130", _("Romania"));
+ ISO_IN("127.0.2.131", _("Russian Federation"));
+ ISO_IN("127.0.2.134", _("Rwanda"));
+ ISO_IN("127.0.2.170", _("Saudi Arabia"));
+ ISO_IN("127.0.0.90", _("Solomon Islands"));
+ ISO_IN("127.0.2.178", _("Seychelles"));
+ ISO_IN("127.0.2.224", _("Sudan"));
+ ISO_IN("127.0.2.240", _("Sweden"));
+ ISO_IN("127.0.2.190", _("Singapore"));
+ ISO_IN("127.0.2.142", _("Saint Helena"));
+ ISO_IN("127.0.2.193", _("Slovenia"));
+ ISO_IN("127.0.2.232", _("Svalbard And Jan Mayen"));
+ ISO_IN("127.0.2.191", _("Slovakia"));
+ ISO_IN("127.0.2.182", _("Sierra Leone"));
+ ISO_IN("127.0.2.162", _("San Marino"));
+ ISO_IN("127.0.2.174", _("Senegal"));
+ ISO_IN("127.0.2.194", _("Somalia"));
+ ISO_IN("127.0.2.228", _("Suriname"));
+ ISO_IN("127.0.2.166", _("Sao Tome And Principe"));
+ ISO_IN("127.0.0.222", _("El Salvador"));
+ ISO_IN("127.0.2.248", _("Syrian Arab Republic"));
+ ISO_IN("127.0.2.236", _("Swaziland"));
+ ISO_IN("127.0.3.28", _("Turks And Caicos Islands"));
+ ISO_IN("127.0.0.148", _("Chad"));
+ ISO_IN("127.0.1.4", _("French Southern Territories"));
+ ISO_IN("127.0.3.0", _("Togo"));
+ ISO_IN("127.0.2.252", _("Thailand"));
+ ISO_IN("127.0.2.250", _("Tajikistan"));
+ ISO_IN("127.0.3.4", _("Tokelau"));
+ ISO_IN("127.0.3.27", _("Turkmenistan"));
+ ISO_IN("127.0.3.20", _("Tunisia"));
+ ISO_IN("127.0.3.8", _("Tonga"));
+ ISO_IN("127.0.2.114", _("East Timor"));
+ ISO_IN("127.0.3.24", _("Turkey"));
+ ISO_IN("127.0.3.12", _("Trinidad And Tobago"));
+ ISO_IN("127.0.3.30", _("Tuvalu"));
+ ISO_IN("127.0.0.158", _("Taiwan, Province Of China"));
+ ISO_IN("127.0.3.66", _("Tanzania, United Republic Of"));
+ ISO_IN("127.0.3.36", _("Ukraine"));
+ ISO_IN("127.0.3.32", _("Uganda"));
+ ISO_IN("127.0.3.58", _("United Kingdom"));
+ ISO_IN("127.0.2.69", _("United States Minor Outlying Islands"));
+ ISO_IN("127.0.3.72", _("United States"));
+ ISO_IN("127.0.3.90", _("Uruguay"));
+ ISO_IN("127.0.3.92", _("Uzbekistan"));
+ ISO_IN("127.0.1.80", _("Holy See (Vatican City State)"));
+ ISO_IN("127.0.2.158", _("Saint Vincent And The Grenadines"));
+ ISO_IN("127.0.3.94", _("Venezuela"));
+ ISO_IN("127.0.0.92", _("Virgin Islands, British"));
+ ISO_IN("127.0.3.82", _("Virgin Islands, U.S."));
+ ISO_IN("127.0.2.192", _("Viet Nam"));
+ ISO_IN("127.0.2.36", _("Vanuatu"));
+ ISO_IN("127.0.3.108", _("Wallis And Futuna"));
+ ISO_IN("127.0.3.114", _("Samoa"));
+ ISO_IN("127.0.3.119", _("Yemen"));
+ ISO_IN("127.0.0.175", _("Mayotte"));
+ ISO_IN("127.0.3.123", _("Serbia And Montenegro"));
+ ISO_IN("127.0.2.198", _("South Africa"));
+ ISO_IN("127.0.3.126", _("Zambia"));
+ ISO_IN("127.0.0.180", _("Democratic Republic Of The Congo"));
+ ISO_IN("127.0.2.204", _("Zimbabwe"));
+}
+#undef ISO_IN
+
+gint plugin_init(gchar **error)
+{
+ GError *err = NULL;
+
+ /* Version check */
+ if(!check_plugin_version(MAKE_NUMERIC_VERSION(3,7,1,55),
+ VERSION_NUMERIC, _("GeoLocation"), error))
+ return -1;
+
+ if(gtk_clutter_init(0, NULL) != CLUTTER_INIT_SUCCESS)
+ {
+ *error = g_strdup_printf(_("Could not initialize clutter"));
+ return -1;
+ }
+
+ ip_from_received_header_regex = g_regex_new(EXTRACT_IP_FROM_RECEIVED_HEADER_REGEX, 0, 0, &err);
+ if(err) {
+ *error = g_strdup_printf(_("Could not create regular expression: %s\n"), err->message);
+ g_error_free(err);
+ return -1;
+ }
+
+ lat_lon_from_hostip_response_regex = g_regex_new(EXTRACT_LAT_LON_FROM_HOSTIP_RESPONSE_REGEX, 0, 0, &err);
+ if(err) {
+ *error = g_strdup_printf(_("Could not create regular expression: %s\n"), err->message);
+ g_error_free(err);
+ g_regex_unref(ip_from_received_header_regex);
+ return -1;
+ }
+
+ hook_messageview_show = hooks_register_hook(MESSAGE_VIEW_SHOW_DONE_HOOKLIST, my_messageview_show_hook, NULL);
+ if(hook_messageview_show == (guint) -1) {
+ *error = g_strdup(_("Failed to register messageview_show hook in the GeoLocation plugin"));
+ g_regex_unref(ip_from_received_header_regex);
+ g_regex_unref(lat_lon_from_hostip_response_regex);
+ return -1;
+ }
+
+ fill_iso_country_hash();
+
+ debug_print("GeoLocation plugin loaded\n");
+
+ return 0;
+}
+
+gboolean plugin_done(void)
+{
+
+ hooks_unregister_hook(MESSAGE_VIEW_SHOW_DONE_HOOKLIST, hook_messageview_show);
+
+ if(!claws_is_exiting()) {
+ GSList *copy, *walk;
+
+ copy = g_slist_copy(container_list);
+ for(walk = copy; walk; walk = walk->next) {
+ GtkWidget *wid = walk->data;
+ GtkWidget *button = g_object_get_data(G_OBJECT(wid), GEOLOCATION_CONTAINER_DATA_TOGGLEBUTTON);
+ if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button)))
+ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), FALSE);
+ gtk_widget_destroy(GTK_WIDGET(wid));
+ }
+ g_slist_free(copy);
+ if(container_list) {
+ g_slist_free(container_list);
+ container_list = NULL;
+ }
+
+ if(ip_from_received_header_regex) {
+ g_regex_unref(ip_from_received_header_regex);
+ ip_from_received_header_regex = NULL;
+ }
+
+ if(lat_lon_from_hostip_response_regex) {
+ g_regex_unref(lat_lon_from_hostip_response_regex);
+ lat_lon_from_hostip_response_regex = NULL;
+ }
+
+ if(iso_country_hash) {
+ g_hash_table_destroy(iso_country_hash);
+ iso_country_hash = NULL;
+ }
+ }
+
+ debug_print("GeoLocation plugin unloaded\n");
+
+ /* returning FALSE because dependant libraries may not be unload-safe. */
+ return FALSE;
+}
+
+const gchar *plugin_name(void)
+{
+ return _("GeoLocation");
+}
+
+const gchar *plugin_desc(void)
+{
+ return _("This plugin provides GeoLocation functionality "
+ "for Claws Mail.\n\n"
+ "Warning: It is technically impossible to derive the geographic "
+ "location of senders from their E-Mails with any amount of certainty. "
+ "The results presented by "
+ "this plugin are only rough estimates. In particular, mailing list managers "
+ "often strip sender information from the mails, so mails from mailing lists "
+ "may be assigned to the location of the mailing list server instead of the "
+ "mail sender.\n"
+ "When in doubt, don't trust the results of this plugin, and don't rely on this "
+ "information to divorce your spouse.\n"
+ "\nFeedback to <berndth at gmx.de> is welcome "
+ "(but only if it's not about marital quarrels).");
+}
+
+const gchar *plugin_type(void)
+{
+ return "GTK2";
+}
+
+const gchar *plugin_licence(void)
+{
+ return "GPL3+";
+}
+
+const gchar *plugin_version(void)
+{
+ return VERSION;
+}
+
+struct PluginFeature *plugin_provides(void)
+{
+ static struct PluginFeature features[] =
+ { {PLUGIN_UTILITY, N_("GeoLocation integration")},
+ {PLUGIN_NOTHING, NULL}};
+ return features;
+}
diff --git a/src/plugins/geolocation/pixmap_earth.h b/src/plugins/geolocation/pixmap_earth.h
new file mode 100644
index 0000000..625ed07
--- /dev/null
+++ b/src/plugins/geolocation/pixmap_earth.h
@@ -0,0 +1,123 @@
+/* GdkPixbuf RGBA C-Source image dump */
+
+#ifdef __SUNPRO_C
+#pragma align 4 (pixmap_earth)
+#endif
+#ifdef __GNUC__
+static const guint8 pixmap_earth[] __attribute__ ((__aligned__ (4))) =
+#else
+static const guint8 pixmap_earth[] =
+#endif
+{ ""
+ /* Pixbuf magic (0x47646b50) */
+ "GdkP"
+ /* length: header (24) + pixel_data (2304) */
+ "\0\0\11\30"
+ /* pixdata_type (0x1010002) */
+ "\1\1\0\2"
+ /* rowstride (96) */
+ "\0\0\0`"
+ /* width (24) */
+ "\0\0\0\30"
+ /* height (24) */
+ "\0\0\0\30"
+ /* pixel_data: */
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "99l\12""99m)99l077l\36++\200\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0""88k\15RR\200s\231\234\264\316\236\241\273\372"
+ "\271\275\317\372\271\276\320\372\234\246\302\371\206\216\257\361_d\217"
+ "\244:=oD\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0KM{W\227\233\266\351\331"
+ "\340\350\377\311\327\347\377\356\360\361\377\376\376\376\377\353\354"
+ "\355\377\253\302\332\377\245\301\337\377\244\277\335\377\227\250\306"
+ "\374[b\215\270;;n\32\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0jl\222\202\324\325\336\375\302\313\324"
+ "\377\305\314\324\377\307\322\335\377\350\354\357\377\313\322\330\377"
+ "\271\306\323\377\273\314\337\377\264\314\346\377\306\325\344\377\327"
+ "\332\335\377\315\322\331\377\207\213\244\344:=p.\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\_\211l\343\344\352\375"
+ "\267\310\332\377\337\353\366\377\325\332\337\377\341\357\376\377\322"
+ "\335\351\377\331\350\370\377\320\342\364\377\305\331\356\377\273\316"
+ "\341\377\320\327\336\377\264\276\311\377\360\361\361\377\347\347\347"
+ "\377\210\214\243\343::m\30\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0 at Bu)\306\310\326\371\376\376\376\377\360\362\363\377\364\364\364"
+ "\377\327\332\335\377\323\336\351\377\342\361\377\377\335\355\374\377"
+ "\323\345\367\377\310\331\354\377\307\316\326\377\355\357\360\377\371"
+ "\372\372\377\370\370\370\377\346\346\346\377\334\334\335\377fi\212\262"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\211\213\250\255\376"
+ "\376\376\377\376\376\376\377\376\376\376\377\340\343\346\377\323\337"
+ "\353\377\333\351\367\377\341\360\377\377\337\356\375\377\324\346\370"
+ "\377\315\335\356\377\345\347\352\377\321\325\333\377\355\356\360\377"
+ "\372\372\372\377\352\352\352\377\330\330\330\377\262\264\274\3759<oA"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0""88n\33\304\305\324\373\376\376\376"
+ "\377\376\376\376\377\320\325\333\377\325\345\365\377\337\357\377\377"
+ "\337\357\377\377\340\357\377\377\335\355\375\377\322\345\367\377\315"
+ "\334\353\377\303\313\323\377\266\310\334\377\241\265\313\377\242\265"
+ "\312\377\323\326\332\377\330\330\330\377\321\321\321\377`c\200\247\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0BEvi\371\371\372\377\330\333\336\377\314"
+ "\321\325\377\274\322\352\377\327\352\376\377\336\356\377\377\336\357"
+ "\377\377\336\356\376\377\327\351\373\377\315\340\365\377\334\345\357"
+ "\377\376\376\376\377\376\376\376\377\337\343\350\377\317\330\342\377"
+ "\330\332\335\377\327\327\327\377\274\275\277\377\206\207\235\363@@j\3"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\200\201\240\216\323\327\333\377\240\277\337"
+ "\377\254\310\346\377\274\326\362\377\306\336\367\377\325\350\373\377"
+ "\330\352\373\377\324\347\372\377\315\341\366\377\314\334\356\377\376"
+ "\376\376\377\376\376\376\377\376\376\376\377\376\376\376\377\366\366"
+ "\366\377\247\262\277\377\321\321\322\377\214\231\250\377t~\230\37199"
+ "k\"\0\0\0\0\0\0\0\0\0\0\0\0ns\230\237\334\340\345\377\321\327\335\377"
+ "\244\301\337\377\257\314\353\377\267\322\357\377\275\326\362\377\303"
+ "\333\363\377\306\334\363\377\301\330\360\377\320\335\353\377\376\376"
+ "\376\377\376\376\376\377\376\376\376\377\375\375\375\377\360\360\360"
+ "\377\324\325\327\377\232\247\265\377\204\217\234\377ex\236\37388k7\0"
+ "\0\0\0\0\0\0\0\0\0\0\0]c\215\227\241\275\334\377\232\262\314\377\254"
+ "\273\313\377\335\345\354\377\323\342\361\377\251\306\345\377\254\312"
+ "\351\377\251\307\347\377\246\304\345\377\247\300\333\377\367\367\370"
+ "\377\376\376\376\377\376\376\376\377\367\367\367\377\350\350\350\377"
+ "\330\330\330\377\262\265\271\377Pm\220\377dv\234\37288l/\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\77Ar}\242\275\333\377\201\247\321\377\241\273\327\377\376"
+ "\376\376\377\376\376\376\377\320\327\340\377\234\274\337\377\231\273"
+ "\337\377\224\267\334\377\214\261\330\377\230\262\317\377\206\241\275"
+ "\377\251\271\314\377\354\354\354\377\336\336\336\377\317\317\317\377"
+ "\251\254\257\377;^\213\377bn\224\37166l\17\0\0\0\0\0\0\0\0\0\0\0\0;="
+ "pC\221\246\307\374s\235\312\377\310\327\351\377\376\376\376\377\376\376"
+ "\376\377\376\376\376\377\345\351\355\377\245\275\327\377\204\253\323"
+ "\377~\245\320\377v\236\313\377l\227\306\377v\231\300\377\340\340\340"
+ "\377\322\322\322\377\304\304\304\377\\s\217\377Jj\225\377U]\206\324\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0..t\2r~\244\343t\234\310\377\232\262\315"
+ "\377\367\367\367\377\373\373\373\377\375\375\375\377\375\375\375\377"
+ "\256\274\313\377u\236\313\377o\231\310\377h\223\304\377_\214\277\377"
+ "X\206\272\377\310\312\314\377\305\305\305\377\270\270\270\377Kd\204\377"
+ "]t\230\377<>ov\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\77Cth\206\242"
+ "\307\375`\215\277\377\255\273\312\377\352\352\352\377\355\355\355\377"
+ "\357\357\357\377~\231\266\377e\221\302\377`\215\277\377Y\210\274\377"
+ "Q\201\267\377L}\263\377\303\303\303\377\270\270\270\377\227\232\235\377"
+ "Lc\203\377V`\207\351;;m\16\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\10"
+ "\10\20\17V_\211\315v\234\305\377d\214\270\377\330\330\330\377\333\333"
+ "\333\377\252\264\300\377W\201\256\377U\205\271\377Q\201\267\377J|\264"
+ "\377Cv\257\377\77p\250\377\240\244\251\377\252\252\252\377bp\203\377"
+ "`o\222\374/0Xm\0\0\0\12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0"
+ "\32\24\25'I[f\220\346q\226\300\377\304\304\304\377\307\307\307\377Xz"
+ "\240\377Hz\262\377Ex\261\377Bu\255\377\77p\250\377=k\242\377<f\231\377"
+ "v\206\232\377\211\213\216\377eq\215\37546]\253\0\0\0""0\0\0\0\27\0\0"
+ "\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\4\0\0\0\33\0\0\0""4\21\21\40aSY\177"
+ "\336\265\267\273\376t\206\233\377=m\244\377>n\245\377=l\242\377=i\236"
+ "\377<e\230\377;a\222\377;]\212\377Vl\215\377]h\214\375,.P\253\0\0\0J"
+ "\0\0\0""1\0\0\0\30\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\17\0"
+ "\0\0'\0\0\0>\2\2\5X)+K\252Ze\213\363g~\245\376b\202\252\377Xx\241\377"
+ "Ts\234\377Yt\233\377_u\231\377^j\217\375 at Dk\332\27\27,\205\0\0\0Q\0\0"
+ "\0:\0\0\0#\0\0\0\13\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\15\0\0\0!\0\0\0""5\0\0\0G\2\2\5Z\35\36""9\215,-Q\262<@c\306 at Dh\314"
+ "68[\277%'H\250\20\20\40w\0\0\0U\0\0\0D\0\0\0""2\0\0\0\36\0\0\0\12\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\3"
+ "\0\0\0\15\0\0\0\34\0\0\0(\0\0\0""3\0\0\0;\0\0\0\77\0\0\0A\0\0\0\77\0"
+ "\0\0:\0\0\0""1\0\0\0'\0\0\0\31\0\0\0\13\0\0\0\2\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\1\0\0\0\6\0\0\0\11\0\0\0\13\0\0\0\14\0\0\0\13\0\0\0\11\0"
+ "\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0"};
+
+
commit 4f1b728770f4356230445fafb28ef9dd35232519
Author: Holger Berndt <hb at claws-mail.org>
Date: Thu Apr 4 21:36:53 2013 +0200
Add jhbuild module files and sample config
diff --git a/tools/jhbuild/README b/tools/jhbuild/README
new file mode 100644
index 0000000..b93bcc1
--- /dev/null
+++ b/tools/jhbuild/README
@@ -0,0 +1,17 @@
+Building Claws Mail with JHBuild
+--------------------------------
+
+Claws Mail can be built with JHBuild. This way, it's easy to do
+sandboxed builds, for example in order to try out different versions
+of low-level dependencies like gtk+ or glib without messing up a production
+system. It's also useful to build older dependencies that are otherwise hard
+to get on a more recent distribution.
+
+In order to use JHBuild for building Claws Mail, first, JHBuild itself
+must be built and installed, see
+https://developer.gnome.org/jhbuild/stable/getting-started.html
+
+JHBuild needs a configuration file, either as ~/.jhbuildrc or given with the
+parameter -f on the command line. You can use the file
+sample.jhbuildrc-claws-mail as a starting point, but you'll have to modify
+it to suit your local environment.
diff --git a/tools/jhbuild/claws-mail.modules b/tools/jhbuild/claws-mail.modules
new file mode 100644
index 0000000..53151ce
--- /dev/null
+++ b/tools/jhbuild/claws-mail.modules
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<!DOCTYPE moduleset SYSTEM "moduleset.dtd">
+<?xml-stylesheet type="text/xsl" href="moduleset.xsl"?>
+<moduleset>
+
+ <repository type="git" name="git.claws-mail.org" href="git://git.claws-mail.org/" default="yes"/>
+ <repository type="git" name="git.gnome.org" href="git://git.gnome.org/"/>
+
+ <autotools id="claws-mail">
+ <branch module="claws"/>
+ <dependencies>
+ <dep package="gtk+"/>
+ </dependencies>
+ <suggests>
+ <dep package="libchamplain"/>
+ <dep package="libgdata"/>
+ </suggests>
+ </autotools>
+
+ <!-- Dependencies -->
+
+ <autotools id="gtk+">
+ <branch repo="git.gnome.org" revision="gtk-2-24"/>
+ <dependencies>
+ <dep package="glib"/>
+ </dependencies>
+ </autotools>
+
+ <autotools id="glib">
+ <branch repo="git.gnome.org"/>
+ </autotools>
+
+ <autotools id="libgdata">
+ <pkg-config>libgdata.pc</pkg-config>
+ <branch repo="git.gnome.org"/>
+ <dependencies>
+ <dep package="glib"/>
+ <dep package="liboauth"/>
+ </dependencies>
+ </autotools>
+
+ <tarball id="liboauth" version="0.9.4">
+ <pkg-config>oauth.pc</pkg-config>
+ <source href="http://downloads.sourceforge.net/liboauth/liboauth-0.9.4.tar.gz" hash="sha256:77e372359caca5375fbcc63ac638f349e6c93c98d291992d8ebb9bb8291ca549"
+ md5sum="973ded7a1af348c5bfe4e3b6b7e47bd3"
+ size="459597"/>
+ </tarball>
+
+ <tarball id="libchamplain" version="0.8.3" makeargs="LDFLAGS='-lgthread-2.0'">
+ <source href="ftp://ftp.gnome.org/pub/GNOME/sources/libchamplain/0.8/libchamplain-0.8.3.tar.gz"
+ hash="sha256:e4d7e89195ac91e1e348187be1718dbb7569d1d40fde007cd276256f92e53710"
+ size="863691"/>
+ <dependencies>
+ <dep package="clutter-gtk"/>
+ </dependencies>
+ </tarball>
+
+ <tarball id="clutter-gtk" version="0.10.8" makeargs="LDFLAGS='-lm -lgthread-2.0'">
+ <source href="ftp://ftp.gnome.org/pub/GNOME/sources/clutter-gtk/0.10/clutter-gtk-0.10.8.tar.gz"
+ hash="sha256:8ef57c1a0c6227704e89350805d10caaa9cc3f1bea6263211b05acd473fdfdc4"
+ size="391461"/>
+ </tarball>
+
+</moduleset>
diff --git a/tools/jhbuild/sample.jhbuildrc-claws-mail b/tools/jhbuild/sample.jhbuildrc-claws-mail
new file mode 100644
index 0000000..c8adb47
--- /dev/null
+++ b/tools/jhbuild/sample.jhbuildrc-claws-mail
@@ -0,0 +1,45 @@
+# -*- mode: python -*-
+#
+# Sample jhbuildrc configuration file for building Claws Mail and
+# some of its dependencies.
+
+# Select module set to use
+moduleset = os.path.expanduser('~/src/claws-mail/claws/tools/jhbuild/claws-mail.modules')
+
+# repo login in case of write access
+#repos["git.claws-mail.org"] = 'ssh://git.claws-mail.org/home/git/'
+
+# default modules
+modules = ['claws-mail']
+
+# what directory should the source be checked out to?
+checkoutroot = os.path.expanduser('~/src/claws-mail')
+
+# the prefix to configure/install modules to (must have write access)
+prefix = '/opt/claws-mail'
+
+# make arguments (e.g. concurrent build)
+#makeargs = '-j4'
+
+# environment vars (e.g. CFLAGS)
+#os.environ['CFLAGS'] = '-g -O0'
+
+# module-specific autofoo args
+#module_autogenargs['claws-mail'] = autogenargs + "--disable-manual"
+
+# path for building (if None, build in-tree)
+#buildroot = None
+
+# skip building of dependant modules (system-installed ones will be used)
+skip = [
+ "glib"
+ , "gtk+"
+ , "libgdata"
+ , "libchamplain"
+ ]
+
+# speficif branches/tags of modules that should be built
+#branches['libgdata'] = (None, 'LIBGDATA_0_10_1')
+
+# module specific extra environment variables
+#module_extra_env = { "clutter-gtk" : {"LDFLAGS" : "-lm -lgthread-2.0"} }
-----------------------------------------------------------------------
Summary of changes:
.gitignore | 7 +
configure.ac | 46 +
src/plugins/Makefile.am | 1 +
.../{pdf_viewer => geolocation}/Makefile.am | 19 +-
src/plugins/geolocation/geolocation_plugin.c | 903 ++++++++++++++++++++
src/plugins/geolocation/pixmap_earth.h | 123 +++
tools/jhbuild/README | 17 +
tools/jhbuild/claws-mail.modules | 64 ++
tools/jhbuild/sample.jhbuildrc-claws-mail | 45 +
9 files changed, 1217 insertions(+), 8 deletions(-)
copy src/plugins/{pdf_viewer => geolocation}/Makefile.am (57%)
create mode 100644 src/plugins/geolocation/geolocation_plugin.c
create mode 100644 src/plugins/geolocation/pixmap_earth.h
create mode 100644 tools/jhbuild/README
create mode 100644 tools/jhbuild/claws-mail.modules
create mode 100644 tools/jhbuild/sample.jhbuildrc-claws-mail
hooks/post-receive
--
Claws Mail
More information about the Commits
mailing list