geoloc.c
changeset 29 23fa36d480fb
child 31 e404cd1c7077
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/geoloc.c	Sun May 20 22:15:51 2012 +0300
@@ -0,0 +1,323 @@
+/*
+ * geoloc.c             -- Pep geographical location events
+ *
+ * Copyright (C) 2009-2012 Myhailo Danylenko <isbear@ukrpost.net>
+ *
+ * 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 2 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ */
+
+#include <glib.h>
+#include <string.h>
+
+#include <mcabber/commands.h>
+#include <mcabber/compl.h>
+#include <mcabber/utils.h>
+#include <mcabber/screen.h>
+#include <mcabber/logprint.h>
+#include <mcabber/hbuf.h>        // HBUF_PREFIX_*
+#include <mcabber/roster.h>
+#include <mcabber/hooks.h>
+#include <mcabber/modules.h>
+
+#include "geoloc.h"
+
+#include "config.h"
+
+//
+//  module description
+//
+
+void geoloc_init   (void);
+void geoloc_uninit (void);
+
+#define DESCRIPTION ( \
+	"PEP geoloc event handling\n" \
+	"Provides command /geoloc" )
+
+static const gchar *deps[] = { "pep_geoloc", NULL };
+
+static module_info_t info_geoloc_dev = {
+	.branch      = "dev",
+	.api         = 20,
+	.version     = PROJECT_VERSION,
+	.description = DESCRIPTION,
+	.requires    = deps,
+	.init        = geoloc_init,
+	.uninit      = geoloc_uninit,
+	.next        = NULL,
+};
+
+module_info_t info_geoloc = {
+	.branch      = "0.10.1",
+	.api         = 1,
+	.version     = PROJECT_VERSION,
+	.description = DESCRIPTION,
+	.requires    = deps,
+	.init        = geoloc_init,
+	.uninit      = geoloc_uninit,
+	.next        = &info_geoloc_dev,
+};
+
+//
+//  globals
+//
+
+#ifdef MCABBER_API_HAVE_CMD_ID
+static gpointer geoloc_cmid     = NULL;
+static gboolean geoloc_set_safe = FALSE;
+#endif
+
+static guint geoloc_cid          = 0;
+static guint geoloc_hid_geolocin = 0;
+
+//
+//  code
+//
+
+static void do_geoloc (char *arg)
+{
+	geoloc_pair_t tags[] = {
+		{ "accuracy",    NULL },
+		{ "alt",         NULL },
+		{ "area",        NULL },
+		{ "bearing",     NULL },
+		{ "building",    NULL },
+		{ "country",     NULL },
+		{ "countrycode", NULL },
+		{ "datum",       NULL },
+		{ "description", NULL },
+		{ "error",       NULL },
+		{ "floor",       NULL },
+		{ "lat",         NULL },
+		{ "locality",    NULL },
+		{ "lon",         NULL },
+		{ "postalcode",  NULL },
+		{ "region",      NULL },
+		{ "room",        NULL },
+		{ "speed",       NULL },
+		{ "street",      NULL },
+		{ "text",        NULL },
+		{ "timestamp",   NULL },
+		{ "uri",         NULL },
+		{ NULL,          NULL },
+	};
+
+	if (!*arg) { // request
+
+		GError *error = NULL;
+
+		geoloc_request ( CURRENT_JID, &error );
+		if ( error ) {
+			scr_log_print ( LPRINT_NORMAL, "Error sending request: %s.", error -> message );
+			g_error_free ( error );
+		} else
+			scr_log_print ( LPRINT_NORMAL, "Request sent." );
+
+		return;
+
+	} else if (arg[0] != '-' || arg[1] != '\0') { // publish
+
+		char          *p;
+		char          *argstart  = NULL;
+		char          *argstop   = NULL;
+		char          *tagstart  = NULL;
+		char          *tagstop   = NULL;
+		char          *wordstart = arg;
+		gboolean       proceed   = TRUE;
+
+// pt = p, ws = wordstart, ts = tagstart, tt = tagstop, as = argstart, at = arstop
+// tag=value value tag=value
+// w  p
+// s  t
+// t  ta
+// s  t*
+// tag=value value tag=value
+// t  ta    p
+// s  t*    t
+// t  ta    aw
+// s  ts    ts
+// tag=value value tag=value
+// t  ta    aw    p
+// s  ts    ts    t
+// t  ta          aw
+// s  ts          ts
+// tag=value value tag=value
+// t  ta          aw  p
+// s  ts          ts  t
+//                 t  ta
+//                 s  t*
+// tag=value value tag=value
+//                 t  ta    p
+//                 s  t*    t
+//                 t  ta    a
+//                 s  ts    t
+
+		for (p = arg; proceed; ++p) {
+			switch (*p) {
+			case '=':
+				if (tagstart && tagstop - tagstart) {
+					// process previous args
+					geoloc_pair_t *tag;
+
+					for (tag = tags; tag->name; ++tag) {
+						if (!strncmp (tag->name, tagstart, tagstop - tagstart)) {
+							g_free ( (gchar *) tag -> value );
+							if (argstop - argstart) {
+								*argstop = '\0';
+								tag->value = to_utf8 (argstart);
+							}
+							break;
+						}
+					}
+				}
+
+				tagstart = wordstart;
+				tagstop = p;
+				argstop = p+1;
+				argstart = p+1;
+				break;
+
+			case '\0':
+				argstop = p;
+
+				if (tagstop - tagstart) {
+					// process previous args
+					geoloc_pair_t *tag;
+
+					for (tag = tags; tag->name; ++tag) {
+						if (!strncmp (tag->name, tagstart, tagstop - tagstart)) {
+							g_free ( (gchar *) tag -> value );
+							if (argstop - argstart)
+								tag->value = to_utf8 (argstart);
+							break;
+						}
+					}
+				}
+
+				proceed = FALSE;
+				break;
+
+			case ' ':
+				argstop = p;
+				wordstart = p+1;
+				break;
+
+			default:
+				break;
+			}
+		}
+	}
+
+	hk_run_handlers ( HOOK_GEOLOC_OUT, (hk_arg_t *) tags );
+
+	{
+		geoloc_pair_t *tag;
+
+		for ( tag = tags; tag -> name; ++ tag )
+			g_free ( (gchar *) tag -> value );
+	}
+}
+
+static guint geoloc_hgih ( const gchar *hid, hk_arg_t *args, gpointer userdata )
+{
+	GString     *mesg = g_string_new (NULL);
+	const gchar *from = NULL;
+
+	{
+		hk_arg_t *arg;
+		for ( arg = args; arg -> name; ++ arg )
+			if ( arg -> value ) {
+				if ( ! strcmp ( arg -> name, "from" ) )
+					from = arg -> value;
+				else
+					g_string_append_printf ( mesg, "\n - %s: %s", arg -> name, arg -> value);
+			}
+	}
+
+	if (mesg->len)
+		g_string_prepend (mesg, "Now located at:");
+	else
+		g_string_overwrite (mesg, 0, "No location information.");
+
+	{ // print to buddy's buffer
+		gchar *jid = jidtodisp (from);
+
+		scr_write_incoming_message (jid, mesg->str, 0, HBB_PREFIX_INFO|HBB_PREFIX_NOFLAG, 0); // NO conversion from utf-8
+
+		g_free (jid);
+	}
+
+	g_string_free (mesg, TRUE);
+
+	return HOOK_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
+}
+
+void geoloc_init ( void )
+{
+	geoloc_cid = compl_new_category ();
+	if (geoloc_cid) {
+		compl_add_category_word (geoloc_cid, "accuracy=");
+		compl_add_category_word (geoloc_cid, "alt=");
+		compl_add_category_word (geoloc_cid, "area=");
+		compl_add_category_word (geoloc_cid, "bearing=");
+		compl_add_category_word (geoloc_cid, "building=");
+		compl_add_category_word (geoloc_cid, "country=");
+		compl_add_category_word (geoloc_cid, "countrycode=");
+		compl_add_category_word (geoloc_cid, "datum=");
+		compl_add_category_word (geoloc_cid, "description=");
+		compl_add_category_word (geoloc_cid, "error=");
+		compl_add_category_word (geoloc_cid, "floor=");
+		compl_add_category_word (geoloc_cid, "lat=");
+		compl_add_category_word (geoloc_cid, "locality=");
+		compl_add_category_word (geoloc_cid, "lon=");
+		compl_add_category_word (geoloc_cid, "postalcode=");
+		compl_add_category_word (geoloc_cid, "region=");
+		compl_add_category_word (geoloc_cid, "room=");
+		compl_add_category_word (geoloc_cid, "speed=");
+		compl_add_category_word (geoloc_cid, "street=");
+		compl_add_category_word (geoloc_cid, "text=");
+		compl_add_category_word (geoloc_cid, "timestamp=");
+		compl_add_category_word (geoloc_cid, "uri=");
+	}
+
+#ifndef MCABBER_API_HAVE_CMD_ID
+	cmd_add ("geoloc", "", geoloc_cid, geoloc_cid, do_geoloc, NULL);
+#else
+	geoloc_cmid     = cmd_add ("geoloc", "", geoloc_cid, geoloc_cid, do_geoloc, NULL);
+	geoloc_set_safe = cmd_set_safe ("geoloc", TRUE);
+#endif
+
+	geoloc_hid_geolocin = hk_add_handler (geoloc_hgih, HOOK_GEOLOC_IN, G_PRIORITY_DEFAULT, NULL);
+}
+
+void geoloc_uninit ( void )
+{
+	hk_del_handler (HOOK_GEOLOC_IN, geoloc_hid_geolocin);
+
+#ifndef MCABBER_API_HAVE_CMD_ID
+	cmd_del ("geoloc");
+#else
+	if (geoloc_cmid)
+		cmd_del (geoloc_cmid);
+	if (geoloc_set_safe)
+		cmd_set_safe ("geoloc", FALSE);
+#endif
+
+	if (geoloc_cid)
+		compl_del_category (geoloc_cid);
+}
+
+/* vim: se ts=4 sw=4: */