760ba771675318c52183f05a91a50621418c14b6
[platform/upstream/connman.git] / tools / wispr.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <signal.h>
30
31 #include <gweb/gweb.h>
32
33 #define DEFAULT_URL  "http://www.connman.net/online/status.html"
34
35 static GTimer *timer;
36
37 static GMainLoop *main_loop;
38
39 static void web_debug(const char *str, void *data)
40 {
41         g_print("%s: %s\n", (const char *) data, str);
42 }
43
44 static void sig_term(int sig)
45 {
46         g_main_loop_quit(main_loop);
47 }
48
49 static const char *message_type_to_string(int message_type)
50 {
51         switch (message_type) {
52         case 100:
53                 return "Initial redirect message";
54         case 110:
55                 return "Proxy notification";
56         case 120:
57                 return "Authentication notification";
58         case 130:
59                 return "Logoff notification";
60         case 140:
61                 return "Response to Authentication Poll";
62         case 150:
63                 return "Response to Abort Login";
64         }
65
66         return NULL;
67 }
68
69 static const char *response_code_to_string(int response_code)
70 {
71         switch (response_code) {
72         case 0:
73                 return "No error";
74         case 50:
75                 return "Login succeeded";
76         case 100:
77                 return "Login failed";
78         case 102:
79                 return "RADIUS server error/timeout";
80         case 105:
81                 return "RADIUS server not enabled";
82         case 150:
83                 return "Logoff succeeded";
84         case 151:
85                 return "Login aborted";
86         case 200:
87                 return "Proxy detection/repeat operation";
88         case 201:
89                 return "Authentication pending";
90         case 255:
91                 return "Access gateway internal error";
92         }
93
94         return NULL;
95 }
96
97 struct wispr_msg {
98         gboolean has_error;
99         const char *current_element;
100         int message_type;
101         int response_code;
102         char *login_url;
103         char *logoff_url;
104         char *access_procedure;
105         char *access_location;
106         char *location_name;
107 };
108
109 static inline void wispr_msg_init(struct wispr_msg *msg)
110 {
111         msg->has_error = FALSE;
112         msg->current_element = NULL;
113
114         msg->message_type = -1;
115         msg->response_code = -1;
116
117         g_free(msg->login_url);
118         msg->login_url = NULL;
119
120         g_free(msg->logoff_url);
121         msg->logoff_url = NULL;
122
123         g_free(msg->access_procedure);
124         msg->access_procedure = NULL;
125
126         g_free(msg->access_location);
127         msg->access_location = NULL;
128
129         g_free(msg->location_name);
130         msg->location_name = NULL;
131 }
132
133 struct wispr_session {
134         GWeb *web;
135         GWebParser *parser;
136         guint request;
137         struct wispr_msg msg;
138         const char *username;
139         const char *password;
140         const char *originurl;
141         char *formdata;
142 };
143
144 static struct {
145         const char *str;
146         enum {
147                 WISPR_ELEMENT_NONE,
148                 WISPR_ELEMENT_ACCESS_PROCEDURE,
149                 WISPR_ELEMENT_ACCESS_LOCATION,
150                 WISPR_ELEMENT_LOCATION_NAME,
151                 WISPR_ELEMENT_LOGIN_URL,
152                 WISPR_ELEMENT_ABORT_LOGIN_URL,
153                 WISPR_ELEMENT_MESSAGE_TYPE,
154                 WISPR_ELEMENT_RESPONSE_CODE,
155                 WISPR_ELEMENT_NEXT_URL,
156                 WISPR_ELEMENT_DELAY,
157                 WISPR_ELEMENT_REPLY_MESSAGE,
158                 WISPR_ELEMENT_LOGIN_RESULTS_URL,
159                 WISPR_ELEMENT_LOGOFF_URL,
160         } element;
161 } wispr_element_map[] = {
162         { "AccessProcedure",    WISPR_ELEMENT_ACCESS_PROCEDURE  },
163         { "AccessLocation",     WISPR_ELEMENT_ACCESS_LOCATION   },
164         { "LocationName",       WISPR_ELEMENT_LOCATION_NAME     },
165         { "LoginURL",           WISPR_ELEMENT_LOGIN_URL         },
166         { "AbortLoginURL",      WISPR_ELEMENT_ABORT_LOGIN_URL   },
167         { "MessageType",        WISPR_ELEMENT_MESSAGE_TYPE      },
168         { "ResponseCode",       WISPR_ELEMENT_RESPONSE_CODE     },
169         { "NextURL",            WISPR_ELEMENT_NEXT_URL          },
170         { "Delay",              WISPR_ELEMENT_DELAY             },
171         { "ReplyMessage",       WISPR_ELEMENT_REPLY_MESSAGE     },
172         { "LoginResultsURL",    WISPR_ELEMENT_LOGIN_RESULTS_URL },
173         { "LogoffURL",          WISPR_ELEMENT_LOGOFF_URL        },
174         { NULL,                 WISPR_ELEMENT_NONE              },
175 };
176
177 static void start_element_handler(GMarkupParseContext *context,
178                                         const gchar *element_name,
179                                         const gchar **attribute_names,
180                                         const gchar **attribute_values,
181                                         gpointer user_data, GError **error)
182 {
183         struct wispr_msg *msg = user_data;
184
185         msg->current_element = element_name;
186 }
187
188 static void end_element_handler(GMarkupParseContext *context,
189                                         const gchar *element_name,
190                                         gpointer user_data, GError **error)
191 {
192         struct wispr_msg *msg = user_data;
193
194         msg->current_element = NULL;
195 }
196
197 static void text_handler(GMarkupParseContext *context,
198                                         const gchar *text, gsize text_len,
199                                         gpointer user_data, GError **error)
200 {
201         struct wispr_msg *msg = user_data;
202         int i;
203
204         if (msg->current_element == NULL)
205                 return;
206
207         for (i = 0; wispr_element_map[i].str; i++) {
208                 if (g_str_equal(wispr_element_map[i].str,
209                                         msg->current_element) == FALSE)
210                         continue;
211
212                 switch (wispr_element_map[i].element) {
213                 case WISPR_ELEMENT_NONE:
214                 case WISPR_ELEMENT_ACCESS_PROCEDURE:
215                         g_free(msg->access_procedure);
216                         msg->access_procedure = g_strdup(text);
217                 case WISPR_ELEMENT_ACCESS_LOCATION:
218                         g_free(msg->access_location);
219                         msg->access_location = g_strdup(text);
220                 case WISPR_ELEMENT_LOCATION_NAME:
221                         g_free(msg->location_name);
222                         msg->location_name = g_strdup(text);
223                         break;
224                 case WISPR_ELEMENT_LOGIN_URL:
225                         g_free(msg->login_url);
226                         msg->login_url = g_strdup(text);
227                         break;
228                 case WISPR_ELEMENT_ABORT_LOGIN_URL:
229                         break;
230                 case WISPR_ELEMENT_MESSAGE_TYPE:
231                         msg->message_type = atoi(text);
232                         break;
233                 case WISPR_ELEMENT_RESPONSE_CODE:
234                         msg->response_code = atoi(text);
235                         break;
236                 case WISPR_ELEMENT_NEXT_URL:
237                 case WISPR_ELEMENT_DELAY:
238                 case WISPR_ELEMENT_REPLY_MESSAGE:
239                 case WISPR_ELEMENT_LOGIN_RESULTS_URL:
240                         break;
241                 case WISPR_ELEMENT_LOGOFF_URL:
242                         g_free(msg->logoff_url);
243                         msg->logoff_url = g_strdup(text);
244                         break;
245                 }
246         }
247 }
248
249 static void error_handler(GMarkupParseContext *context,
250                                         GError *error, gpointer user_data)
251 {
252         struct wispr_msg *msg = user_data;
253
254         msg->has_error = TRUE;
255 }
256
257 static const GMarkupParser wispr_parser = {
258         start_element_handler,
259         end_element_handler,
260         text_handler,
261         NULL,
262         error_handler,
263 };
264
265 static void parser_callback(const char *str, gpointer user_data)
266 {
267         struct wispr_session *wispr = user_data;
268         GMarkupParseContext *context;
269         gboolean result;
270
271         //printf("%s\n", str);
272
273         context = g_markup_parse_context_new(&wispr_parser,
274                         G_MARKUP_TREAT_CDATA_AS_TEXT, &wispr->msg, NULL);
275
276         result = g_markup_parse_context_parse(context, str, strlen(str), NULL);
277         if (result == TRUE)
278                 result = g_markup_parse_context_end_parse(context, NULL);
279
280         g_markup_parse_context_free(context);
281 }
282
283 static gboolean wispr_input(const guint8 **data, gsize *length,
284                                                 gpointer user_data)
285 {
286         struct wispr_session *wispr = user_data;
287
288         g_free(wispr->formdata);
289         wispr->formdata = g_strdup_printf("button=Login&UserName=%s&"
290                         "Password=%s&FNAME=0&OriginatingServer=%s",
291                         wispr->username, wispr->password, wispr->originurl);
292
293         *data = (guint8 *) wispr->formdata;
294         *length = strlen(wispr->formdata);
295
296         return FALSE;
297 }
298
299 static gboolean wispr_result(GWebResult *result, gpointer user_data)
300 {
301         struct wispr_session *wispr = user_data;
302         const guint8 *chunk;
303         gsize length;
304         guint16 status;
305         gdouble elapsed;
306
307         g_web_result_get_chunk(result, &chunk, &length);
308
309         if (length > 0) {
310                 //printf("%s\n", (char *) chunk);
311                 g_web_parser_feed_data(wispr->parser, chunk, length);
312                 return TRUE;
313         }
314
315         g_web_parser_end_data(wispr->parser);
316
317         status = g_web_result_get_status(result);
318
319         g_print("status: %03u\n", status);
320
321         elapsed = g_timer_elapsed(timer, NULL);
322
323         g_print("elapse: %f seconds\n", elapsed);
324
325         if (wispr->msg.message_type < 0)
326                 goto done;
327
328         printf("Message type: %s (%d)\n",
329                         message_type_to_string(wispr->msg.message_type),
330                                                 wispr->msg.message_type);
331         printf("Response code: %s (%d)\n",
332                         response_code_to_string(wispr->msg.response_code),
333                                                 wispr->msg.response_code);
334         if (wispr->msg.access_procedure != NULL)
335                 printf("Access procedure: %s\n", wispr->msg.access_procedure);
336         if (wispr->msg.access_location != NULL)
337                 printf("Access location: %s\n", wispr->msg.access_location);
338         if (wispr->msg.location_name != NULL)
339                 printf("Location name: %s\n", wispr->msg.location_name);
340         if (wispr->msg.login_url != NULL)
341                 printf("Login URL: %s\n", wispr->msg.login_url);
342         if (wispr->msg.logoff_url != NULL)
343                 printf("Logoff URL: %s\n", wispr->msg.logoff_url);
344         printf("\n");
345
346         if (status == 302 && wispr->msg.message_type == 100) {
347                 wispr->request = g_web_request_post(wispr->web,
348                                         wispr->msg.login_url,
349                                         "application/x-www-form-urlencoded",
350                                         wispr_input, wispr_result, wispr);
351
352                 wispr_msg_init(&wispr->msg);
353
354                 return FALSE;
355         } else if (status == 200 && wispr->msg.message_type == 120) {
356                 int code = wispr->msg.response_code;
357                 printf("Login process: %s\n",
358                                         code == 50 ? "SUCCESS" : "FAILURE");
359         }
360
361 done:
362         g_main_loop_quit(main_loop);
363
364         return FALSE;
365 }
366
367 static gboolean option_debug = FALSE;
368 static gchar *option_nameserver = NULL;
369 static gchar *option_username = NULL;
370 static gchar *option_password = NULL;
371 static gchar *option_url = NULL;
372
373 static GOptionEntry options[] = {
374         { "debug", 'd', 0, G_OPTION_ARG_NONE, &option_debug,
375                                         "Enable debug output" },
376         { "nameserver", 'n', 0, G_OPTION_ARG_STRING, &option_nameserver,
377                                         "Specify nameserver", "ADDRESS" },
378         { "username", 'u', 0, G_OPTION_ARG_STRING, &option_username,
379                                         "Specify username", "USERNAME" },
380         { "password", 'p', 0, G_OPTION_ARG_STRING, &option_password,
381                                         "Specify password", "PASSWORD" },
382         { "url", 'U', 0, G_OPTION_ARG_STRING, &option_url,
383                                         "Specify arbitrary request", "URL" },
384         { NULL },
385 };
386
387 int main(int argc, char *argv[])
388 {
389         GOptionContext *context;
390         GError *error = NULL;
391         struct sigaction sa;
392         struct wispr_session wispr;
393         int index = 0;
394
395         context = g_option_context_new(NULL);
396         g_option_context_add_main_entries(context, options, NULL);
397
398         if (g_option_context_parse(context, &argc, &argv, &error) == FALSE) {
399                 if (error != NULL) {
400                         g_printerr("%s\n", error->message);
401                         g_error_free(error);
402                 } else
403                         g_printerr("An unknown error occurred\n");
404                 return 1;
405         }
406
407         g_option_context_free(context);
408
409         memset(&wispr, 0, sizeof(wispr));
410         wispr_msg_init(&wispr.msg);
411
412         wispr.web = g_web_new(index);
413         if (wispr.web == NULL) {
414                 fprintf(stderr, "Failed to create web service\n");
415                 return 1;
416         }
417
418         if (option_debug == TRUE)
419                 g_web_set_debug(wispr.web, web_debug, "WEB");
420
421         main_loop = g_main_loop_new(NULL, FALSE);
422
423         if (option_nameserver != NULL) {
424                 g_web_add_nameserver(wispr.web, option_nameserver);
425                 g_free(option_nameserver);
426         }
427
428         g_web_set_accept(wispr.web, NULL);
429         g_web_set_user_agent(wispr.web, "SmartClient/%s wispr", VERSION);
430         g_web_set_close_connection(wispr.web, TRUE);
431
432         if (option_url == NULL)
433                 option_url = g_strdup(DEFAULT_URL);
434
435         wispr.username = option_username;
436         wispr.password = option_password;
437         wispr.originurl = option_url;
438
439         timer = g_timer_new();
440
441         wispr.parser = g_web_parser_new("<WISPAccessGatewayParam",
442                                                 "WISPAccessGatewayParam>",
443                                                 parser_callback, &wispr);
444
445         wispr.request = g_web_request_get(wispr.web, option_url,
446                                                         wispr_result, &wispr);
447
448         if (wispr.request == 0) {
449                 fprintf(stderr, "Failed to start request\n");
450                 return 1;
451         }
452
453         memset(&sa, 0, sizeof(sa));
454         sa.sa_handler = sig_term;
455         sigaction(SIGINT, &sa, NULL);
456         sigaction(SIGTERM, &sa, NULL);
457
458         g_main_loop_run(main_loop);
459
460         g_timer_destroy(timer);
461
462         if (wispr.request > 0)
463                 g_web_cancel_request(wispr.web, wispr.request);
464
465         g_web_parser_unref(wispr.parser);
466         g_web_unref(wispr.web);
467
468         g_main_loop_unref(main_loop);
469
470         g_free(option_username);
471         g_free(option_password);
472         g_free(option_url);
473
474         return 0;
475 }