summaryrefslogtreecommitdiff
path: root/gweb
diff options
context:
space:
mode:
authorMohamed Abbas <mabbas@linux.intel.com>2010-12-27 14:17:40 -0800
committerMarcel Holtmann <marcel@holtmann.org>2010-12-28 09:21:32 -0800
commit11e5f0cbf33f9ef3d5af7a7989cae51b0e963884 (patch)
tree5b8f95c63fdac94da3fb5bfc0091c4872096654f /gweb
parent315a38ee636840ea9e44f54d56db324a35a186d3 (diff)
downloadconnman-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.c99
-rw-r--r--gweb/gweb.h2
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);