1 /*
2 * Author: William Chia-Wei Cheng (bill.cheng@acm.org)
3 *
4 * Copyright (C) 2001-2009, William Chia-Wei Cheng.
5 *
6 * This file may be distributed under the terms of the Q Public License
7 * as defined by Trolltech AS of Norway and appearing in the file
8 * LICENSE.QPL included in the packaging of this file.
9 *
10 * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
11 * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
12 * PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
13 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
14 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
15 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
16 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 *
18 * @(#)$Header: /mm2/home/cvs/bc-src/tgif/stream.c,v 1.6 2011/05/16 16:21:59 william Exp $
19 */
20
21 #define _INCLUDE_FROM_STREAM_C_
22
23 #include "tgifdefs.h"
24
25 #include "dialog.e"
26 #include "drawing.e"
27 #include "file.e"
28 #include "http.e"
29 #include "import.e"
30 #include "menu.e"
31 #include "move.e"
32 #include "msg.e"
33 #include "navigate.e"
34 #include "obj.e"
35 #include "remote.e"
36 #include "setup.e"
37 #include "stream.e"
38 #include "strtbl.e"
39 #include "util.e"
40
41 static int gnMultipartReplace=FALSE;
42 static int gnPossibleMultipartReplace=TRUE;
43
44 static int gnJustLF=0;
45 static int gnHeaderLen=0;
46 static int gnStartIndex=0;
47 static int gnBoundaryLen=0;
48
49 static char *gpszBoundary=NULL;
50
51 static struct ObjRec *gpVideoObj=NULL;
52
53 static char **gaszFilterForContentType=NULL;
54 static int gnMaxStreamFilters=0;
55
56 static
CleanUpFilter()57 void CleanUpFilter()
58 {
59 if (gaszFilterForContentType != NULL) {
60 int i=0;
61
62 for (i=0; i < (gnMaxStreamFilters<<1); i++) {
63 UtilFree(gaszFilterForContentType[i]);
64 UtilFree(gaszFilterForContentType[++i]);
65 }
66 free(gaszFilterForContentType);
67 }
68 gaszFilterForContentType = NULL;
69 gnMaxStreamFilters = 0;
70 }
71
72 static
InitFilter()73 void InitFilter()
74 {
75 char *c_ptr=NULL;
76 int max_filters=0;
77
78 if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"MaxStreamFilters")) != NULL) {
79 max_filters = atoi(c_ptr);
80 if (max_filters <= 0) {
81 sprintf(gszMsgBox, TgLoadString(STID_BAD_XDEF_MUST_BE_GT_0),
82 TOOL_NAME, "MaxStreamFilters", c_ptr);
83 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
84 }
85 }
86 gnMaxStreamFilters = 0;
87 if (max_filters > 0) {
88 int i=0;
89
90 gaszFilterForContentType =
91 (char**)malloc(((max_filters<<1)+1)*sizeof(char*));
92 if (gaszFilterForContentType == NULL) FailAllocMessage();
93 memset(gaszFilterForContentType, 0, ((max_filters<<1)+1)*sizeof(char*));
94 for (i=0; i < max_filters; i++) {
95 char buf[80];
96
97 sprintf(buf, "StreamFilter%1d", i);
98 if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,buf)) == NULL) {
99 sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_XDEF), TOOL_NAME,
100 buf);
101 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
102 max_filters = i;
103 break;
104 } else {
105 char *psz=strchr(c_ptr, ':');
106 int index=(i<<1);
107
108 if (psz == NULL) {
109 sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF), TOOL_NAME,
110 buf, c_ptr);
111 MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
112 max_filters = i;
113 break;
114 }
115 *psz++ = '\0';
116 gaszFilterForContentType[index] = UtilStrDup(c_ptr);
117 gaszFilterForContentType[index+1] = UtilStrDup(psz);
118 if (gaszFilterForContentType[index] == NULL ||
119 gaszFilterForContentType[index+1] == NULL) {
120 FailAllocMessage();
121 }
122 UtilTrimBlanks(gaszFilterForContentType[index]);
123 UtilTrimBlanks(gaszFilterForContentType[index+1]);
124 }
125 }
126 if (max_filters == 0) {
127 free(gaszFilterForContentType);
128 gaszFilterForContentType = NULL;
129 }
130 }
131 gnMaxStreamFilters = max_filters;
132 }
133
CleanUpMime()134 void CleanUpMime()
135 {
136 gnMultipartReplace = FALSE;
137 gnPossibleMultipartReplace = TRUE;
138 gnJustLF = gnHeaderLen = gnStartIndex = gnBoundaryLen = 0;
139 UtilFree(gpszBoundary);
140 gpszBoundary = NULL;
141 if (gpVideoObj != NULL) {
142 UnlinkObj(gpVideoObj);
143 FreeObj(gpVideoObj);
144 }
145 gpVideoObj = NULL;
146 CleanUpFilter();
147 }
148
InitMime()149 void InitMime()
150 {
151 gnMultipartReplace = FALSE;
152 gnPossibleMultipartReplace = TRUE;
153 gnJustLF = gnHeaderLen = gnStartIndex = gnBoundaryLen = 0;
154 gpszBoundary = NULL;
155 gpVideoObj = NULL;
156 InitFilter();
157 }
158
ResetMultipartReplace(redraw)159 void ResetMultipartReplace(redraw)
160 int redraw;
161 {
162 gnMultipartReplace = FALSE;
163 gnPossibleMultipartReplace = TRUE;
164 gnJustLF = gnHeaderLen = gnStartIndex = gnBoundaryLen = 0;
165 UtilFree(gpszBoundary);
166 gpszBoundary = NULL;
167 if (gpVideoObj != NULL) {
168 UnlinkObj(gpVideoObj);
169 FreeObj(gpVideoObj);
170 if (redraw) {
171 ClearAndRedrawDrawWindow();
172 }
173 }
174 gpVideoObj = NULL;
175 }
176
IsJustLF(buf)177 int IsJustLF(buf)
178 char *buf;
179 {
180 char *first_lf=strchr(buf, '\n');
181
182 if (first_lf == NULL) return TRUE;
183 if (first_lf == buf) return TRUE;
184 --first_lf;
185 return (*first_lf != '\r');
186 }
187
GetHeaderLine(psz_start,just_lf)188 char *GetHeaderLine(psz_start, just_lf)
189 char *psz_start;
190 int just_lf;
191 {
192 if (just_lf) {
193 return strchr(psz_start, '\n');
194 } else {
195 return strstr(psz_start, "\r\n");
196 }
197 }
198
199 static char *gppszValidMultipartReplace[] = {
200 "multipart/x-mixed-replace", /* only knows about JPEG movie */
201 NULL
202 };
203
204 static
ValidMultipartReplace(buf,pn_multipart)205 int ValidMultipartReplace(buf, pn_multipart)
206 char *buf;
207 int *pn_multipart;
208 {
209 char *psz=NULL, *psz_copy=UtilStrDup(buf);
210 char **ppsz=NULL;
211
212 *pn_multipart = FALSE;
213
214 if (psz_copy == NULL) FailAllocMessage();
215 UtilTrimBlanks(psz_copy);
216 psz = strchr(psz_copy, '/');
217 if (psz != NULL) {
218 *psz = '\0';
219 if (UtilStrICmp(psz_copy, "multipart") == 0) {
220 *pn_multipart = TRUE;
221 }
222 *psz = '/';
223 } else {
224 UtilFree(psz_copy);
225 return FALSE;
226 }
227 for (ppsz=gppszValidMultipartReplace; *ppsz != NULL; ppsz++) {
228 if (UtilStrICmp(*ppsz, psz_copy) == 0) {
229 UtilFree(psz_copy);
230 return TRUE;
231 }
232 }
233 UtilFree(psz_copy);
234 return FALSE;
235 }
236
237 static char *gppszValidImageContentType[] = {
238 "image/jpeg", "JPEG-dither", /* JPEG movie or Motion JPEG */
239 "image/jpg", "JPEG-dither", /* JPEG movie or Motion JPEG */
240 "image/png", "PNG-dither", /* Netscape Server Push */
241 NULL
242 };
243
244 static
ValidImageContentType(buf,ppsz_filter)245 int ValidImageContentType(buf, ppsz_filter)
246 char *buf, **ppsz_filter;
247 {
248 char *psz_copy=UtilStrDup(buf);
249 char **ppsz=NULL;
250
251 if (psz_copy == NULL) FailAllocMessage();
252 UtilTrimBlanks(psz_copy);
253 ppsz = (gaszFilterForContentType==NULL ? gppszValidImageContentType:
254 gaszFilterForContentType);
255 for ( ; *ppsz != NULL; ppsz++) {
256 if (UtilStrICmp(*ppsz, psz_copy) == 0) {
257 if (ppsz_filter != NULL) *ppsz_filter = ppsz[1];
258 UtilFree(psz_copy);
259 return TRUE;
260 }
261 ppsz++;
262 }
263 if (UtilStrICmp(psz_copy, "text/html") == 0) {
264 if (ppsz_filter != NULL) *ppsz_filter = NULL;
265 UtilFree(psz_copy);
266 return TRUE;
267 }
268 UtilFree(psz_copy);
269 return FALSE;
270 }
271
272 static
UpdateBoundary(buf)273 void UpdateBoundary(buf)
274 char *buf;
275 {
276 UtilFree(gpszBoundary);
277 gpszBoundary = (char*)malloc(strlen(buf)+3);
278 if (gpszBoundary == NULL) FailAllocMessage();
279 sprintf(gpszBoundary, "--%s", buf);
280 UtilTrimBlanks(gpszBoundary);
281 if (*gpszBoundary == '"') {
282 int len=strlen(gpszBoundary);
283
284 if (len > 2 && gpszBoundary[len-1] == '"') {
285 char *psz=gpszBoundary, *psz1=(&gpszBoundary[1]);
286
287 gpszBoundary[--len] = '\0';
288 while (*psz1 != '\0') {
289 *psz++ = *psz1++;
290 }
291 *psz = '\0';
292 }
293 }
294 gnBoundaryLen = strlen(gpszBoundary);
295 }
296
297 static
FindBoundary(buf)298 int FindBoundary(buf)
299 char *buf;
300 {
301 char *semi_colon=NULL;
302 int found=FALSE;
303
304 while (*buf == ' ' || *buf == '\t') buf++;
305 semi_colon = strchr(buf, ';');
306 while (!found) {
307 char *equal_ptr=NULL;
308
309 if (semi_colon != NULL) *semi_colon = '\0';
310 equal_ptr = strchr(buf, '=');
311 if (equal_ptr != NULL) {
312 *equal_ptr = '\0';
313 if (UtilStrICmp(buf, "boundary") == 0) {
314 UpdateBoundary(&equal_ptr[1]);
315 found = TRUE;
316 }
317 *equal_ptr = '=';
318 }
319 if (semi_colon == NULL) break;
320 *semi_colon++ = ';';
321 buf = semi_colon;
322 while (*buf == ' ' || *buf == '\t') buf++;
323 semi_colon = strchr(buf, ';');
324 }
325 return found;
326 }
327
328 static
GetContentLength(buf)329 int GetContentLength(buf)
330 char *buf;
331 {
332 char *c_ptr=NULL, *psz=NULL, *line_ptr=buf;
333 int content_len=(-1), just_lf=IsJustLF(buf);
334 int good_content_type=FALSE, last_line_is_content_type=FALSE;
335 int inc=(just_lf?1:2);
336
337 for (c_ptr=GetHeaderLine(line_ptr, just_lf); c_ptr != NULL;
338 c_ptr=GetHeaderLine(line_ptr, just_lf)) {
339 char *colon_ptr=NULL;
340
341 if (c_ptr == line_ptr) {
342 /* reach the end of header, now decide if the header is good */
343 gnJustLF = just_lf;
344 gnHeaderLen = gnStartIndex = ((&c_ptr[inc]) - buf);
345 if (good_content_type && gpszBoundary != NULL) {
346 gnMultipartReplace = TRUE;
347 if ((debugHttp % 100) == 99 && cmdLineDumpURL &&
348 cmdLineDumpURLWithHeader) {
349 fprintf(stdout, "%s", buf);
350 }
351 } else {
352 ResetMultipartReplace(FALSE);
353 gnPossibleMultipartReplace = FALSE;
354 }
355 return (content_len==(-1) ? 0 : content_len);
356 }
357 *c_ptr = '\0';
358 if (*line_ptr == ' ' || *line_ptr == '\t') {
359 if (last_line_is_content_type && good_content_type) {
360 for (psz=line_ptr; *psz == ' ' || *psz == '\t'; psz++) ;
361 FindBoundary(psz);
362 }
363 } else {
364 last_line_is_content_type = FALSE;
365 colon_ptr = strchr(line_ptr, ':');
366 if (colon_ptr != NULL) {
367 *colon_ptr = '\0';
368 if (UtilStrICmp(line_ptr, "Content-Length") == 0) {
369 char length_str[MAXSTRING];
370 int len=0;
371
372 UtilStrCpyN(length_str, MAXSTRING-1, &colon_ptr[1]);
373 UtilTrimBlanks(length_str);
374 if (sscanf(length_str, "%d", &len) == 1) {
375 content_len = len;
376 }
377 } else if (UtilStrICmp(line_ptr, "Content-Type") == 0) {
378 int multipart=FALSE;
379
380 last_line_is_content_type = TRUE;
381 psz = strchr(&colon_ptr[1], ';');
382 if (psz != NULL) *psz = '\0';
383 good_content_type = ValidMultipartReplace(&colon_ptr[1],
384 &multipart);
385 if (!good_content_type && multipart) {
386 #ifdef _TGIF_DBG /* debug, do not translate */
387 fprintf(stderr, "%s Content-Type: %s\n",
388 "Does not know how to handle", &colon_ptr[1]);
389 #endif /* _TGIF_DBG */
390 }
391 if (psz != NULL) {
392 *psz++ = ';';
393 if (good_content_type) {
394 FindBoundary(psz);
395 }
396 }
397 }
398 *colon_ptr = ':';
399 }
400 }
401 *c_ptr = (just_lf ? '\n' : '\r');
402 line_ptr = (&c_ptr[inc]);
403 }
404 return (-1);
405 }
406
407 static
ScanHeader(buf)408 void ScanHeader(buf)
409 char *buf;
410 {
411 if (GetContentLength(buf) > 0) {
412 /* the header contains Content-Length, no good! */
413 ResetMultipartReplace(FALSE);
414 gnPossibleMultipartReplace = FALSE;
415 }
416 }
417
418 typedef struct tagImageContentInfo {
419 char sz_content_type[MAXSTRING];
420 char *psz_filter;
421 int content_len;
422 int header_len;
423 } ImageContentInfo;
424
425 /*
426 * The data in the buffer is expected to have the following structure:
427 *
428 * HTTP/1.0 200
429 * Content-Type: multipart/x-mixed-replace: boundary=BOUNDARYPATTERN
430 *
431 * --BOUNDARYPATTERN
432 * Content-Type: image/jpeg
433 *
434 * ~~~~..JFIF.....H.H..~~..Photoshop 3.0.8BIM.~....
435 * 3~O~~~~~~.~~~~?~G~~~~~~~~,~~~a~ \~~~
436 *
437 * --BOUNDARYPATTERN
438 * Content-Type: image/jpeg
439 *
440 * ~~~~..JFIF..........~~.C...........#!.$.M2.**.^C
441 * ..................................~~
442 *
443 * Notices that the first 3 bytes in a JPEG file is ff d8 ff and
444 * the last 2 bytes are ff d9. This is how the code can figure
445 * out the end of the JPEG file without Content-Length.
446 */
447
448 static
GetContent(buf,buf_len,start_index,pici)449 int GetContent(buf, buf_len, start_index, pici)
450 char *buf;
451 int buf_len, start_index;
452 ImageContentInfo *pici;
453 {
454 char *c_ptr=NULL, *line_ptr=(&buf[start_index]);
455 int content_len=(-1), just_lf=IsJustLF(line_ptr);
456 int found_boundary=FALSE, inc=(just_lf?1:2), first_line=TRUE;
457 int faked_found_boundary=FALSE, seen_none_blank_line=FALSE;
458
459 memset(pici, 0, sizeof(ImageContentInfo));
460 for (c_ptr=GetHeaderLine(line_ptr, just_lf); c_ptr != NULL;
461 c_ptr=GetHeaderLine(line_ptr, just_lf)) {
462 char *colon_ptr=NULL;
463
464 if (!found_boundary) {
465 *c_ptr = '\0';
466 if (*line_ptr == ' ' || *line_ptr == '\t') {
467 /* ignore */
468 } else if (first_line && *line_ptr == '\0') {
469 /*
470 * it may not have the boundary line, just pretend that the
471 * boundary line is found
472 */
473 found_boundary = TRUE;
474 faked_found_boundary = TRUE;
475 } else {
476 if (strcmp(line_ptr, gpszBoundary) == 0) {
477 found_boundary = TRUE;
478 } else if (strncmp(gpszBoundary, "----", 4) == 0 &&
479 strcmp(line_ptr, &gpszBoundary[2]) == 0) {
480 found_boundary = TRUE;
481 UpdateBoundary(&line_ptr[2]);
482 }
483 seen_none_blank_line = TRUE;
484 }
485 first_line = FALSE;
486 *c_ptr = (just_lf ? '\n' : '\r');
487 line_ptr = (&c_ptr[inc]);
488 continue;
489 }
490 if (c_ptr == line_ptr && seen_none_blank_line) {
491 /* reach the end of header, now decide if the header is good */
492
493 pici->header_len = ((&c_ptr[inc])-(&buf[start_index]));
494 pici->content_len = (content_len==(-1) ? 0 : content_len);
495 if (pici->content_len == 0) {
496 /*
497 * no content length information, see if it's really a JPEG file,
498 * and if it is, just look for the EOI
499 */
500 if (start_index+pici->header_len+3 <= buf_len) {
501 char *psz=(&buf[start_index+pici->header_len]);
502
503 if (psz[0] == ((char)0xff) && psz[1] == ((char)0xd8) &&
504 psz[2] == ((char)0xff)) {
505 int index=0;
506
507 /* now look for EOI, which is 0xffd9 */
508 for (index=start_index+pici->header_len; index < buf_len-1;
509 index++, psz++) {
510 if (*psz == ((char)0xff) && psz[1] == ((char)0xd9)) {
511 /* got EOI, now we know the content length */
512 pici->content_len = content_len =
513 index+2-(start_index+pici->header_len);
514 break;
515 }
516 }
517 } else if (psz[0] == ((char)0x89) && psz[1] == 'P' &&
518 psz[2] == 'N' && psz[3] == 'G') {
519 /*
520 * Well, Content-Length better be there!
521 */
522 } else {
523 /* this stream should be abandoned */
524 }
525 }
526 }
527 if (start_index+pici->header_len+pici->content_len >= buf_len) {
528 /* image is not in the buffer yet */
529 return (-1);
530 }
531 return (content_len==(-1) ? 0 : content_len);
532 }
533 *c_ptr = '\0';
534 if (*line_ptr == ' ' || *line_ptr == '\t' || *line_ptr == '\0') {
535 /* ignore */
536 } else {
537 seen_none_blank_line = TRUE;
538
539 colon_ptr = strchr(line_ptr, ':');
540 if (colon_ptr != NULL) {
541 *colon_ptr = '\0';
542 if (UtilStrICmp(line_ptr, "Content-Length") == 0) {
543 char length_str[MAXSTRING];
544 int len;
545
546 UtilStrCpyN(length_str, MAXSTRING-1, &colon_ptr[1]);
547 UtilTrimBlanks(length_str);
548 if (sscanf(length_str, "%d", &len) == 1) {
549 content_len = len;
550 }
551 } else if (UtilStrICmp(line_ptr, "Content-Type") == 0) {
552 char *psz=strchr(&colon_ptr[1], ';');
553
554 if (psz != NULL) *psz = '\0';
555 UtilStrCpyN(pici->sz_content_type,
556 sizeof(pici->sz_content_type),
557 &colon_ptr[1]);
558 UtilTrimBlanks(pici->sz_content_type);
559 if (!ValidImageContentType(&colon_ptr[1], &pici->psz_filter)) {
560 fprintf(stderr,
561 TgLoadCachedString(CSTID_DONT_KNOW_HOW_HANDLE_FRAME_CT),
562 &colon_ptr[1]);
563 fprintf(stderr, "\n");
564 } else if (pici->psz_filter == NULL) {
565 /* content-type is text/html, pretend it's okay */
566 }
567 if (psz != NULL) *psz++ = ';';
568 }
569 *colon_ptr = ':';
570 } else if (faked_found_boundary) {
571 if (strcmp(line_ptr, gpszBoundary) == 0) {
572 faked_found_boundary = FALSE;
573 }
574 }
575 }
576 *c_ptr = (just_lf ? '\n' : '\r');
577 line_ptr = (&c_ptr[inc]);
578 }
579 return (-1);
580 }
581
582 static
ScanBody(buf,pn_buf_len)583 void ScanBody(buf, pn_buf_len)
584 char *buf;
585 int *pn_buf_len;
586 {
587 ImageContentInfo ici;
588
589 memset(&ici, 0, sizeof(ImageContentInfo));
590 while (GetContent(buf, *pn_buf_len, gnStartIndex, &ici) > 0) {
591 if (*ici.sz_content_type != '\0' && ici.psz_filter != NULL) {
592 char *tmp_fname=WriteRemoteFileIntoTemp(
593 &buf[gnStartIndex+ici.header_len], ici.content_len, NULL);
594
595 if (tmp_fname != NULL) {
596 int left_over=0;
597 int saved_enable_failed_import_msgbox=GetEnableFailedImportMsgBox();
598 char *dest=NULL, *src=NULL;
599
600 if (gpVideoObj != NULL) {
601 UnlinkObj(gpVideoObj);
602 FreeObj(gpVideoObj);
603 }
604 gpVideoObj = NULL;
605 if (strcmp(ici.sz_content_type, "image/png") == 0) {
606 SetEnableFailedImportMsgBox(FALSE);
607 }
608 if (ImportSpecifiedFileType(tmp_fname, ici.psz_filter)) {
609 gpVideoObj = topObj;
610 MoveObj(gpVideoObj, drawOrigX-gpVideoObj->obbox.ltx,
611 drawOrigY-gpVideoObj->obbox.lty);
612 DrawObj(drawWindow, gpVideoObj);
613 }
614 SetEnableFailedImportMsgBox(saved_enable_failed_import_msgbox);
615 unlink(tmp_fname);
616 free(tmp_fname);
617 /* now we need to shrink the buffer */
618 left_over = *pn_buf_len -
619 gnStartIndex - ici.header_len - ici.content_len;
620 dest = (&buf[gnStartIndex]);
621 src = (&buf[gnStartIndex+ici.header_len+ici.content_len]);
622 if (left_over >= 5 && UtilStrNCaseCmp(src, "HTTP/", 5) == 0) {
623 dest = buf;
624 memcpy(dest, src, left_over*sizeof(char));
625 *pn_buf_len = left_over;
626 ResetMultipartReplace(FALSE);
627 ScanHeader(buf);
628 if (!gnMultipartReplace) {
629 return;
630 }
631 } else {
632 memcpy(dest, src, left_over*sizeof(char));
633 *pn_buf_len = gnStartIndex + left_over;
634 }
635 }
636 }
637 }
638 }
639
HandleMultipartReplace(buf,pn_buf_len)640 void HandleMultipartReplace(buf, pn_buf_len)
641 char *buf;
642 int *pn_buf_len;
643 {
644 if (!gnPossibleMultipartReplace) return;
645
646 if (gnMultipartReplace) {
647 ScanBody(buf, pn_buf_len);
648 } else {
649 ScanHeader(buf);
650 if (gnMultipartReplace) {
651 ScanBody(buf, pn_buf_len);
652 }
653 }
654 }
655
FakeUserAgent(buf)656 void FakeUserAgent(buf)
657 char *buf;
658 {
659 char prev_agent[MAXSTRING<<1], spec[MAXSTRING<<1];
660
661 if (buf != NULL && strcmp(buf, "-1") != 0) {
662 int len=0;
663
664 UtilStrCpyN(spec, sizeof(spec), buf);
665 UtilTrimBlanks(spec);
666 len = strlen(spec);
667 if (len > 0 && spec[len-1] == ')') spec[len-1] = '\0';
668 } else {
669 *prev_agent = '\0';
670 GetUserAgent(prev_agent, sizeof(prev_agent));
671 if (*prev_agent == '\0') {
672 sprintf(gszMsgBox, TgLoadString(STID_ENTER_USERAGENT_FOR_HTTP));
673 } else {
674 sprintf(gszMsgBox, TgLoadString(STID_ENTER_USERAGENT_FOR_HTTP_CUR),
675 prev_agent);
676 }
677 *spec = '\0';
678 if (Dialog(gszMsgBox, TgLoadString(STID_PRESS_ENTER_FOR_DEF_USERAGENT),
679 spec) == INVALID) {
680 return;
681 }
682 }
683 UtilTrimBlanks(spec);
684 SetUserAgent(spec);
685 *prev_agent = '\0';
686 GetUserAgent(prev_agent, sizeof(prev_agent));
687 if (*prev_agent == '\0') {
688 sprintf(gszMsgBox, TgLoadString(STID_WILL_USE_DEF_USERAGENT_HTTP));
689 } else {
690 sprintf(gszMsgBox, TgLoadString(STID_WILL_USE_NAMED_USERAGENT_HTTP),
691 prev_agent);
692 }
693 Msg(gszMsgBox);
694 }
695
FakeReferer(buf)696 void FakeReferer(buf)
697 char *buf;
698 {
699 char spec[MAXSTRING<<1];
700
701 *spec = '\0';
702 if (buf != NULL && strcmp(buf, "-1") != 0) {
703 int len=0;
704
705 UtilStrCpyN(spec, sizeof(spec), buf);
706 UtilTrimBlanks(spec);
707 len = strlen(spec);
708 if (len > 0 && spec[len-1] == ')') spec[len-1] = '\0';
709 } else {
710 if (gpszFakedReferer == NULL) {
711 sprintf(gszMsgBox, TgLoadString(STID_ENTER_REFERRER_FOR_HTTP));
712 } else {
713 sprintf(gszMsgBox, TgLoadString(STID_ENTER_REFERRER_FOR_HTTP_CUR),
714 gpszFakedReferer);
715 }
716 *spec = '\0';
717 if (Dialog(gszMsgBox, TgLoadString(STID_PRESS_ENTER_FOR_NO_REFERRER),
718 spec) == INVALID) {
719 return;
720 }
721 }
722 if (*spec != '\0') {
723 if (!navigatingBackAndForth) BeforeNavigate();
724 ClearFileInfo(FALSE);
725 RedrawTitleWindow();
726 }
727 UtilTrimBlanks(spec);
728 HttpFakeReferer(spec);
729 if (gpszFakedReferer == NULL) {
730 sprintf(gszMsgBox, TgLoadString(STID_WILL_NOT_USE_REFERRER_HTTP));
731 } else {
732 sprintf(gszMsgBox, TgLoadString(STID_WILL_USE_NAMED_REFERRER_HTTP),
733 gpszFakedReferer);
734 }
735 Msg(gszMsgBox);
736 }
737
ToggleKeepAlive()738 void ToggleKeepAlive()
739 {
740 gnHttpKeepAlive = (!gnHttpKeepAlive);
741 sprintf(gszMsgBox, TgLoadString(gnHttpKeepAlive ?
742 STID_WILL_USE_KEEP_ALIVE_HTTP : STID_NOT_WILL_USE_KEEP_ALIVE_HTTP));
743 Msg(gszMsgBox);
744 }
745
746