Mercurial > pidgin
comparison src/html.c @ 4331:bbd7b12986a8
[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 <tailor@pidgin.im>
| author | Christian Hammond <chipx86@chipx86.com> |
|---|---|
| date | Sat, 18 Jan 2003 00:53:42 +0000 |
| parents | a789969fc198 |
| children | 60b9f8fccce8 |
comparison
equal
deleted
inserted
replaced
| 4330:a9dc4f90d490 | 4331:bbd7b12986a8 |
|---|---|
| 126 gboolean sentreq; | 126 gboolean sentreq; |
| 127 gboolean newline; | 127 gboolean newline; |
| 128 gboolean startsaving; | 128 gboolean startsaving; |
| 129 char *webdata; | 129 char *webdata; |
| 130 unsigned long len; | 130 unsigned long len; |
| 131 unsigned long data_len; | |
| 131 }; | 132 }; |
| 133 | |
| 134 static gboolean | |
| 135 parse_redirect(const char *data, size_t data_len, gint sock, | |
| 136 struct grab_url_data *gunk) | |
| 137 { | |
| 138 gchar *s; | |
| 139 | |
| 140 if ((s = g_strstr_len(data, data_len, "Location: ")) != NULL) { | |
| 141 gchar *new_url, *end; | |
| 142 int len; | |
| 143 | |
| 144 s += strlen("Location: "); | |
| 145 end = strchr(s, '\r'); | |
| 146 | |
| 147 /* Just in case :) */ | |
| 148 if (end == NULL) | |
| 149 end = strchr(s, '\n'); | |
| 150 | |
| 151 len = end - s; | |
| 152 | |
| 153 new_url = g_malloc(len + 1); | |
| 154 strncpy(new_url, s, len); | |
| 155 new_url[len] = '\0'; | |
| 156 | |
| 157 /* Close the existing stuff. */ | |
| 158 gaim_input_remove(gunk->inpa); | |
| 159 close(sock); | |
| 160 | |
| 161 /* Try again, with this new location. */ | |
| 162 grab_url(new_url, gunk->full, gunk->callback, | |
| 163 gunk->data); | |
| 164 | |
| 165 /* Free up. */ | |
| 166 g_free(new_url); | |
| 167 g_free(gunk->webdata); | |
| 168 g_free(gunk->website); | |
| 169 g_free(gunk->url); | |
| 170 g_free(gunk); | |
| 171 | |
| 172 return TRUE; | |
| 173 } | |
| 174 | |
| 175 return FALSE; | |
| 176 } | |
| 177 | |
| 178 static size_t | |
| 179 parse_content_len(const char *data, size_t data_len) | |
| 180 { | |
| 181 gchar *s; | |
| 182 size_t content_len = 0; | |
| 183 | |
| 184 sscanf(data, "Content-Length: %d", &content_len); | |
| 185 | |
| 186 return content_len; | |
| 187 } | |
| 132 | 188 |
| 133 static void grab_url_callback(gpointer dat, gint sock, GaimInputCondition cond) | 189 static void grab_url_callback(gpointer dat, gint sock, GaimInputCondition cond) |
| 134 { | 190 { |
| 135 struct grab_url_data *gunk = dat; | 191 struct grab_url_data *gunk = dat; |
| 136 char data; | 192 char data; |
| 152 | 208 |
| 153 write(sock, buf, strlen(buf)); | 209 write(sock, buf, strlen(buf)); |
| 154 fcntl(sock, F_SETFL, O_NONBLOCK); | 210 fcntl(sock, F_SETFL, O_NONBLOCK); |
| 155 gunk->sentreq = TRUE; | 211 gunk->sentreq = TRUE; |
| 156 gunk->inpa = gaim_input_add(sock, GAIM_INPUT_READ, grab_url_callback, dat); | 212 gunk->inpa = gaim_input_add(sock, GAIM_INPUT_READ, grab_url_callback, dat); |
| 213 gunk->data_len = 4096; | |
| 214 gunk->webdata = g_malloc(gunk->data_len); | |
| 157 return; | 215 return; |
| 158 } | 216 } |
| 159 | 217 |
| 160 if (read(sock, &data, 1) > 0 || errno == EWOULDBLOCK) { | 218 if (read(sock, &data, 1) > 0 || errno == EWOULDBLOCK) { |
| 161 if (errno == EWOULDBLOCK) { | 219 if (errno == EWOULDBLOCK) { |
| 162 errno = 0; | 220 errno = 0; |
| 163 return; | 221 return; |
| 164 } | 222 } |
| 223 | |
| 224 gunk->len++; | |
| 225 | |
| 226 if (gunk->len == gunk->data_len + 1) { | |
| 227 gunk->data_len += (gunk->data_len) / 2; | |
| 228 | |
| 229 gunk->webdata = g_realloc(gunk->webdata, gunk->data_len); | |
| 230 } | |
| 231 | |
| 232 gunk->webdata[gunk->len - 1] = data; | |
| 233 | |
| 165 if (!gunk->startsaving) { | 234 if (!gunk->startsaving) { |
| 166 if (data == '\r') | 235 if (data == '\r') |
| 167 return; | 236 return; |
| 168 if (data == '\n') { | 237 if (data == '\n') { |
| 169 if (gunk->newline) | 238 if (gunk->newline) { |
| 239 size_t content_len; | |
| 170 gunk->startsaving = TRUE; | 240 gunk->startsaving = TRUE; |
| 241 | |
| 242 /* See if we can find a redirect. */ | |
| 243 if (parse_redirect(gunk->webdata, gunk->len, sock, gunk)) | |
| 244 return; | |
| 245 | |
| 246 /* No redirect. See if we can find a content length. */ | |
| 247 content_len = parse_content_len(gunk->webdata, gunk->len); | |
| 248 | |
| 249 if (content_len == 0) { | |
| 250 /* We'll stick with an initial 8192 */ | |
| 251 content_len = 8192; | |
| 252 } | |
| 253 | |
| 254 /* Out with the old... */ | |
| 255 gunk->len = 0; | |
| 256 g_free(gunk->webdata); | |
| 257 gunk->webdata = NULL; | |
| 258 | |
| 259 /* In with the new. */ | |
| 260 gunk->data_len = content_len; | |
| 261 gunk->webdata = g_malloc(gunk->data_len); | |
| 262 } | |
| 171 else | 263 else |
| 172 gunk->newline = TRUE; | 264 gunk->newline = TRUE; |
| 173 return; | 265 return; |
| 174 } | 266 } |
| 175 gunk->newline = FALSE; | 267 gunk->newline = FALSE; |
| 176 } else { | |
| 177 gunk->len++; | |
| 178 gunk->webdata = g_realloc(gunk->webdata, gunk->len); | |
| 179 gunk->webdata[gunk->len - 1] = data; | |
| 180 } | 268 } |
| 181 } else if (errno != ETIMEDOUT) { | 269 } else if (errno != ETIMEDOUT) { |
| 182 gunk->webdata = g_realloc(gunk->webdata, gunk->len + 1); | 270 gunk->webdata = g_realloc(gunk->webdata, gunk->len + 1); |
| 183 gunk->webdata[gunk->len] = 0; | 271 gunk->webdata[gunk->len] = 0; |
| 184 | 272 |
