diff options
Diffstat (limited to 'src/trg-peers-model.c')
-rw-r--r-- | src/trg-peers-model.c | 123 |
1 files changed, 112 insertions, 11 deletions
diff --git a/src/trg-peers-model.c b/src/trg-peers-model.c index 0d15753..d8e42ed 100644 --- a/src/trg-peers-model.c +++ b/src/trg-peers-model.c @@ -28,6 +28,7 @@ #include <glib/gstdio.h> #ifdef HAVE_GEOIP #include <GeoIP.h> +#include <GeoIPCity.h> #endif #include "trg-tree-view.h" @@ -46,6 +47,7 @@ typedef struct _TrgPeersModelPrivate TrgPeersModelPrivate; struct _TrgPeersModelPrivate { GeoIP *geoip; GeoIP *geoipv6; + GeoIP *geoipcity; }; #endif @@ -57,7 +59,7 @@ static void trg_peers_model_class_init(TrgPeersModelClass * #endif } -gboolean +static gboolean find_existing_peer_item_foreachfunc(GtkTreeModel * model, GtkTreePath * path G_GNUC_UNUSED, @@ -78,7 +80,7 @@ find_existing_peer_item_foreachfunc(GtkTreeModel * model, return pi->found; } -gboolean +static gboolean find_existing_peer_item(TrgPeersModel * model, JsonObject * p, GtkTreeIter * iter) { @@ -143,6 +145,20 @@ static void resolved_dns_cb(GObject * source_object, GAsyncResult * res, } } +#ifdef HAVE_GEOIP +/* for handling v4 or v6 addresses. string is owned by GeoIP, should not be freed. */ +static const gchar* lookup_country(TrgPeersModel *model, const gchar *address) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + + if (strchr(address, ':') && priv->geoipv6) + return GeoIP_country_name_by_addr_v6(priv->geoipv6, address); + else if (priv->geoip) + return GeoIP_country_name_by_addr(priv->geoip, address); + else + return NULL; +} +#endif + void trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, gint64 updateSerial, JsonObject * t, gint mode) @@ -151,6 +167,8 @@ trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); gboolean doGeoLookup = trg_tree_view_is_column_showing(tv, PEERSCOL_COUNTRY); + gboolean doGeoCityLookup = + trg_tree_view_is_column_showing(tv, PEERSCOL_CITY); #endif gboolean doHostLookup = @@ -171,6 +189,7 @@ trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, const gchar *address = NULL, *flagStr; #ifdef HAVE_GEOIP const gchar *country = NULL; + GeoIPRecord *city = NULL; #endif if (mode == TORRENT_GET_MODE_FIRST @@ -179,21 +198,19 @@ trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, address = peer_get_address(peer); #ifdef HAVE_GEOIP - if (address && doGeoLookup) { /* just in case address wasn't set */ - if (strchr(address, ':') && priv->geoipv6) - country = - GeoIP_country_name_by_addr_v6(priv->geoipv6, - address); - else if (priv->geoip) - country = - GeoIP_country_name_by_addr(priv->geoip, address); + if (address) { /* just in case address wasn't set */ + if (doGeoLookup) + country = lookup_country(model, address); + if (doGeoCityLookup) + city = GeoIP_record_by_addr(priv->geoipcity, address); } #endif gtk_list_store_set(GTK_LIST_STORE(model), &peerIter, - PEERSCOL_ICON, GTK_STOCK_NETWORK, + PEERSCOL_ICON, "network-workgroup", PEERSCOL_IP, address, #ifdef HAVE_GEOIP PEERSCOL_COUNTRY, country ? country : "", + PEERSCOL_CITY, city ? city->city : "", #endif PEERSCOL_CLIENT, peer_get_client_name(peer), -1); @@ -203,6 +220,11 @@ trg_peers_model_update(TrgPeersModel * model, TrgTreeView * tv, isNew = FALSE; } +#ifdef HAVE_GEOIP + if (city) + GeoIPRecord_delete(city); +#endif + flagStr = peer_get_flagstr(peer); gtk_list_store_set(GTK_LIST_STORE(model), &peerIter, PEERSCOL_FLAGS, flagStr, PEERSCOL_PROGRESS, @@ -244,6 +266,8 @@ static void trg_peers_model_init(TrgPeersModel * self) TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(self); gchar *geoip_db_path = NULL; gchar *geoip_v6_db_path = NULL; + gchar *geoip_city_db_path = NULL; + gchar *geoip_city_alt_db_path = NULL; #endif GType column_types[PEERSCOL_COLUMNS]; @@ -252,6 +276,7 @@ static void trg_peers_model_init(TrgPeersModel * self) column_types[PEERSCOL_IP] = G_TYPE_STRING; #ifdef HAVE_GEOIP column_types[PEERSCOL_COUNTRY] = G_TYPE_STRING; + column_types[PEERSCOL_CITY] = G_TYPE_STRING; #endif column_types[PEERSCOL_HOST] = G_TYPE_STRING; column_types[PEERSCOL_FLAGS] = G_TYPE_STRING; @@ -268,9 +293,13 @@ static void trg_peers_model_init(TrgPeersModel * self) #ifdef WIN32 geoip_db_path = trg_win32_support_path("GeoIP.dat"); geoip_v6_db_path = trg_win32_support_path("GeoIPv6.dat"); + geoip_city_db_path = trg_win32_support_path("GeoLiteCity.dat"); + geoip_city_alt_db_path = trg_win32_support_path("GeoIPCity.dat"); #else geoip_db_path = g_strdup(TRG_GEOIP_DATABASE); geoip_v6_db_path = g_strdup(TRG_GEOIPV6_DATABASE); + geoip_city_db_path = g_strdup(TRG_GEOIP_CITY_DATABASE); + geoip_city_alt_db_path = g_strdup(TRG_GEOIP_CITY_ALT_DATABASE); #endif if (g_file_test(geoip_db_path, G_FILE_TEST_EXISTS) == TRUE) @@ -281,11 +310,83 @@ static void trg_peers_model_init(TrgPeersModel * self) priv->geoipv6 = GeoIP_open(geoip_v6_db_path, GEOIP_STANDARD | GEOIP_CHECK_CACHE); + if (g_file_test(geoip_city_db_path, G_FILE_TEST_EXISTS) == TRUE) + priv->geoipcity = GeoIP_open(geoip_city_db_path, + GEOIP_STANDARD | GEOIP_CHECK_CACHE); + else if (g_file_test(geoip_city_alt_db_path, G_FILE_TEST_EXISTS) == TRUE) + priv->geoipcity = GeoIP_open(geoip_city_alt_db_path, + GEOIP_STANDARD | GEOIP_CHECK_CACHE); + + if (priv->geoipcity) + GeoIP_set_charset(priv->geoipcity, GEOIP_CHARSET_UTF8); + + g_free(geoip_city_db_path); + g_free(geoip_city_alt_db_path); g_free(geoip_db_path); g_free(geoip_v6_db_path); #endif } +#ifdef HAVE_GEOIP +static gboolean trg_peers_model_add_city_foreach(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + gchar *address = NULL; + GeoIPRecord *record = NULL; + + gtk_tree_model_get(GTK_TREE_MODEL(model), iter, PEERSCOL_IP, &address, -1); + record = GeoIP_record_by_addr(priv->geoipcity, address); + + if (record) { + gtk_list_store_set(GTK_LIST_STORE(model), iter, PEERSCOL_CITY, record->city, -1); + GeoIPRecord_delete(record); + } + + g_free(address); + + return FALSE; +} + +gboolean trg_peers_model_has_city_db(TrgPeersModel *model) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + return priv->geoipcity != NULL; +} + +gboolean trg_peers_model_has_country_db(TrgPeersModel *model) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + return priv->geoip != NULL; +} + +void trg_peers_model_add_city_column(TrgPeersModel *model) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + if (priv->geoipcity) + gtk_tree_model_foreach(GTK_TREE_MODEL(model), trg_peers_model_add_city_foreach, NULL); +} + +static gboolean trg_peers_model_add_country_foreach(GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) { + gchar *address = NULL; + + gtk_tree_model_get(GTK_TREE_MODEL(model), iter, PEERSCOL_IP, &address, -1); + gtk_list_store_set(GTK_LIST_STORE(model), iter, PEERSCOL_COUNTRY, lookup_country(TRG_PEERS_MODEL(model), address), -1); + + g_free(address); + + return FALSE; +} + +void trg_peers_model_add_country_column(TrgPeersModel *model) { + TrgPeersModelPrivate *priv = TRG_PEERS_MODEL_GET_PRIVATE(model); + if (priv->geoip) + gtk_tree_model_foreach(GTK_TREE_MODEL(model), trg_peers_model_add_country_foreach, NULL); +} +#endif + + TrgPeersModel *trg_peers_model_new() { return g_object_new(TRG_TYPE_PEERS_MODEL, NULL); |