summaryrefslogtreecommitdiff
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
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.
-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);