Mercurial > pidgin.yaz
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 |