X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=tools%2Fwispr.c;h=b14050687a755153858038cefd89878bb20db162;hb=b9d16f7fe9c5f42cd14b5839a81deae3ccd94c14;hp=760ba771675318c52183f05a91a50621418c14b6;hpb=ab459eafd190cecf68153dc19635cea5513d0ede;p=platform%2Fupstream%2Fconnman.git diff --git a/tools/wispr.c b/tools/wispr.c index 760ba77..b140506 100644 --- a/tools/wispr.c +++ b/tools/wispr.c @@ -23,10 +23,15 @@ #include #endif +#define _GNU_SOURCE #include +#include +#include #include #include #include +#include +#include #include @@ -100,6 +105,7 @@ struct wispr_msg { int message_type; int response_code; char *login_url; + char *abort_login_url; char *logoff_url; char *access_procedure; char *access_location; @@ -117,6 +123,9 @@ static inline void wispr_msg_init(struct wispr_msg *msg) 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; @@ -135,12 +144,14 @@ struct wispr_session { GWebParser *parser; guint request; struct wispr_msg msg; - const char *username; - const char *password; - const char *originurl; + char *username; + char *password; + char *originurl; char *formdata; }; +static gboolean execute_login(gpointer user_data); + static struct { const char *str; enum { @@ -214,9 +225,11 @@ static void text_handler(GMarkupParseContext *context, 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); @@ -226,6 +239,8 @@ static void text_handler(GMarkupParseContext *context, 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); @@ -280,22 +295,205 @@ static void parser_callback(const char *str, gpointer user_data) g_markup_parse_context_free(context); } +typedef void (*user_input_cb)(const char *value, gpointer user_data); + +struct user_input_data { + GString *str; + user_input_cb cb; + gpointer user_data; + gboolean hidden; + int fd; + struct termios saved_termios; +}; + +static void user_callback(struct user_input_data *data) +{ + char *value; + + if (data->hidden == TRUE) { + ssize_t len; + + len = write(data->fd, "\n", 1); + if (len < 0) + return; + } + + tcsetattr(data->fd, TCSADRAIN, &data->saved_termios); + + close(data->fd); + + value = g_string_free(data->str, FALSE); + + if (data->cb) + data->cb(value, data->user_data); + + g_free(value); + + g_free(data); +} + +static gboolean keyboard_input(GIOChannel *channel, GIOCondition condition, + gpointer user_data) +{ + struct user_input_data *data = user_data; + char buf[1]; + int len; + + len = read(data->fd, buf, 1); + + if (len != 1) + return TRUE; + + if (buf[0] == '\n') { + user_callback(data); + return FALSE; + } + + g_string_append_c(data->str, buf[0]); + + if (data->hidden == TRUE) + len = write(data->fd, "*", 1); + + return TRUE; +} + +static gboolean user_input(const char *label, gboolean hidden, + user_input_cb func, gpointer user_data) +{ + struct user_input_data *data; + struct termios new_termios; + GIOChannel *channel; + guint watch; + ssize_t len; + + data = g_try_new0(struct user_input_data, 1); + if (data == NULL) + return FALSE; + + data->str = g_string_sized_new(32); + data->cb = func; + data->user_data = user_data; + data->hidden = hidden; + + data->fd = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC); + if (data->fd < 0) + goto error; + + if (tcgetattr(data->fd, &data->saved_termios) < 0) { + close(data->fd); + goto error; + } + + new_termios = data->saved_termios; + if (data->hidden == TRUE) + new_termios.c_lflag &= ~(ICANON|ECHO); + else + new_termios.c_lflag &= ~ICANON; + new_termios.c_cc[VMIN] = 1; + new_termios.c_cc[VTIME] = 0; + + tcsetattr(data->fd, TCSADRAIN, &new_termios); + + channel = g_io_channel_unix_new(data->fd); + g_io_channel_set_encoding(channel, NULL, NULL); + g_io_channel_set_buffered(channel, FALSE); + watch = g_io_add_watch(channel, G_IO_IN, keyboard_input, data); + g_io_channel_unref(channel); + + if (watch == 0) + goto error; + + len = write(data->fd, label, strlen(label)); + if (len < 0) + goto error; + + len = write(data->fd, ": ", 2); + if (len < 0) + goto error; + + return TRUE; + +error: + g_string_free(data->str, TRUE); + g_free(data); + + return FALSE; +} + +static void password_callback(const char *value, gpointer user_data) +{ + struct wispr_session *wispr = user_data; + + g_free(wispr->password); + wispr->password = g_strdup(value); + + printf("\n"); + + execute_login(wispr); +} + +static void username_callback(const char *value, gpointer user_data) +{ + struct wispr_session *wispr = user_data; + + g_free(wispr->username); + wispr->username = g_strdup(value); + + if (wispr->password == NULL) { + user_input("Password", TRUE, password_callback, wispr); + return; + } + + printf("\n"); + + execute_login(wispr); +} + static gboolean wispr_input(const guint8 **data, gsize *length, gpointer user_data) { struct wispr_session *wispr = user_data; + GString *buf; + gsize count; + + buf = g_string_sized_new(100); + + g_string_append(buf, "button=Login&UserName="); + g_string_append_uri_escaped(buf, wispr->username, NULL, FALSE); + g_string_append(buf, "&Password="); + g_string_append_uri_escaped(buf, wispr->password, NULL, FALSE); + g_string_append(buf, "&FNAME=0&OriginatingServer="); + g_string_append_uri_escaped(buf, wispr->originurl, NULL, FALSE); + + count = buf->len; g_free(wispr->formdata); - wispr->formdata = g_strdup_printf("button=Login&UserName=%s&" - "Password=%s&FNAME=0&OriginatingServer=%s", - wispr->username, wispr->password, wispr->originurl); + wispr->formdata = g_string_free(buf, FALSE); *data = (guint8 *) wispr->formdata; - *length = strlen(wispr->formdata); + *length = count; return FALSE; } +static gboolean wispr_route(const char *addr, int ai_family, int if_index, + gpointer user_data) +{ + char *family = "unknown"; + + if (ai_family == AF_INET) + family = "IPv4"; + else if (ai_family == AF_INET6) + family = "IPv6"; + + printf("Route request: %s %s index %d\n", family, addr, if_index); + + if (ai_family != AF_INET && ai_family != AF_INET6) + return FALSE; + + return TRUE; +} + static gboolean wispr_result(GWebResult *result, gpointer user_data) { struct wispr_session *wispr = user_data; @@ -322,8 +520,24 @@ static gboolean wispr_result(GWebResult *result, gpointer user_data) g_print("elapse: %f seconds\n", elapsed); - if (wispr->msg.message_type < 0) - goto done; + if (wispr->msg.message_type < 0) { + const char *redirect; + + if (status != 302) + goto done; + + if (g_web_result_get_header(result, "Location", + &redirect) == FALSE) + goto done; + + printf("Redirect URL: %s\n", redirect); + printf("\n"); + + wispr->request = g_web_request_get(wispr->web, redirect, + wispr_result, wispr_route, wispr); + + return FALSE; + } printf("Message type: %s (%d)\n", message_type_to_string(wispr->msg.message_type), @@ -339,31 +553,71 @@ static gboolean wispr_result(GWebResult *result, gpointer user_data) printf("Location name: %s\n", wispr->msg.location_name); if (wispr->msg.login_url != NULL) printf("Login URL: %s\n", wispr->msg.login_url); + if (wispr->msg.abort_login_url != NULL) + printf("Abort login URL: %s\n", wispr->msg.abort_login_url); if (wispr->msg.logoff_url != NULL) printf("Logoff URL: %s\n", wispr->msg.logoff_url); printf("\n"); - if (status == 302 && wispr->msg.message_type == 100) { - wispr->request = g_web_request_post(wispr->web, - wispr->msg.login_url, - "application/x-www-form-urlencoded", - wispr_input, wispr_result, wispr); + if (status != 200 && status != 302 && status != 404) + goto done; - wispr_msg_init(&wispr->msg); + if (wispr->msg.message_type == 100) { + if (wispr->username == NULL) { + user_input("Username", FALSE, username_callback, wispr); + return FALSE; + } + + if (wispr->password == NULL) { + user_input("Password", TRUE, password_callback, wispr); + return FALSE; + } + g_idle_add(execute_login, wispr); return FALSE; - } else if (status == 200 && wispr->msg.message_type == 120) { + } else if (wispr->msg.message_type == 120 || + wispr->msg.message_type == 140) { int code = wispr->msg.response_code; printf("Login process: %s\n", code == 50 ? "SUCCESS" : "FAILURE"); } + if (status == 302) { + const char *redirect; + + if (g_web_result_get_header(result, "Location", + &redirect) == FALSE) + goto done; + + printf("\n"); + printf("Redirect URL: %s\n", redirect); + printf("\n"); + + wispr->request = g_web_request_get(wispr->web, redirect, + wispr_result, NULL, wispr); + + return FALSE; + } + done: g_main_loop_quit(main_loop); return FALSE; } +static gboolean execute_login(gpointer user_data) +{ + struct wispr_session *wispr = user_data; + + wispr->request = g_web_request_post(wispr->web, wispr->msg.login_url, + "application/x-www-form-urlencoded", + wispr_input, wispr_result, wispr); + + wispr_msg_init(&wispr->msg); + + return FALSE; +} + static gboolean option_debug = FALSE; static gchar *option_nameserver = NULL; static gchar *option_username = NULL; @@ -443,7 +697,7 @@ int main(int argc, char *argv[]) parser_callback, &wispr); wispr.request = g_web_request_get(wispr.web, option_url, - wispr_result, &wispr); + wispr_result, wispr_route, &wispr); if (wispr.request == 0) { fprintf(stderr, "Failed to start request\n"); @@ -467,9 +721,9 @@ int main(int argc, char *argv[]) g_main_loop_unref(main_loop); - g_free(option_username); - g_free(option_password); - g_free(option_url); + g_free(wispr.username); + g_free(wispr.password); + g_free(wispr.originurl); return 0; }