wispr: Added WISPr XML content parser
authorTomasz Bursztyka <tomasz.bursztyka@linux.intel.com>
Mon, 29 Aug 2011 15:25:04 +0000 (18:25 +0300)
committerSamuel Ortiz <sameo@linux.intel.com>
Mon, 12 Sep 2011 17:45:30 +0000 (19:45 +0200)
src/wispr.c

index 9e3b0e3..4cda5ed 100644 (file)
 
 #define STATUS_URL  "http://www.connman.net/online/status.html"
 
+struct connman_wispr_message {
+       gboolean has_error;
+       const char *current_element;
+       int message_type;
+       int response_code;
+       char *login_url;
+       char *abort_login_url;
+       char *logoff_url;
+       char *access_procedure;
+       char *access_location;
+       char *location_name;
+};
+
 struct connman_wispr_portal_context {
        struct connman_service *service;
        enum connman_ipconfig_type type;
@@ -40,6 +53,10 @@ struct connman_wispr_portal_context {
        GWeb *web;
        unsigned int token;
        guint request_id;
+
+       /* WISPr specific */
+       GWebParser *wispr_parser;
+       struct connman_wispr_message wispr_msg;
 };
 
 struct connman_wispr_portal {
@@ -49,6 +66,35 @@ struct connman_wispr_portal {
 
 static GHashTable *wispr_portal_list = NULL;
 
+static void connman_wispr_message_init(struct connman_wispr_message *msg)
+{
+       DBG("");
+
+       msg->has_error = FALSE;
+       msg->current_element = NULL;
+
+       msg->message_type = -1;
+       msg->response_code = -1;
+
+       g_free(msg->login_url);
+       msg->login_url = NULL;
+
+       g_free(msg->abort_login_url);
+       msg->abort_login_url = NULL;
+
+       g_free(msg->logoff_url);
+       msg->logoff_url = NULL;
+
+       g_free(msg->access_procedure);
+       msg->access_procedure = NULL;
+
+       g_free(msg->access_location);
+       msg->access_location = NULL;
+
+       g_free(msg->location_name);
+       msg->location_name = NULL;
+}
+
 static void free_connman_wispr_portal_context(struct connman_wispr_portal_context *wp_context)
 {
        DBG("");
@@ -64,6 +110,9 @@ static void free_connman_wispr_portal_context(struct connman_wispr_portal_contex
 
        g_web_unref(wp_context->web);
 
+       g_web_parser_unref(wp_context->wispr_parser);
+       connman_wispr_message_init(&wp_context->wispr_msg);
+
        g_free(wp_context);
 }
 
@@ -82,6 +131,151 @@ static void free_connman_wispr_portal(gpointer data)
        g_free(wispr_portal);
 }
 
+static struct {
+       const char *str;
+       enum {
+               WISPR_ELEMENT_NONE              = 0,
+               WISPR_ELEMENT_ACCESS_PROCEDURE  = 1,
+               WISPR_ELEMENT_ACCESS_LOCATION   = 2,
+               WISPR_ELEMENT_LOCATION_NAME     = 3,
+               WISPR_ELEMENT_LOGIN_URL         = 4,
+               WISPR_ELEMENT_ABORT_LOGIN_URL   = 5,
+               WISPR_ELEMENT_MESSAGE_TYPE      = 6,
+               WISPR_ELEMENT_RESPONSE_CODE     = 7,
+               WISPR_ELEMENT_NEXT_URL          = 8,
+               WISPR_ELEMENT_DELAY             = 9,
+               WISPR_ELEMENT_REPLY_MESSAGE     = 10,
+               WISPR_ELEMENT_LOGIN_RESULTS_URL = 11,
+               WISPR_ELEMENT_LOGOFF_URL        = 12,
+       } element;
+} wispr_element_map[] = {
+       { "AccessProcedure",    WISPR_ELEMENT_ACCESS_PROCEDURE  },
+       { "AccessLocation",     WISPR_ELEMENT_ACCESS_LOCATION   },
+       { "LocationName",       WISPR_ELEMENT_LOCATION_NAME     },
+       { "LoginURL",           WISPR_ELEMENT_LOGIN_URL         },
+       { "AbortLoginURL",      WISPR_ELEMENT_ABORT_LOGIN_URL   },
+       { "MessageType",        WISPR_ELEMENT_MESSAGE_TYPE      },
+       { "ResponseCode",       WISPR_ELEMENT_RESPONSE_CODE     },
+       { "NextURL",            WISPR_ELEMENT_NEXT_URL          },
+       { "Delay",              WISPR_ELEMENT_DELAY             },
+       { "ReplyMessage",       WISPR_ELEMENT_REPLY_MESSAGE     },
+       { "LoginResultsURL",    WISPR_ELEMENT_LOGIN_RESULTS_URL },
+       { "LogoffURL",          WISPR_ELEMENT_LOGOFF_URL        },
+       { NULL,                 WISPR_ELEMENT_NONE              },
+};
+
+static void xml_wispr_start_element_handler(GMarkupParseContext *context,
+                                       const gchar *element_name,
+                                       const gchar **attribute_names,
+                                       const gchar **attribute_values,
+                                       gpointer user_data, GError **error)
+{
+       struct connman_wispr_message *msg = user_data;
+
+       msg->current_element = element_name;
+}
+
+static void xml_wispr_end_element_handler(GMarkupParseContext *context,
+                                       const gchar *element_name,
+                                       gpointer user_data, GError **error)
+{
+       struct connman_wispr_message *msg = user_data;
+
+       msg->current_element = NULL;
+}
+
+static void xml_wispr_text_handler(GMarkupParseContext *context,
+                                       const gchar *text, gsize text_len,
+                                       gpointer user_data, GError **error)
+{
+       struct connman_wispr_message *msg = user_data;
+       int i;
+
+       if (msg->current_element == NULL)
+               return;
+
+       for (i = 0; wispr_element_map[i].str; i++) {
+               if (g_str_equal(wispr_element_map[i].str,
+                                       msg->current_element) == FALSE)
+                       continue;
+
+               switch (wispr_element_map[i].element) {
+               case WISPR_ELEMENT_NONE:
+               case WISPR_ELEMENT_ACCESS_PROCEDURE:
+                       g_free(msg->access_procedure);
+                       msg->access_procedure = g_strdup(text);
+                       break;
+               case WISPR_ELEMENT_ACCESS_LOCATION:
+                       g_free(msg->access_location);
+                       msg->access_location = g_strdup(text);
+                       break;
+               case WISPR_ELEMENT_LOCATION_NAME:
+                       g_free(msg->location_name);
+                       msg->location_name = g_strdup(text);
+                       break;
+               case WISPR_ELEMENT_LOGIN_URL:
+                       g_free(msg->login_url);
+                       msg->login_url = g_strdup(text);
+                       break;
+               case WISPR_ELEMENT_ABORT_LOGIN_URL:
+                       g_free(msg->abort_login_url);
+                       msg->abort_login_url = g_strdup(text);
+                       break;
+               case WISPR_ELEMENT_MESSAGE_TYPE:
+                       msg->message_type = atoi(text);
+                       break;
+               case WISPR_ELEMENT_RESPONSE_CODE:
+                       msg->response_code = atoi(text);
+                       break;
+               case WISPR_ELEMENT_NEXT_URL:
+               case WISPR_ELEMENT_DELAY:
+               case WISPR_ELEMENT_REPLY_MESSAGE:
+               case WISPR_ELEMENT_LOGIN_RESULTS_URL:
+                       break;
+               case WISPR_ELEMENT_LOGOFF_URL:
+                       g_free(msg->logoff_url);
+                       msg->logoff_url = g_strdup(text);
+                       break;
+               }
+       }
+}
+
+static void xml_wispr_error_handler(GMarkupParseContext *context,
+                                       GError *error, gpointer user_data)
+{
+       struct connman_wispr_message *msg = user_data;
+
+       msg->has_error = TRUE;
+}
+
+static const GMarkupParser xml_wispr_parser_handlers = {
+       xml_wispr_start_element_handler,
+       xml_wispr_end_element_handler,
+       xml_wispr_text_handler,
+       NULL,
+       xml_wispr_error_handler,
+};
+
+static void xml_wispr_parser_callback(const char *str, gpointer user_data)
+{
+       struct connman_wispr_portal_context *wp_context = user_data;
+       GMarkupParseContext *parser_context = NULL;
+       gboolean result;
+
+       DBG("");
+
+       parser_context = g_markup_parse_context_new(&xml_wispr_parser_handlers,
+                                       G_MARKUP_TREAT_CDATA_AS_TEXT,
+                                       &(wp_context->wispr_msg), NULL);
+
+       result = g_markup_parse_context_parse(parser_context,
+                                       str, strlen(str), NULL);
+       if (result == TRUE)
+               result = g_markup_parse_context_end_parse(parser_context, NULL);
+
+       g_markup_parse_context_free(parser_context);
+}
+
 static void web_debug(const char *str, void *data)
 {
        connman_info("%s: %s\n", (const char *) data, str);
@@ -121,20 +315,35 @@ static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data)
 {
        struct connman_wispr_portal_context *wp_context = user_data;
        const char *redirect = NULL;
+       const guint8 *chunk = NULL;
        const char *str = NULL;
        guint16 status;
+       gsize length;
 
        DBG("");
 
        if (wp_context->request_id == 0)
                return FALSE;
 
+       g_web_result_get_chunk(result, &chunk, &length);
+
+       if (length > 0) {
+               g_web_parser_feed_data(wp_context->wispr_parser,
+                                                       chunk, length);
+               return TRUE;
+       }
+
+       g_web_parser_end_data(wp_context->wispr_parser);
+
        status = g_web_result_get_status(result);
 
        DBG("status: %03u", status);
 
        switch (status) {
        case 200:
+               if (wp_context->wispr_msg.message_type >= 0)
+                       break;
+
                if (g_web_result_get_header(result, "X-ConnMan-Status",
                                                                &str) == TRUE)
                        portal_manage_status(result, wp_context);
@@ -147,6 +356,9 @@ static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data)
 
                DBG("Redirect URL: %s", redirect);
 
+               wp_context->request_id = g_web_request_get(wp_context->web,
+                               redirect, wispr_portal_web_result, wp_context);
+
                goto done;
        case 404:
                wispr_portal_error(wp_context);
@@ -158,6 +370,7 @@ static gboolean wispr_portal_web_result(GWebResult *result, gpointer user_data)
 
        wp_context->request_id = 0;
 done:
+       wp_context->wispr_msg.message_type = -1;
        return FALSE;
 }
 
@@ -193,6 +406,13 @@ static void proxy_callback(const char *proxy, void *user_data)
        g_web_set_user_agent(wp_context->web, "ConnMan/%s", VERSION);
        g_web_set_close_connection(wp_context->web, TRUE);
 
+       connman_wispr_message_init(&wp_context->wispr_msg);
+
+       wp_context->wispr_parser = g_web_parser_new(
+                                       "<WISPAccessGatewayParam",
+                                       "WISPAccessGatewayParam>",
+                                       xml_wispr_parser_callback, wp_context);
+
        wispr_portal_request_portal(wp_context);
 }