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