summaryrefslogtreecommitdiff
path: root/gweb/gweb.c
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/gweb.c
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/gweb.c')
-rw-r--r--gweb/gweb.c99
1 files changed, 86 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;