# HG changeset patch # User Christian Hammond # Date 1042851222 0 # Node ID bbd7b12986a89a37c1d9bbd57e5259ab11bb99ab # Parent a9dc4f90d490e301b95802d824fd2c17efcf4018 [gaim-migrate @ 4595] Okay, a few new goodies in here! HTTP redirect support! Sean wants to be able to drag-and-drop themes from our new themes page, but they're hiding behind a script that redirects. Rather than lose functionality in the script, I added redirects here. Works like a charm. Smarter memory reallocation! The buffer was being reallocated every byte. That means 10,000,000 of data would cause 10,000,000 reallocations. Now it starts off with a buffer of 4096 (for HTTP headers) or 8192 (for data) and reads until it's full. When full, the buffer increases by half of the previous size. Content-Length support! The HTTP headers are scanned for a Content-Length header. If found, it uses this for the buffer instead of 8192. This should reduce the number of reallocations to 0. Have fun draggening-and-droppening. committer: Tailor Script diff -r a9dc4f90d490 -r bbd7b12986a8 src/html.c --- a/src/html.c Fri Jan 17 23:28:06 2003 +0000 +++ b/src/html.c Sat Jan 18 00:53:42 2003 +0000 @@ -128,8 +128,64 @@ gboolean startsaving; char *webdata; unsigned long len; + unsigned long data_len; }; +static gboolean +parse_redirect(const char *data, size_t data_len, gint sock, + struct grab_url_data *gunk) +{ + gchar *s; + + if ((s = g_strstr_len(data, data_len, "Location: ")) != NULL) { + gchar *new_url, *end; + int len; + + s += strlen("Location: "); + end = strchr(s, '\r'); + + /* Just in case :) */ + if (end == NULL) + end = strchr(s, '\n'); + + len = end - s; + + new_url = g_malloc(len + 1); + strncpy(new_url, s, len); + new_url[len] = '\0'; + + /* Close the existing stuff. */ + gaim_input_remove(gunk->inpa); + close(sock); + + /* Try again, with this new location. */ + grab_url(new_url, gunk->full, gunk->callback, + gunk->data); + + /* Free up. */ + g_free(new_url); + g_free(gunk->webdata); + g_free(gunk->website); + g_free(gunk->url); + g_free(gunk); + + return TRUE; + } + + return FALSE; +} + +static size_t +parse_content_len(const char *data, size_t data_len) +{ + gchar *s; + size_t content_len = 0; + + sscanf(data, "Content-Length: %d", &content_len); + + return content_len; +} + static void grab_url_callback(gpointer dat, gint sock, GaimInputCondition cond) { struct grab_url_data *gunk = dat; @@ -154,6 +210,8 @@ fcntl(sock, F_SETFL, O_NONBLOCK); gunk->sentreq = TRUE; gunk->inpa = gaim_input_add(sock, GAIM_INPUT_READ, grab_url_callback, dat); + gunk->data_len = 4096; + gunk->webdata = g_malloc(gunk->data_len); return; } @@ -162,21 +220,51 @@ errno = 0; return; } + + gunk->len++; + + if (gunk->len == gunk->data_len + 1) { + gunk->data_len += (gunk->data_len) / 2; + + gunk->webdata = g_realloc(gunk->webdata, gunk->data_len); + } + + gunk->webdata[gunk->len - 1] = data; + if (!gunk->startsaving) { if (data == '\r') return; if (data == '\n') { - if (gunk->newline) + if (gunk->newline) { + size_t content_len; gunk->startsaving = TRUE; + + /* See if we can find a redirect. */ + if (parse_redirect(gunk->webdata, gunk->len, sock, gunk)) + return; + + /* No redirect. See if we can find a content length. */ + content_len = parse_content_len(gunk->webdata, gunk->len); + + if (content_len == 0) { + /* We'll stick with an initial 8192 */ + content_len = 8192; + } + + /* Out with the old... */ + gunk->len = 0; + g_free(gunk->webdata); + gunk->webdata = NULL; + + /* In with the new. */ + gunk->data_len = content_len; + gunk->webdata = g_malloc(gunk->data_len); + } else gunk->newline = TRUE; return; } gunk->newline = FALSE; - } else { - gunk->len++; - gunk->webdata = g_realloc(gunk->webdata, gunk->len); - gunk->webdata[gunk->len - 1] = data; } } else if (errno != ETIMEDOUT) { gunk->webdata = g_realloc(gunk->webdata, gunk->len + 1);