diff options
author | Mohamed Abbas <mabbas@linux.intel.com> | 2010-12-27 14:17:40 -0800 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2010-12-28 09:21:32 -0800 |
commit | 11e5f0cbf33f9ef3d5af7a7989cae51b0e963884 (patch) | |
tree | 5b8f95c63fdac94da3fb5bfc0091c4872096654f /gweb | |
parent | 315a38ee636840ea9e44f54d56db324a35a186d3 (diff) | |
download | connman-11e5f0cbf33f9ef3d5af7a7989cae51b0e963884.tar.gz connman-11e5f0cbf33f9ef3d5af7a7989cae51b0e963884.tar.bz2 connman-11e5f0cbf33f9ef3d5af7a7989cae51b0e963884.zip |
Add g_web_result_get_header support.
Add all http response header to hash table and allow
user to get these header values.
Header with same key will be replaced by last header value.
Diffstat (limited to 'gweb')
-rw-r--r-- | gweb/gweb.c | 99 | ||||
-rw-r--r-- | gweb/gweb.h | 2 |
2 files changed, 88 insertions, 13 deletions
diff --git a/gweb/gweb.c b/gweb/gweb.c index a348cddd..c6a76cc5 100644 --- a/gweb/gweb.c +++ b/gweb/gweb.c @@ -52,6 +52,8 @@ struct _GWebResult { const guint8 *buffer; gsize length; gboolean use_chunk; + gchar *last_key; + GHashTable *headers; }; struct web_session { @@ -148,6 +150,9 @@ static void free_session(struct web_session *session) if (session->transport_channel != NULL) g_io_channel_unref(session->transport_channel); + g_free(session->result.last_key); + g_hash_table_destroy(session->result.headers); + g_string_free(session->send_buffer, TRUE); g_string_free(session->current_header, TRUE); g_free(session->receive_buffer); @@ -718,7 +723,23 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, ptr = NULL; if (session->current_header->len == 0) { + char *val; + session->header_done = TRUE; + + val = g_hash_table_lookup(session->result.headers, + "Transfer-Encoding"); + if (val != NULL) { + val = g_strrstr(val, "chunked"); + if (val != NULL) { + session->result.use_chunk = TRUE; + + session->chunck_state = CHUNK_SIZE; + session->chunk_left = 0; + session->total_len = 0; + } + } + if (handle_body(session, ptr, bytes_read) < 0) { session->transport_watch = 0; return FALSE; @@ -733,23 +754,51 @@ static gboolean received_data(GIOChannel *channel, GIOCondition cond, if (sscanf(str, "HTTP/%*s %u %*s", &code) == 1) session->result.status = code; - } else if (session->result.use_chunk == FALSE && - g_ascii_strncasecmp("Transfer-Encoding:", - str, 18) == 0) { - char *val; + } - val = g_strrstr(str + 18, "chunked"); - if (val != NULL) { - session->result.use_chunk = TRUE; + debug(session->web, "[header] %s", str); - session->chunck_state = CHUNK_SIZE; - session->chunk_left = 0; - session->chunk_left = 0; - session->total_len = 0; + /* handle multi-line header */ + if (str[0] == ' ' || str[0] == '\t') { + gchar *value; + + while (str[0] == ' ' || str[0] == '\t') + str++; + + count = str - session->current_header->str; + if (count > 0) { + g_string_erase(session->current_header, + 0, count); + g_string_insert_c(session->current_header, + 0, ' '); } - } - debug(session->web, "[header] %s", str); + value = g_hash_table_lookup(session->result.headers, + session->result.last_key); + if (value != NULL) { + g_string_insert(session->current_header, + 0, value); + + str = session->current_header->str; + + g_hash_table_replace(session->result.headers, + g_strdup(session->result.last_key), + g_strdup(str)); + } + } else { + pos = memchr(str, ':', session->current_header->len); + if (pos != NULL) { + *pos = '\0'; + pos++; + + g_hash_table_replace(session->result.headers, + g_strdup(str), + g_strdup((char *)pos)); + + g_free(session->result.last_key); + session->result.last_key = g_strdup(str); + } + } g_string_truncate(session->current_header, 0); } @@ -943,6 +992,13 @@ static guint do_request(GWeb *web, const char *url, return 0; } + session->result.headers = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + if (session->result.headers == NULL) { + free_session(session); + return 0; + } + session->receive_space = DEFAULT_BUFFER_SIZE; session->send_buffer = g_string_sized_new(0); session->current_header = g_string_sized_new(0); @@ -1016,6 +1072,23 @@ gboolean g_web_result_get_chunk(GWebResult *result, return TRUE; } +gboolean g_web_result_get_header(GWebResult *result, + const char *header, const char **value) +{ + if (result == NULL) + return FALSE; + + if (value == NULL) + return FALSE; + + *value = g_hash_table_lookup(result->headers, header); + + if (*value == NULL) + return FALSE; + + return TRUE; +} + struct _GWebParser { gint ref_count; char *begin_token; diff --git a/gweb/gweb.h b/gweb/gweb.h index 5bbcc9aa..2979db52 100644 --- a/gweb/gweb.h +++ b/gweb/gweb.h @@ -75,6 +75,8 @@ gboolean g_web_cancel_request(GWeb *web, guint id); guint16 g_web_result_get_status(GWebResult *result); +gboolean g_web_result_get_header(GWebResult *result, + const char *header, const char **value); gboolean g_web_result_get_chunk(GWebResult *result, const guint8 **chunk, gsize *length); |