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/remote.c,v 1.9 2011/05/16 16:21:59 william Exp $
19  */
20 
21 #define _INCLUDE_FROM_REMOTE_C_
22 
23 #include "tgifdefs.h"
24 #include "patchlvl.h"
25 
26 #include "cmd.e"
27 #include "cutpaste.e"
28 #include "dialog.e"
29 #include "drawing.e"
30 #include "file.e"
31 #include "ftp.e"
32 #include "http.e"
33 #include "mainloop.e"
34 #include "markup.e"
35 #include "menu.e"
36 #include "msg.e"
37 #include "names.e"
38 #include "navigate.e"
39 #include "page.e"
40 #include "remote.e"
41 #include "setup.e"
42 #include "stream.e"
43 #include "strtbl.e"
44 #include "tcp.e"
45 #include "util.e"
46 #include "version.e"
47 
48 int postingCGIQuery=FALSE;
49 int gettingHttpHeaderOnly=FALSE;
50 char *fnameForPostingCGIQuery=NULL;
51 char gszLocalPID[MAXSTRING];
52 char gzipCmd[MAXPATHLENGTH+1];
53 char gunzipCmd[MAXPATHLENGTH+1];
54 
55 static int debugRemote=FALSE;
56 static char uncompressCmd[MAXPATHLENGTH+1];
57 static char httpProxy[MAXPATHLENGTH+1];
58 static char ftpProxy[MAXPATHLENGTH+1];
59 
60 typedef struct DownloadStatRec {
61    int timestamp;
62    int cumulative_bytes;
63    struct DownloadStatRec *next, *prev;
64 } *DownloadStatRecPtr;
65 
66 static struct DownloadStatRec *gpFirstDLS=NULL, *gpLastDLS=NULL;
67 static int gnDownloadStartTime=0;
68 
CleanUpDownloadStats()69 void CleanUpDownloadStats()
70 {
71    struct DownloadStatRec *pdls=NULL, *next_pdls=NULL;
72 
73    for (pdls=gpFirstDLS; pdls != NULL; pdls=next_pdls) {
74       next_pdls = pdls->next;
75       free(pdls);
76    }
77    gpFirstDLS = gpLastDLS = NULL;
78    gnDownloadStartTime = 0;
79 }
80 
81 #define THROUGHPUT_WINDOW 10
82 
UpdateDownloadStats(bytes,psz_buf)83 int UpdateDownloadStats(bytes, psz_buf)
84    int bytes;
85    char *psz_buf;
86 {
87    struct DownloadStatRec *pdls=NULL;
88    time_t tloc;
89    int curtime=0, count=0, elapsetime=0, interval=0;
90    float bps=(float)0;
91 
92    *psz_buf = '\0';
93    time(&tloc);
94    curtime = (int)tloc;
95    if (gpFirstDLS == NULL) gnDownloadStartTime = curtime;
96    pdls = gpLastDLS;
97    if (pdls != NULL) {
98       if (curtime == pdls->timestamp) {
99          pdls->cumulative_bytes += bytes;
100       } else {
101          pdls = NULL;
102       }
103    }
104    if (pdls == NULL) {
105       pdls = (struct DownloadStatRec *)malloc(sizeof(struct DownloadStatRec));
106       if (pdls == NULL) FailAllocMessage();
107       memset(pdls, 0, sizeof(struct DownloadStatRec));
108       pdls->timestamp = curtime;
109       pdls->cumulative_bytes = (gpLastDLS==NULL ? 0 :
110             gpLastDLS->cumulative_bytes);
111       pdls->cumulative_bytes += bytes;
112       pdls->prev = gpLastDLS;
113       pdls->next = NULL;
114       if (gpLastDLS == NULL) {
115          gpFirstDLS = pdls;
116       } else {
117          gpLastDLS->next = pdls;
118       }
119       gpLastDLS = pdls;
120    }
121    if (gnDownloadStartTime == curtime) {
122       return FALSE;
123    }
124    for (pdls=gpLastDLS, count=0; pdls != NULL && count < THROUGHPUT_WINDOW;
125          pdls=pdls->prev, count++) {
126    }
127    elapsetime = gpLastDLS->timestamp - gnDownloadStartTime;
128    if (pdls == NULL) {
129       interval = elapsetime;
130       bps = ((float)(gpLastDLS->cumulative_bytes)) / ((float)interval);
131    } else {
132       interval = gpLastDLS->timestamp - pdls->timestamp;
133       bps = ((float)(gpLastDLS->cumulative_bytes - pdls->cumulative_bytes)) /
134             ((float)interval);
135    }
136    bps /= (float)1000;
137    sprintf(psz_buf, TgLoadCachedString(CSTID_PARANED_SEC_ELAPSED_AVG_SPEED),
138          elapsetime, bps);
139    return TRUE;
140 }
141 
142 static int gnUserAgentInitialized=FALSE;
143 static char gszUserAgentName[MAXSTRING];
144 
145 static
InitUserAgentName()146 void InitUserAgentName()
147 {
148    char *c_ptr=NULL;
149 
150    if (!gnUserAgentInitialized) {
151       gnUserAgentInitialized = TRUE;
152       *gszUserAgentName = '\0';
153       if (!(PRTGIF && !cmdLineOpenDisplay) &&
154             (c_ptr=XGetDefault(mainDisplay, TOOL_NAME, "UserAgentName")) !=
155             NULL) {
156          strcpy(gszUserAgentName, c_ptr);
157          UtilTrimBlanks(gszUserAgentName);
158       }
159    }
160 }
161 
GetClientID(psz_buf,buf_sz)162 int GetClientID(psz_buf, buf_sz)
163    char *psz_buf;
164    int buf_sz;
165 {
166    char agent_name[128];
167 
168    *agent_name = '\0';
169    InitUserAgentName();
170    if (*gszUserAgentName != '\0') strcpy(agent_name, gszUserAgentName);
171 
172    if (*agent_name == '\0') {
173       if (*specialBuild == '\0') {
174          sprintf(agent_name, "%s/%s.%1d", TOOL_NAME, versionString,
175                TGIF_PATCHLEVEL);
176       } else {
177          sprintf(agent_name, "%s/%s.%1d-%s", TOOL_NAME, versionString,
178                TGIF_PATCHLEVEL, specialBuild);
179       }
180    }
181    return UtilStrCpyN(psz_buf, buf_sz, agent_name);
182 }
183 
GetUserAgent(buf,buf_sz)184 void GetUserAgent(buf, buf_sz)
185    char *buf;
186    int buf_sz;
187 {
188    InitUserAgentName();
189    if (buf == NULL || buf_sz <= 0) return;
190    *buf = '\0';
191    UtilStrCpyN(buf, buf_sz, gszUserAgentName);
192 }
193 
SetUserAgent(buf)194 void SetUserAgent(buf)
195    char *buf;
196 {
197    InitUserAgentName();
198    if (buf == NULL || *buf == '\0') {
199       *gszUserAgentName = '\0';
200    } else {
201       UtilStrCpyN(gszUserAgentName, sizeof(gszUserAgentName), buf);
202       UtilTrimBlanks(gszUserAgentName);
203    }
204 }
205 
GetUserID(psz_buf,buf_sz)206 int GetUserID(psz_buf, buf_sz)
207    char *psz_buf;
208    int buf_sz;
209 {
210    char user_name[MAXSTRING+1];
211    int total=0;
212 
213    sprintf(user_name, "%s@", TOOL_NAME);
214    total = strlen(user_name);
215    if (gethostname(&user_name[total], sizeof(user_name)-1-total) < 0) {
216       sprintf(&user_name[total], "UNKNOWN");
217    } else {
218       struct hostent *p_hostent=gethostbyname(&user_name[total]);
219 
220       if (p_hostent != NULL && p_hostent->h_name != NULL &&
221             *p_hostent->h_name != '\0') {
222          if (strchr(p_hostent->h_name, '.') == NULL &&
223                strchr(&user_name[total], '.') != NULL) {
224          } else {
225             strcpy(&user_name[total], p_hostent->h_name);
226          }
227       }
228    }
229    return UtilStrCpyN(psz_buf, buf_sz, user_name);
230 }
231 
UserAbortComm()232 int UserAbortComm()
233 {
234    return CheckInterrupt(TRUE);
235 }
236 
OtherAbortComm()237 int OtherAbortComm()
238 {
239    XEvent ev;
240 
241    if (initializingMain || PRTGIF) return FALSE;
242 
243    while (XCheckMaskEvent(mainDisplay, StructureNotifyMask, &ev)) {
244       if (iconWindowShown) {
245          if ((ev.xany.window == iconBaseWindow && ev.type == UnmapNotify) ||
246                (ev.xany.window == mainWindow && ev.type == MapNotify)) {
247             XPutBackEvent(mainDisplay, &ev);
248             return TRUE;
249          }
250       } else if ((ev.xany.window == iconBaseWindow && ev.type == MapNotify) ||
251             (ev.xany.window == mainWindow && ev.type == UnmapNotify)) {
252          XPutBackEvent(mainDisplay, &ev);
253          return TRUE;
254       } else if (ev.type == ConfigureNotify) {
255          Reconfigure(FALSE);
256       }
257    }
258    while (XCheckMaskEvent(mainDisplay, VisibilityChangeMask, &ev)) {
259       if (iconWindowShown) {
260          if (ev.xany.window == mainWindow && ev.type == VisibilityNotify &&
261                ev.xvisibility.state == VisibilityUnobscured) {
262             XPutBackEvent(mainDisplay, &ev);
263             return TRUE;
264          } else {
265             ExposeEventHandler(&ev, TRUE);
266          }
267       } else {
268          if (ev.xany.window == iconBaseWindow && ev.type == VisibilityNotify &&
269                ev.xvisibility.state == VisibilityUnobscured) {
270             XPutBackEvent(mainDisplay, &ev);
271             return TRUE;
272          } else {
273             ExposeEventHandler(&ev, TRUE);
274          }
275       }
276    }
277    if (XCheckMaskEvent(mainDisplay, ExposureMask, &ev)) {
278       ExposeEventHandler(&ev, TRUE);
279       while (XCheckMaskEvent(mainDisplay, ExposureMask, &ev)) ;
280    }
281    return FALSE;
282 }
283 
GetPageNumFromPageSpec(psz_spec,pn_page_num)284 int GetPageNumFromPageSpec(psz_spec, pn_page_num)
285    char *psz_spec;
286    int *pn_page_num;
287 {
288    if (*psz_spec == '#') {
289       int i=atoi(&psz_spec[1]);
290 
291       if (i >= 1 && i <= lastPageNum) {
292          if (pn_page_num != NULL) *pn_page_num = i;
293          return TRUE;
294       }
295    } else {
296       struct PageRec *page_ptr;
297       int i;
298 
299       if (pn_page_num != NULL) *pn_page_num = (-1);
300       for (i=1, page_ptr=firstPage; i <= lastPageNum; i++,
301             page_ptr=page_ptr->next) {
302          if (page_ptr->name != NULL && strcmp(psz_spec,page_ptr->name) == 0) {
303             if (pn_page_num != NULL) *pn_page_num = i;
304             return TRUE;
305          }
306       }
307    }
308    if (pn_page_num != NULL) *pn_page_num = (-1);
309    return FALSE;
310 }
311 
FreeRemoteBuf(psz_buf)312 void FreeRemoteBuf(psz_buf)
313    char *psz_buf;
314 {
315    TcpFreeBuf(psz_buf);
316 }
317 
318 static
ParseURL(url,protocol,host,port,path)319 int ParseURL(url, protocol, host, port, path)
320    char *url, **protocol, **host, **path;
321    int *port;
322 {
323    char *c_ptr=strchr(url, ':');
324 
325    *protocol = *host = *path = 0;
326    if (c_ptr == NULL) return TG_REMOTE_STATUS_FORMAT;
327 
328    *c_ptr = '\0';
329    *protocol = UtilStrDup(url);
330    *c_ptr++ = ':';
331    if (strncmp(c_ptr, "//", 2) == 0) {
332       char *tmp_host=(&c_ptr[2]), *port_ptr;
333 
334       if ((c_ptr=strchr(tmp_host, '/')) == NULL) {
335          *path = UtilStrDup("");
336       } else {
337          *path = UtilStrDup(c_ptr);
338          *c_ptr = '\0';
339       }
340       if ((port_ptr=strchr(tmp_host, ':')) != NULL) {
341          *port_ptr = '\0';
342          *port = (int)atoi(&port_ptr[1]);
343          *host = UtilStrDup(tmp_host);
344          *port_ptr = ':';
345          if (*port <= 0) {
346             return TG_REMOTE_STATUS_FORMAT;
347          }
348       } else {
349          *host = UtilStrDup(tmp_host);
350       }
351       if (c_ptr != NULL) *c_ptr = '/';
352    } else {
353       *host = UtilStrDup("localhost");
354       *path = UtilStrDup(c_ptr);
355    }
356    return TG_REMOTE_STATUS_OK;
357 }
358 
359 static
DumpURL(host,port,path)360 void DumpURL(host, port, path)
361    char *host, *path;
362    int port;
363 {
364    /* debug, do not translate */
365    fprintf(stderr, "\thost = %s\n", host);
366    fprintf(stderr, "\tport = %1d\n", port);
367    fprintf(stderr, "\tpath = %s\n", path);
368    fprintf(stderr, "\n");
369 }
370 
DirIsRemote(psz_dir)371 int DirIsRemote(psz_dir)
372    char *psz_dir;
373 {
374    int port=0;
375    char *protocol=NULL, *host=NULL, *path=NULL;
376    int status=ParseURL(psz_dir, &protocol, &host, &port, &path), rc=FALSE;
377 
378    if (status == TG_REMOTE_STATUS_OK && protocol != NULL) {
379       if (UtilStrICmp(protocol, "http") == 0 ||
380             UtilStrICmp(protocol, "ftp") == 0) {
381          rc = TRUE;
382       }
383    }
384    if (protocol != NULL) free(protocol);
385    if (host != NULL) free(host);
386    if (path != NULL) free(path);
387    return rc;
388 }
389 
FileIsRemote(psz_file)390 int FileIsRemote(psz_file)
391    char *psz_file;
392 {
393    return DirIsRemote(psz_file);
394 }
395 
UrlIsHtml(psz_url)396 int UrlIsHtml(psz_url)
397    char *psz_url;
398 {
399    char *ext_str=UtilStrRChr(psz_url, (int)'/');
400 
401    if (ext_str == NULL) return FALSE;
402    if ((ext_str=strchr(ext_str, '.')) == NULL) return FALSE;
403    ext_str++;
404    return (UtilStrICmp(ext_str,"html")==0 || UtilStrICmp(ext_str,"htm")==0);
405 }
406 
407 static
FormLocalName(psz_file,psz_def_ext,psz_return)408 int FormLocalName(psz_file, psz_def_ext, psz_return)
409    char *psz_file, *psz_def_ext, *psz_return;
410 {
411    if (psz_def_ext != NULL) {
412       char *slash_ptr=UtilStrRChr(psz_file, (int)DIR_SEP), *dot_ptr=NULL;
413 
414       if (slash_ptr == NULL) {
415          dot_ptr = strchr(psz_file, '.');
416       } else {
417          dot_ptr = strchr(slash_ptr, '.');
418       }
419       if (dot_ptr == NULL) {
420          if (slash_ptr != NULL && slash_ptr[1] == '\0') {
421             sprintf(psz_return, "%s/index.%s", psz_file, psz_def_ext);
422          } else {
423             sprintf(psz_return, "%s.%s", psz_file, psz_def_ext);
424          }
425       } else {
426          strcpy(psz_return, psz_file);
427       }
428    } else {
429       strcpy(psz_return, psz_file);
430    }
431    return UtilShrinkName(psz_return);
432 }
433 
FormRemoteName(psz_file,psz_def_ext,psz_return)434 int FormRemoteName(psz_file, psz_def_ext, psz_return)
435    char *psz_file, *psz_def_ext, *psz_return;
436 {
437    char *c_ptr=strstr(psz_file, "//"), *path;
438 
439    if (c_ptr == NULL) return FALSE;
440    if ((c_ptr=strchr(&c_ptr[2], '/')) == NULL) {
441       if (!FormLocalName("/", psz_def_ext, psz_return)) return FALSE;
442       path = UtilStrDup(psz_return);
443       sprintf(psz_return, "%s%s", psz_file, path);
444       free(path);
445    } else {
446       if (!FormLocalName(c_ptr, psz_def_ext, psz_return)) return FALSE;
447       path = UtilStrDup(psz_return);
448       *c_ptr = '\0';
449       sprintf(psz_return, "%s%s", psz_file, path);
450       free(path);
451       *c_ptr = '/';
452    }
453    return TRUE;
454 }
455 
FormNewFileName(psz_dir,psz_file,psz_def_ext,psz_return,ppsz_page_spec)456 int FormNewFileName(psz_dir, psz_file, psz_def_ext, psz_return, ppsz_page_spec)
457    char *psz_dir, *psz_file, *psz_def_ext, *psz_return, **ppsz_page_spec;
458 {
459    int rc=TRUE;
460 
461    if (ppsz_page_spec != NULL) *ppsz_page_spec = NULL;
462    if (DirIsRemote(psz_dir)) {
463       if (*psz_file == '/') {
464          int len;
465          char *c_ptr=strstr(psz_dir, "//"), *fname=NULL;
466 
467          if (c_ptr == NULL) return FALSE;
468          if ((c_ptr=strchr(&c_ptr[2], '/')) == NULL) return FALSE;
469          *c_ptr = '\0';
470          len = strlen(psz_dir)+strlen(psz_file);
471          fname = (char*)malloc((len+1)*sizeof(char));
472          if (fname == NULL) {
473             *c_ptr = '/';
474             return FailAllocMessage();
475          }
476          sprintf(fname, "%s%s", psz_dir, psz_file);
477          *c_ptr = '/';
478          if (!FormRemoteName(fname, psz_def_ext, psz_return)) rc = FALSE;
479          free(fname);
480       } else if (FileIsRemote(psz_file)) {
481          if (!FormRemoteName(psz_file, psz_def_ext, psz_return)) rc = FALSE;
482       } else {
483          int len=strlen(psz_dir)+1+strlen(psz_file);
484          char *fname=(char*)malloc((len+1)*sizeof(char));
485 
486          if (fname == NULL) return FailAllocMessage();
487 
488          sprintf(fname, "%s/%s", psz_dir, psz_file);
489          if (!FormRemoteName(fname, psz_def_ext, psz_return)) rc = FALSE;
490          free(fname);
491       }
492    } else {
493       if (*psz_file == DIR_SEP) {
494          if (!FormLocalName(psz_file, psz_def_ext, psz_return)) rc = FALSE;
495       } else if (FileIsRemote(psz_file)) {
496          if (!FormRemoteName(psz_file, psz_def_ext, psz_return)) rc = FALSE;
497       } else {
498          int len=strlen(psz_dir)+1+strlen(psz_file);
499          char *fname=(char*)malloc((len+1)*sizeof(char));
500 
501          if (fname == NULL) return FailAllocMessage();
502 
503          sprintf(fname, "%s%c%s", psz_dir, DIR_SEP, psz_file);
504          if (!FormLocalName(fname, psz_def_ext, psz_return)) rc = FALSE;
505          free(fname);
506       }
507    }
508    if (rc && ppsz_page_spec != NULL && psz_return != NULL &&
509          *psz_return != '\0') {
510       char *c_ptr=UtilStrRChr(psz_return, (int)'/');
511 
512       if (c_ptr != NULL) {
513          for (++c_ptr; *c_ptr != '\0'; c_ptr++) {
514             if (*c_ptr == '#') {
515                *c_ptr++ = '\0';
516                *ppsz_page_spec = UtilStrDup(c_ptr);
517             } else if (*c_ptr == '?') {
518                break;
519             }
520          }
521       }
522    }
523    return rc;
524 }
525 
ShowRemoteStatus(psz_msg)526 void ShowRemoteStatus(psz_msg)
527    char *psz_msg;
528 {
529    if (PRTGIF) return;
530    if (serializingFile || deserializingFile) return;
531 
532    SetStringStatus(psz_msg);
533    XSync(mainDisplay, False);
534 }
535 
WriteRemoteFileIntoTemp(psz_buf,buf_sz,psz_ext)536 char *WriteRemoteFileIntoTemp(psz_buf, buf_sz, psz_ext)
537    char *psz_buf, *psz_ext;
538    int buf_sz;
539 {
540    char *tmp_fname=NULL;
541    int fd=(-1);
542    mode_t mode=((tmpFileMode == 0) ? 0700 : tmpFileMode);
543 
544    tmp_fname = (char*)malloc((strlen(tmpDir)+20)*sizeof(char));
545    if (tmp_fname == NULL) {
546       FailAllocMessage();
547       return NULL;
548    }
549    if (MkTempFile(tmp_fname, (strlen(tmpDir)+19)*sizeof(char), tmpDir,
550          TOOL_NAME) == NULL) {
551       free(tmp_fname);
552       return NULL;
553    }
554    if (psz_ext != NULL) strcat(tmp_fname, psz_ext);
555    unlink(tmp_fname);
556    if ((fd=open(tmp_fname, O_WRONLY|O_CREAT|O_TRUNC, mode)) == (-1)) {
557       sprintf(gszMsgBox, TgLoadString(STID_CANT_CREATE_NAMED_TMP_FILE),
558             tmp_fname);
559       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
560       free(tmp_fname);
561       return NULL;
562    } else {
563       int ok=TRUE;
564 
565       if (write(fd, psz_buf, buf_sz) != buf_sz) {
566          sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_WRITE_TO_FILE),
567                tmp_fname);
568          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
569          ok = FALSE;
570       }
571       close(fd);
572       if (!ok) {
573          unlink(tmp_fname);
574          free(tmp_fname);
575          return NULL;
576       }
577       if (tmpFileMode != 0 && chmod(tmp_fname, tmpFileMode)) {
578          sprintf(gszMsgBox, TgLoadString(STID_CANNOT_CHMOD), tmp_fname,
579                tmpFileMode);
580          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
581       }
582       return tmp_fname;
583    }
584 }
585 
586 #define USE_GUNZIP 0
587 #define USE_UNCOMPRESS 1
588 
589 static
TgifCompressedUrl(url)590 int TgifCompressedUrl(url)
591    char *url;
592 {
593    char *ext_ptr=NULL;
594    int len, count=0, obj_len, sym_len, pin_len, uncompress_method=INVALID;
595 
596    if (url == NULL) return uncompress_method;
597    len = strlen(url);
598    for (ext_ptr=(&url[len-1]); ext_ptr != url; ext_ptr--) {
599       if (*ext_ptr == '.') {
600          if (++count == 2) break;
601       }
602    }
603    if (count != 2) return uncompress_method;
604    ext_ptr++;
605    obj_len = strlen(OBJ_FILE_EXT);
606    sym_len = strlen(SYM_FILE_EXT);
607    pin_len = strlen(PIN_FILE_EXT);
608 
609    if (strcmp(ext_ptr,"obj.gz")==0 || strcmp(ext_ptr,"sym.gz")==0 ||
610          strcmp(ext_ptr,"pin.gz")==0) {
611       uncompress_method = USE_GUNZIP;
612    } else if (strcmp(ext_ptr,"obj.Z")==0 || strcmp(ext_ptr,"sym.Z")==0 ||
613          strcmp(ext_ptr,"pin.Z")==0) {
614       uncompress_method = USE_UNCOMPRESS;
615    } else if ((strncmp(ext_ptr,OBJ_FILE_EXT,obj_len)==0 &&
616          strcmp(&ext_ptr[obj_len],".gz")==0) ||
617          (strncmp(ext_ptr,SYM_FILE_EXT,sym_len)==0 &&
618          strcmp(&ext_ptr[sym_len],".gz")==0) ||
619          (strncmp(ext_ptr,PIN_FILE_EXT,pin_len)==0 &&
620          strcmp(&ext_ptr[pin_len],".gz")==0)) {
621       uncompress_method = USE_GUNZIP;
622    } else if ((strncmp(ext_ptr,OBJ_FILE_EXT,obj_len)==0 &&
623          strcmp(&ext_ptr[obj_len],".Z")==0) ||
624          (strncmp(ext_ptr,SYM_FILE_EXT,sym_len)==0 &&
625          strcmp(&ext_ptr[sym_len],".Z")==0) ||
626          (strncmp(ext_ptr,PIN_FILE_EXT,pin_len)==0 &&
627          strcmp(&ext_ptr[pin_len],".Z")==0)) {
628       uncompress_method = USE_UNCOMPRESS;
629    }
630    return uncompress_method;
631 }
632 
633 static
UncompressTgifFile(url,ppsz_buf,pn_buf_sz,pn_html)634 void UncompressTgifFile(url, ppsz_buf, pn_buf_sz, pn_html)
635    char *url, **ppsz_buf;
636    int *pn_buf_sz, *pn_html;
637 {
638    FILE *pfp=NULL;
639    char *uncompress_cmd=NULL, *tmp_fname=NULL, *cmd=NULL;
640    int uncompress_method;
641 
642    if (ppsz_buf == NULL || *ppsz_buf == NULL || pn_buf_sz == NULL ||
643          *pn_buf_sz <= 0) {
644       return;
645    }
646    uncompress_method = TgifCompressedUrl(url);
647 
648    switch (uncompress_method) {
649    case USE_GUNZIP:
650       uncompress_cmd = gunzipCmd;
651       sprintf(gszMsgBox, TgLoadCachedString(CSTID_UNZIPPING_WITH_CMD_DOTS),
652             gunzipCmd);
653       ShowRemoteStatus(gszMsgBox);
654       break;
655    case USE_UNCOMPRESS:
656       uncompress_cmd = uncompressCmd;
657       sprintf(gszMsgBox, TgLoadCachedString(CSTID_UNCOMPRESSING_WITH_CMD_DOTS),
658             uncompressCmd);
659       ShowRemoteStatus(gszMsgBox);
660       break;
661    default: return;
662    }
663    if ((tmp_fname=WriteRemoteFileIntoTemp(*ppsz_buf, *pn_buf_sz,
664          (uncompress_method==USE_UNCOMPRESS ? ".Z" : NULL))) == NULL) {
665       return;
666    }
667    cmd = (char*)malloc((strlen(tmp_fname)+strlen(uncompress_cmd)+20) *
668          sizeof(char));
669    if (cmd == NULL) FailAllocMessage();
670 
671    if (strstr(uncompress_cmd, "%s") == NULL) {
672       sprintf(cmd, "%s %s", uncompress_cmd, tmp_fname);
673    } else {
674       sprintf(cmd, uncompress_cmd, tmp_fname);
675    }
676    if (!FindProgramInPath(cmd, NULL, FALSE)) {
677       free(cmd);
678       unlink(tmp_fname);
679       free(tmp_fname);
680       return;
681    }
682    if ((pfp=(FILE*)popen(cmd, "r")) == NULL) {
683       sprintf(gszMsgBox, TgLoadString(STID_CANNOT_EXECUTE_GIVEN_CMD), cmd);
684       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
685    } else {
686       int buf_sz=0x1000, total=0, chunk_sz=0x1000, bytes_read;
687       char *buf=(char*)malloc((buf_sz+1)*sizeof(char));
688 
689       if (buf == NULL) FailAllocMessage();
690       while (buf != NULL && (bytes_read=fread(&buf[total], sizeof(char),
691             chunk_sz, pfp)) > 0) {
692          total += bytes_read;
693          buf_sz += chunk_sz;
694          buf = (char*)realloc(buf, buf_sz+1);
695       }
696       buf[total] = '\0';
697       pclose(pfp);
698       if (buf != NULL && total > 0) {
699          free(*ppsz_buf);
700          *ppsz_buf = buf;
701          *pn_buf_sz = total;
702       } else if (buf != NULL) {
703          free(buf);
704       }
705    }
706    unlink(tmp_fname);
707    free(tmp_fname);
708    if (cmd != NULL) free(cmd);
709 }
710 
711 static
GetProxyHostAndPort(proxy_spec,def_port,pn_port)712 char *GetProxyHostAndPort(proxy_spec, def_port, pn_port)
713    char *proxy_spec;
714    int def_port, *pn_port;
715 {
716    char *colon_ptr=strchr(proxy_spec, ':'), *return_buf=NULL;
717    int len=(-1);
718 
719    if (colon_ptr == NULL) {
720       len = strlen(proxy_spec);
721       if (len > 0 && proxy_spec[len-1] == '/') {
722          proxy_spec[len-1] = '\0';
723       } else {
724          len = (-1);
725       }
726       *pn_port = def_port;
727       return_buf = UtilStrDup(proxy_spec);
728    } else {
729       *colon_ptr = '\0';
730       len = strlen(proxy_spec);
731       if (len > 0 && proxy_spec[len-1] == '/') {
732          proxy_spec[len-1] = '\0';
733       } else {
734          len = (-1);
735       }
736       *pn_port = atoi(&colon_ptr[1]);
737       return_buf = UtilStrDup(proxy_spec);
738       *colon_ptr = ':';
739    }
740    if (len != (-1)) proxy_spec[len-1] = '/';
741    return return_buf;
742 }
743 
744 static
LoadHttpIntoMem(url,host,port,path,ppsz_buf,ppsz_content_type,pn_buf_sz,pn_html,pn_http_extracted_text)745 int LoadHttpIntoMem(url, host, port, path, ppsz_buf, ppsz_content_type,
746       pn_buf_sz, pn_html, pn_http_extracted_text)
747    char *url, *host, *path, **ppsz_buf, **ppsz_content_type;
748    int port, *pn_buf_sz, *pn_html, *pn_http_extracted_text;
749 {
750    int status=TG_REMOTE_STATUS_OK, n_socket=0, proxy_port=0;
751    char *proxy_host=NULL, port_str[20];
752 
753    if (pn_http_extracted_text != NULL) *pn_http_extracted_text=FALSE;
754    if (port == 0) port = 80;
755    if (debugRemote) DumpURL(host, port, path);
756 
757    ShowInterrupt(1);
758    if (*httpProxy == '\0') {
759       sprintf(port_str, "%1d", port);
760       status = HttpDoConnect(host, port, &n_socket);
761    } else {
762       proxy_host = GetProxyHostAndPort(httpProxy, 80, &proxy_port);
763       sprintf(port_str, "%1d", proxy_port);
764       if (proxy_host == NULL) {
765          status = INVALID;
766       } else {
767          status = HttpDoConnect(proxy_host, proxy_port, &n_socket);
768       }
769    }
770    if (status == TG_REMOTE_STATUS_HOST) {
771       sprintf(gszMsgBox, TgLoadString(STID_CANT_LOCATE_NAMED_SERVER_TRY),
772             "HTTP", (*httpProxy == '\0' ? host : proxy_host));
773       if (PRTGIF) {
774          fprintf(stderr, "%s\n", gszMsgBox);
775       } else {
776          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
777       }
778    } else if (status == TG_REMOTE_STATUS_INTR) {
779       sprintf(gszMsgBox, TgLoadString(STID_CONNECTION_INTERRUPTED), "HTTP");
780       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
781       close(n_socket);
782    } else if (status < 0) {
783       /* n_socket already closed in TcpDoDonnect() */
784       if (*httpProxy == '\0') {
785          sprintf(gszMsgBox, TgLoadString(STID_CANT_CONN_TO_HOST_PORT), "HTTP",
786                host, port==80 ? "" : ":", port==80 ? "" : port_str);
787       } else {
788          sprintf(gszMsgBox, TgLoadString(STID_CANT_CONN_TO_HOST_PORT), "HTTP",
789                proxy_host, proxy_port==80 ? "" : ":",
790                proxy_port==80 ? "" : port_str);
791       }
792       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
793    } else if (status == TG_REMOTE_STATUS_OK) {
794       status = HttpDoWrite(n_socket, (*httpProxy=='\0' ? path : url),
795             host, port);
796       if (status == TG_REMOTE_STATUS_OK) {
797          char *buf=NULL;
798          int buf_sz=0;
799 
800          if ((status=HttpDoRead(n_socket, &buf, &buf_sz)) ==
801                TG_REMOTE_STATUS_OK && buf != NULL && *buf != '\0') {
802             *ppsz_buf = HttpExtractText(buf, pn_buf_sz, pn_html,
803                   ppsz_content_type);
804             if (*ppsz_buf != NULL && pn_buf_sz != NULL &&
805                   ppsz_content_type != NULL) {
806                if (!ParseMarkUpFile(*ppsz_buf, *pn_buf_sz, pn_html,
807                      *ppsz_content_type)) {
808                }
809             }
810             if (*ppsz_buf != NULL && debugHttp > 0) {
811                if ((debugHttp % 100) == 99) {
812                   /*
813                    * Because of the way HttpExtractText() is coded,
814                    * if *ppsz_buf != NULL, (*ppsz_buf)[*pn_buf_sz] is '\0'
815                    * no matter what kind of file it is!
816                    */
817                   if (cmdLineDumpURL) {
818                      (void)fwrite(*ppsz_buf, sizeof(char), (*pn_buf_sz),
819                            stdout);
820                   }
821                }
822             }
823             if (pn_http_extracted_text != NULL) *pn_http_extracted_text = TRUE;
824             FreeRemoteBuf(buf);
825          } else if (status == TG_REMOTE_STATUS_INTR) {
826             sprintf(gszMsgBox, TgLoadString(STID_CONNECTION_INTERRUPTED),
827                   "HTTP");
828             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
829          } else if (buf == NULL || *buf == '\0') {
830             sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_GET_DATA_FROM_URL),
831                   "HTTP", url);
832             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
833          } else {
834             if (*httpProxy == '\0') {
835                sprintf(gszMsgBox,
836                      TgLoadString(STID_NETWORK_ERR_TALK_TO_HOST_PORT),
837                      "HTTP", host, port==80 ? "" : ":",
838                      port==80 ? "" : port_str);
839             } else {
840                sprintf(gszMsgBox,
841                      TgLoadString(STID_NETWORK_ERR_TALK_TO_HOST_PORT),
842                      "HTTP", proxy_host, proxy_port==80 ? "" : ":",
843                      proxy_port==80 ? "" : port_str);
844             }
845             MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
846          }
847       }
848       close(n_socket);
849    } else {
850       if (*httpProxy == '\0') {
851          sprintf(gszMsgBox, TgLoadString(STID_CANT_CONN_TO_HOST_PORT),
852                "HTTP", host, port==80 ? "" : ":", port==80 ? "" : port_str);
853       } else {
854          sprintf(gszMsgBox, TgLoadString(STID_CANT_CONN_TO_HOST_PORT),
855                "HTTP", proxy_host, proxy_port==80 ? "" : ":",
856                proxy_port==80 ? "" : port_str);
857       }
858       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
859    }
860    HideInterrupt();
861    return status;
862 }
863 
864 static
LoadFtpIntoMem(url,host,port,path,ppsz_buf,ppsz_content_type,pn_buf_sz,pn_html)865 int LoadFtpIntoMem(url, host, port, path, ppsz_buf, ppsz_content_type,
866       pn_buf_sz, pn_html)
867    char *url, *host, *path, **ppsz_buf, **ppsz_content_type;
868    int port, *pn_buf_sz, *pn_html;
869 {
870    int status=TG_REMOTE_STATUS_OK, n_socket=0, proxy_port=0;
871    char *proxy_host=NULL, port_str[20];
872 
873    if (port == 0) port = 21;
874    if (debugRemote) DumpURL(host, port, path);
875 
876    ShowInterrupt(1);
877    if (*ftpProxy == '\0') {
878       sprintf(port_str, "%1d", port);
879       status = FtpDoConnect(host, port, &n_socket);
880    } else {
881       proxy_host = GetProxyHostAndPort(ftpProxy, 21, &proxy_port);
882       sprintf(port_str, "%1d", proxy_port);
883       if (proxy_host == NULL) {
884          status = INVALID;
885       } else {
886          status = FtpDoConnect(proxy_host, proxy_port, &n_socket);
887       }
888    }
889    if (status == TG_REMOTE_STATUS_HOST) {
890       sprintf(gszMsgBox, TgLoadString(STID_CANT_LOCATE_NAMED_SERVER_TRY),
891             "FTP", (*ftpProxy == '\0' ? host : proxy_host));
892       if (PRTGIF) {
893          fprintf(stderr, "%s\n", gszMsgBox);
894       } else {
895          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
896       }
897    } else if (status == TG_REMOTE_STATUS_INTR) {
898       sprintf(gszMsgBox, TgLoadString(STID_CONNECTION_INTERRUPTED), "FTP");
899       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
900       close(n_socket);
901    } else if (status < 0) {
902       /* n_socket already closed in TcpDoDonnect() */
903       if (*ftpProxy == '\0') {
904          sprintf(gszMsgBox, TgLoadString(STID_CANT_CONN_TO_HOST_PORT),
905                "FTP", host, port==21 ? "" : ":", port==21 ? "" : port_str);
906       } else {
907          sprintf(gszMsgBox, TgLoadString(STID_CANT_CONN_TO_HOST_PORT),
908                "FTP", proxy_host, proxy_port==21 ? "" : ":",
909                proxy_port==21 ? "" : port_str);
910       }
911       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
912    } else if (status == TG_REMOTE_STATUS_OK) {
913       char *buf=NULL;
914       int buf_sz=0;
915 
916       sprintf(gszMsgBox, TgLoadCachedString(CSTID_SENDING_REQUESTS_DOTS),
917             "FTP");
918       ShowRemoteStatus(gszMsgBox);
919       if (((status=FtpDoTalk(n_socket, (*ftpProxy=='\0' ? path : url),
920             &buf, &buf_sz))&(~FTP_LOGGED_IN)) == TG_REMOTE_STATUS_OK &&
921             buf != NULL && *buf != '\0') {
922          *ppsz_buf = buf;
923          if (pn_buf_sz != NULL) *pn_buf_sz = buf_sz;
924          if (*ppsz_buf != NULL && pn_buf_sz != NULL && debugFtp == -99) {
925             /*
926              * Because of the way FtpDoTalk() is coded,
927              * if *ppsz_buf != NULL, (*ppsz_buf)[*pn_buf_sz] is '\0'
928              * no matter what kind of file it is!
929              */
930             if (cmdLineDumpURL) {
931                (void)fwrite(*ppsz_buf, sizeof(char), (*pn_buf_sz), stdout);
932             }
933          }
934          sprintf(gszMsgBox, TgLoadCachedString(CSTID_DATA_RECEIVED), "FTP");
935          ShowRemoteStatus(gszMsgBox);
936       } else if ((status & (~FTP_LOGGED_IN)) == TG_REMOTE_STATUS_INTR) {
937          sprintf(gszMsgBox, TgLoadString(STID_CONNECTION_INTERRUPTED), "FTP");
938          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
939       } else if (status & FTP_LOGGED_IN) {
940          sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_GET_DATA_FROM_URL),
941                "FTP", url);
942          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
943       } else {
944          if (*ftpProxy == '\0') {
945             sprintf(gszMsgBox, TgLoadString(STID_FAILED_TO_LOGIN_TO_HOST_PORT),
946                   "FTP", host, port==21 ? "" : ":", port==21 ? "" : port_str);
947          } else {
948             sprintf(gszMsgBox, TgLoadString(STID_FAILED_TO_LOGIN_TO_HOST_PORT),
949                   "FTP", proxy_host, proxy_port==21 ? "" : ":",
950                   proxy_port==21 ? "" : port_str);
951          }
952          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
953       }
954       close(n_socket);
955    } else {
956       if (*ftpProxy == '\0') {
957          sprintf(gszMsgBox, TgLoadString(STID_CANT_CONN_TO_HOST_PORT),
958                "FTP", host, port==21 ? "" : ":", port==21 ? "" : port_str);
959       } else {
960          sprintf(gszMsgBox, TgLoadString(STID_CANT_CONN_TO_HOST_PORT),
961                "FTP", proxy_host, proxy_port==21 ? "" : ":",
962                proxy_port==21 ? "" : port_str);
963       }
964       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
965    }
966    HideInterrupt();
967    return status;
968 }
969 
970 static
ResetRemoteBuf(ppsz_buf,ppsz_content_type,pn_buf_sz,pn_html)971 void ResetRemoteBuf(ppsz_buf, ppsz_content_type, pn_buf_sz, pn_html)
972    char **ppsz_buf, **ppsz_content_type;
973    int *pn_buf_sz, *pn_html;
974 {
975    if (ppsz_buf != NULL && *ppsz_buf != NULL) {
976       free(*ppsz_buf);
977       *ppsz_buf = NULL;
978    }
979    if (ppsz_content_type != NULL && *ppsz_content_type != NULL) {
980       free(*ppsz_content_type);
981       *ppsz_content_type = NULL;
982    }
983    if (pn_buf_sz != NULL) *pn_buf_sz = 0;
984    if (pn_html != NULL) *pn_html = FALSE;
985 }
986 
987 static int gnForwardCount=0;
988 static int gnAuthCount=0;
989 
990 static
LoadForwardedFileInMem(url,ppsz_buf,ppsz_content_type,pn_buf_sz,pn_html,force_load,psz_final_url,cb_final_url)991 int LoadForwardedFileInMem(url, ppsz_buf, ppsz_content_type, pn_buf_sz,
992       pn_html, force_load, psz_final_url, cb_final_url)
993    char *url, **ppsz_buf, **ppsz_content_type, *psz_final_url;
994    int *pn_buf_sz, *pn_html, force_load, cb_final_url;
995 {
996    char *location=HttpHeaderGetLocation(), *dup_location;
997    int rc=TRUE;
998 
999    if (location == NULL) {
1000       sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_LOCATION_IN_HDR),
1001             "HTTP", url);
1002       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1003       return TRUE;
1004    }
1005 
1006    if (gnForwardCount >= 5) {
1007       sprintf(gszMsgBox, TgLoadString(STID_LNK_FWD_5_TIMES_LOAD_ABORT),
1008             "HTTP", url);
1009       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1010       return TRUE;
1011    }
1012    dup_location = UtilStrDup(location);
1013    if (dup_location == NULL) {
1014       FailAllocMessage();
1015       return TRUE;
1016    }
1017    if (psz_final_url != NULL && cb_final_url > 0) {
1018       UtilStrCpyN(psz_final_url, cb_final_url, dup_location);
1019    }
1020    sprintf(gszMsgBox, TgLoadCachedString(CSTID_FORWARDING_URL_TO_URL),
1021          "HTTP", url, location);
1022    Msg(gszMsgBox);
1023    ShowRemoteStatus(gszMsgBox);
1024    /*
1025     * After calling ResetRemoteBuf(),
1026     *     can only return TRUE if buffer is filled.
1027     */
1028    ResetRemoteBuf(ppsz_buf, ppsz_content_type, pn_buf_sz, pn_html);
1029    gnForwardCount++;
1030    rc = LoadRemoteFileInMem(dup_location, ppsz_buf, ppsz_content_type,
1031          pn_buf_sz, pn_html, force_load, psz_final_url, cb_final_url);
1032    gnForwardCount--;
1033    free(dup_location);
1034    return rc;
1035 }
1036 
1037 static
ParseAuthFields(psz_scheme)1038 char *ParseAuthFields(psz_scheme)
1039    char *psz_scheme;
1040 {
1041    char *realm_ptr, *realm_value;
1042 
1043    UtilTrimBlanks(psz_scheme);
1044    realm_ptr = strchr(psz_scheme, ' ');
1045    if (realm_ptr != NULL) {
1046       *realm_ptr++ = '\0';
1047       while (*realm_ptr == ' ') {
1048          realm_ptr++;
1049       }
1050       if (*realm_ptr == '\0') {
1051          return NULL;
1052       } else if ((realm_value=strchr(realm_ptr, '=')) != NULL) {
1053          return ++realm_value;
1054       }
1055    }
1056    return NULL;
1057 }
1058 
1059 static
LoadAuthenticatedFileInMem(url,host,port,ppsz_buf,ppsz_content_type,pn_buf_sz,pn_html,force_load)1060 int LoadAuthenticatedFileInMem(url, host, port, ppsz_buf, ppsz_content_type,
1061       pn_buf_sz, pn_html, force_load)
1062    char *url, *host, **ppsz_buf, **ppsz_content_type;
1063    int port, *pn_buf_sz, *pn_html, force_load;
1064 {
1065    char *www_authenticate=HttpHeaderGetWWWAuthentication();
1066    char *scheme=NULL, *realm=NULL, *encoded_auth=NULL;
1067    int rc=TRUE;
1068 
1069    if (www_authenticate == NULL) {
1070       sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_WWW_AUTHEN_IN_HDR),
1071             "HTTP", url);
1072       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1073       return TRUE;
1074    }
1075    scheme = UtilStrDup(www_authenticate);
1076    if (scheme == NULL) {
1077       FailAllocMessage();
1078       return TRUE;
1079    }
1080    if ((realm=ParseAuthFields(scheme)) == NULL) {
1081       free(scheme);
1082       return TRUE;
1083    }
1084    /* realm has double-quotes around it */
1085    if ((encoded_auth=FindAuthorization(host, port, scheme, realm)) != NULL) {
1086       /* committed authorization is cached */
1087       /*
1088        * After calling ResetRemoteBuf(),
1089        *     can only return TRUE if buffer is filled.
1090        */
1091       ResetRemoteBuf(ppsz_buf, ppsz_content_type, pn_buf_sz, pn_html);
1092       SetAuthorization(host, port, scheme, realm, encoded_auth);
1093       gnAuthCount++;
1094       rc = LoadRemoteFileInMem(url, ppsz_buf, ppsz_content_type, pn_buf_sz,
1095             pn_html, force_load, NULL, 0);
1096       gnAuthCount--;
1097       ResetAuthorization();
1098    } else {
1099       char *psz=NULL, user_name[MAXSTRING+1], password[MAXSTRING+1];
1100 
1101       *user_name = *password = '\0';
1102       sprintf(gszMsgBox, TgLoadString(STID_AUTHEN_REQ_FOR_REALM),
1103             "HTTP", realm);
1104       ShowRemoteStatus(gszMsgBox);
1105       sprintf(gszMsgBox, TgLoadString(STID_ENTER_USERNAME_FOR_REALM), realm);
1106       if (mainDisplay == NULL) {
1107          fprintf(stdout, "%s ", gszMsgBox);
1108          fflush(stdout);
1109          psz = UtilGetALine(stdin);
1110          if (psz != NULL) {
1111             UtilStrCpyN(user_name, sizeof(user_name), psz);
1112             UtilFree(psz);
1113          }
1114       } else {
1115          Dialog(gszMsgBox, TgLoadCachedString(CSTID_DLG_ACCEPT_CANCEL),
1116                user_name);
1117       }
1118       UtilTrimBlanks(user_name);
1119       if (*user_name != '\0') {
1120          *password = '\0';
1121          sprintf(gszMsgBox, TgLoadString(STID_ENTER_PASSWORD_FOR_REALM), realm);
1122          doPassword = TRUE;
1123          if (mainDisplay == NULL) {
1124             fprintf(stdout, "%s ", gszMsgBox);
1125             fflush(stdout);
1126             psz = UtilGetALine(stdin);
1127             if (psz != NULL) {
1128                UtilStrCpyN(password, sizeof(password), psz);
1129                UtilFree(psz);
1130             }
1131          } else {
1132             Dialog(gszMsgBox, NULL, password);
1133          }
1134          doPassword = FALSE;
1135       }
1136       if (*user_name != '\0' && *password != '\0') {
1137          char *tmp_auth;
1138 
1139          sprintf(gszMsgBox, "%s:%s", user_name, password);
1140          if ((tmp_auth=UtilStrDup(gszMsgBox)) == NULL) FailAllocMessage();
1141          if ((encoded_auth=Base64Encode(tmp_auth)) == NULL) FailAllocMessage();
1142          free(tmp_auth);
1143          if (!SetAuthorization(host, port, scheme, realm, encoded_auth)) {
1144             FailAllocMessage();
1145          } else {
1146             /*
1147              * After calling ResetRemoteBuf(),
1148              *     can only return TRUE if buffer is filled.
1149              */
1150             ResetRemoteBuf(ppsz_buf, ppsz_content_type, pn_buf_sz, pn_html);
1151             SetAuthorization(host, port, scheme, realm, encoded_auth);
1152             gnAuthCount++;
1153             rc = LoadRemoteFileInMem(url, ppsz_buf, ppsz_content_type,
1154                   pn_buf_sz, pn_html, force_load, NULL, 0);
1155             gnAuthCount--;
1156             ResetAuthorization();
1157          }
1158          free(encoded_auth);
1159       }
1160    }
1161    free(scheme);
1162    return rc;
1163 }
1164 
LoadRemoteFileInMem(url,ppsz_buf,ppsz_content_type,pn_buf_sz,pn_html,force_load,psz_final_url,cb_final_url)1165 int LoadRemoteFileInMem(url, ppsz_buf, ppsz_content_type, pn_buf_sz, pn_html,
1166       force_load, psz_final_url, cb_final_url)
1167    char *url, **ppsz_buf, **ppsz_content_type, *psz_final_url;
1168    int *pn_buf_sz, *pn_html, force_load, cb_final_url;
1169    /* if the remote type is http, the url has an extension and it */
1170    /*       is not html but the retrieved file is html, then it's */
1171    /*       probably an error */
1172 {
1173    int status=0, rc;
1174    int port=0, protocol_is_http=FALSE, http_extracted_text=FALSE;
1175    char *protocol=NULL, *host=NULL, *path=NULL, *proxy_host=NULL;
1176    char port_str[20];
1177    struct URLCacheRec *url_cache=NULL;
1178 
1179    *port_str = '\0';
1180    if (pn_buf_sz != NULL) *pn_buf_sz = 0;
1181    if (pn_html != NULL) *pn_html = FALSE;
1182    *ppsz_buf = NULL;
1183 
1184    if (!force_load) url_cache = FindURLCache(url, TRUE);
1185    if (url_cache != NULL && url_cache->remote_buf_sz > 0 &&
1186          url_cache->remote_buf != NULL) {
1187       *ppsz_buf = (char*)malloc((url_cache->remote_buf_sz)*sizeof(char));
1188       if (*ppsz_buf == NULL) FailAllocMessage();
1189       memcpy(*ppsz_buf, url_cache->remote_buf, url_cache->remote_buf_sz);
1190       *pn_buf_sz = url_cache->remote_buf_sz;
1191       if (ppsz_content_type != NULL) {
1192          *ppsz_content_type = UtilStrDup(url_cache->content_type);
1193       }
1194       *pn_html = url_cache->is_html;
1195       return TRUE;
1196    }
1197    status = ParseURL(url, &protocol, &host, &port, &path);
1198    if (status != TG_REMOTE_STATUS_OK) {
1199       if (protocol != NULL) free(protocol);
1200       if (host != NULL) free(host);
1201       if (path != NULL) free(path);
1202       sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_PARSE_GIVEN_URL), url);
1203       if (PRTGIF) {
1204          fprintf(stderr, "%s\n", gszMsgBox);
1205       } else {
1206          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1207       }
1208       return FALSE;
1209    }
1210    if (UtilStrICmp(protocol, "http") == 0) {
1211       protocol_is_http = TRUE;
1212       status = LoadHttpIntoMem(url, host, port, path, ppsz_buf,
1213             ppsz_content_type, pn_buf_sz, pn_html, &http_extracted_text);
1214    } else if (UtilStrICmp(protocol, "ftp") == 0) {
1215       status = LoadFtpIntoMem(url, host, port, path, ppsz_buf,
1216             ppsz_content_type, pn_buf_sz, pn_html);
1217    } else {
1218       if (debugRemote) DumpURL(host, port, path);
1219       sprintf(gszMsgBox, TgLoadString(STID_TOOL_NOT_KNOW_HOW_TALK_PROTO),
1220             protocol);
1221       if (PRTGIF) {
1222          fprintf(stderr, "%s\n", gszMsgBox);
1223       } else {
1224          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1225       }
1226       status = TG_REMOTE_STATUS_FORMAT;
1227    }
1228    rc = TRUE;
1229    if (status==TG_REMOTE_STATUS_OK && protocol_is_http && http_extracted_text) {
1230       int resp_code=HttpHeaderGetResponseCode();
1231 
1232       switch (resp_code) {
1233       case 301:
1234       case 302:
1235          rc = LoadForwardedFileInMem(url, ppsz_buf, ppsz_content_type,
1236                pn_buf_sz, pn_html, force_load, psz_final_url, cb_final_url);
1237          break;
1238       case 401:
1239          rc = LoadAuthenticatedFileInMem(url, host, port,
1240                ppsz_buf, ppsz_content_type, pn_buf_sz, pn_html, force_load);
1241          break;
1242       default:
1243          if (gnAuthCount > 0) {
1244             /* password verified? */
1245             CommitAuthorization();
1246          }
1247          break;
1248       }
1249    }
1250    if (status == TG_REMOTE_STATUS_OK) {
1251       UncompressTgifFile(url, ppsz_buf, pn_buf_sz, pn_html);
1252       UpdateURLCache(url, *ppsz_buf,
1253             (ppsz_content_type==NULL ? NULL : *ppsz_content_type),
1254             *pn_buf_sz, *pn_html);
1255    }
1256    if (protocol != NULL) free(protocol);
1257    if (host != NULL) free(host);
1258    if (path != NULL) free(path);
1259    if (proxy_host != NULL) free(proxy_host);
1260    return rc;
1261 }
1262 
1263 static
LaunchViewer(launch_remote_file,psz_viewer,psz_url,psz_new_fname)1264 void LaunchViewer(launch_remote_file, psz_viewer, psz_url,
1265       psz_new_fname)
1266    int launch_remote_file;
1267    char *psz_viewer, *psz_url, *psz_new_fname;
1268 {
1269    if (strcmp(psz_viewer, "NONE") != 0) {
1270 #ifndef _BACKGROUND_DONT_FORK
1271       int pid=0;
1272 #endif /* ~_BACKGROUND_DONT_FORK */
1273       char cmd[MAXSTRING<<2];
1274 
1275       if (launch_remote_file) {
1276          sprintf(cmd, psz_viewer, psz_url);
1277       } else {
1278          sprintf(cmd, psz_viewer, psz_new_fname);
1279       }
1280       sprintf(gszMsgBox, TgLoadString(STID_LAUNCH_GIVEN_VIEWER), cmd);
1281       Msg(gszMsgBox);
1282       ShowRemoteStatus(gszMsgBox);
1283 
1284 #ifdef _BACKGROUND_DONT_FORK
1285       strcat(cmd, " &");
1286       (void)system(cmd);
1287 #else /* ~_BACKGROUND_DONT_FORK */
1288       pid = fork();
1289       if (pid == 0) {
1290          (void)system(cmd);
1291          exit(0);
1292       }
1293 #endif /* _BACKGROUND_DONT_FORK */
1294    } else {
1295       sprintf(gszMsgBox, TgLoadString(STID_FILE_SAVED), psz_new_fname);
1296       Msg(gszMsgBox);
1297    }
1298 }
1299 
1300 struct MimeTypeRec {
1301    char *main_type, *sub_type;
1302    struct MimeTypeRec *next;
1303 };
1304 
1305 struct MailCapRec {
1306    char *main_type, *sub_type;
1307    char *cmd, *params;
1308    struct MailCapRec *next, *prev;
1309 };
1310 
1311 static struct MimeTypeRec *topMimeTypesInfo=NULL;
1312 static struct MailCapRec *topMailCapInfo=NULL, *botMailCapInfo=NULL;
1313 
1314 static
AddAMimeType(main_type,sub_type)1315 void AddAMimeType(main_type, sub_type)
1316    char *main_type, *sub_type;
1317 {
1318    struct MimeTypeRec *mime_type_ptr;
1319 
1320    mime_type_ptr = (struct MimeTypeRec *)malloc(sizeof(struct MimeTypeRec));
1321    if (mime_type_ptr == NULL) { FailAllocMessage(); return; }
1322    memset(mime_type_ptr, 0, sizeof(struct MimeTypeRec));
1323    mime_type_ptr->main_type = UtilStrDup(main_type);
1324    mime_type_ptr->sub_type = UtilStrDup(sub_type);
1325    mime_type_ptr->next = topMimeTypesInfo;
1326    topMimeTypesInfo = mime_type_ptr;
1327 }
1328 
1329 static
AddAMailCap(main_type,sub_type,cmd,params)1330 void AddAMailCap(main_type, sub_type, cmd, params)
1331    char *main_type, *sub_type, *cmd, *params;
1332 {
1333    struct MailCapRec *mail_cap_ptr;
1334 
1335    mail_cap_ptr = (struct MailCapRec *)malloc(sizeof(struct MailCapRec));
1336    if (mail_cap_ptr == NULL) { FailAllocMessage(); return; }
1337    memset(mail_cap_ptr, 0, sizeof(struct MailCapRec));
1338    mail_cap_ptr->main_type = UtilStrDup(main_type);
1339    mail_cap_ptr->sub_type = UtilStrDup(sub_type);
1340    mail_cap_ptr->cmd = UtilStrDup(cmd);
1341    mail_cap_ptr->params = (params==NULL ? NULL : UtilStrDup(params));
1342    mail_cap_ptr->prev = botMailCapInfo;
1343    mail_cap_ptr->next = NULL;
1344    if (botMailCapInfo == NULL) {
1345       topMailCapInfo = mail_cap_ptr;
1346    } else {
1347       botMailCapInfo->next = mail_cap_ptr;
1348    }
1349    botMailCapInfo = mail_cap_ptr;
1350 }
1351 
1352 static
FreeMimeTypesInfo()1353 void FreeMimeTypesInfo()
1354 {
1355    struct MimeTypeRec *next_mime_type_ptr;
1356 
1357    for ( ; topMimeTypesInfo != NULL; topMimeTypesInfo=next_mime_type_ptr) {
1358       next_mime_type_ptr = topMimeTypesInfo->next;
1359       if (topMimeTypesInfo->main_type!=NULL) free(topMimeTypesInfo->main_type);
1360       if (topMimeTypesInfo->sub_type!=NULL) free(topMimeTypesInfo->sub_type);
1361       free(topMimeTypesInfo);
1362    }
1363 }
1364 
1365 static
FreeMailCapInfo()1366 void FreeMailCapInfo()
1367 {
1368    struct MailCapRec *next_mail_cap_ptr;
1369 
1370    for ( ; topMailCapInfo != NULL; topMailCapInfo=next_mail_cap_ptr) {
1371       next_mail_cap_ptr = topMailCapInfo->next;
1372       if (topMailCapInfo->main_type != NULL) free(topMailCapInfo->main_type);
1373       if (topMailCapInfo->sub_type != NULL) free(topMailCapInfo->sub_type);
1374       if (topMailCapInfo->cmd != NULL) free(topMailCapInfo->cmd);
1375       if (topMailCapInfo->params != NULL) free(topMailCapInfo->params);
1376       free(topMailCapInfo);
1377    }
1378    botMailCapInfo = NULL;
1379 }
1380 
1381 static
DumpMimeTypesInfo()1382 void DumpMimeTypesInfo()
1383 {
1384    struct MimeTypeRec *mime_type_ptr;
1385 
1386    /* do not translate -- program constants */
1387    fprintf(stderr, "***  Mime Types  ***\n");
1388    for (mime_type_ptr=topMimeTypesInfo; mime_type_ptr != NULL;
1389          mime_type_ptr=mime_type_ptr->next) {
1390       fprintf(stderr, "%s/%s\n",
1391             mime_type_ptr->main_type != NULL ? mime_type_ptr->main_type : "",
1392             mime_type_ptr->sub_type != NULL ? mime_type_ptr->sub_type : "");
1393    }
1394    fprintf(stderr, "\n");
1395 }
1396 
1397 static
DumpMailCapInfo()1398 void DumpMailCapInfo()
1399 {
1400    struct MailCapRec *mail_cap_ptr;
1401 
1402    /* do not translate -- program constants */
1403    fprintf(stderr, "***  Mail Capabilities  ***\n");
1404    for (mail_cap_ptr=topMailCapInfo; mail_cap_ptr != NULL;
1405          mail_cap_ptr=mail_cap_ptr->next) {
1406       fprintf(stderr, "%s/%s; %s; %s\n",
1407             mail_cap_ptr->main_type != NULL ? mail_cap_ptr->main_type : "",
1408             mail_cap_ptr->sub_type != NULL ? mail_cap_ptr->sub_type : "",
1409             mail_cap_ptr->cmd != NULL ? mail_cap_ptr->cmd : "",
1410             mail_cap_ptr->params != NULL ? mail_cap_ptr->params : "");
1411    }
1412    fprintf(stderr, "\n");
1413 }
1414 
1415 static
FillMimeTypesInfo()1416 void FillMimeTypesInfo()
1417 {
1418    char *c_ptr, *buf, fname[MAXPATHLENGTH+1];
1419    FILE *fp;
1420    int line_num=0;
1421 
1422    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"MimeTypesFile")) != NULL) {
1423       strcpy(fname, c_ptr);
1424    } else {
1425       sprintf(fname, "%s%c.mime.types", homeDir, DIR_SEP);
1426    }
1427    if ((fp=fopen(fname, "r")) == NULL) return;
1428    while ((buf=UtilGetALine(fp)) != NULL) {
1429       line_num++;
1430       if (*buf != '#') {
1431          char *c_ptr1=strtok(buf, " \t\n\r");
1432 
1433          if (c_ptr1 != NULL && *c_ptr1 != '\0') {
1434             int ok=TRUE;
1435             char *sub_type=NULL;
1436 
1437             if ((sub_type=strchr(c_ptr1, '/')) == NULL) {
1438                ok = FALSE;
1439             } else {
1440                *sub_type++ = '\0';
1441                if (*sub_type == '\0') ok = FALSE;
1442                if (*c_ptr1 == '*') ok = FALSE;
1443             }
1444             if (!ok) {
1445                sprintf(gszMsgBox,
1446                      TgLoadCachedString(CSTID_MALFORMED_LINE_NUM_IN_FILE),
1447                      line_num, fname);
1448                Msg(gszMsgBox);
1449             } else {
1450                AddAMimeType(c_ptr1, sub_type);
1451             }
1452          }
1453       }
1454       free(buf);
1455    }
1456    fclose(fp);
1457    if (debugRemote) DumpMimeTypesInfo();
1458 }
1459 
1460 static
FillMailCapInfo()1461 void FillMailCapInfo()
1462 {
1463    char *spec=NULL, *fname=NULL, *colon_ptr=NULL, *c_ptr=NULL;
1464 
1465    if ((c_ptr=getenv("MAILCAPS")) != NULL) {
1466       spec = UtilStrDup(c_ptr);
1467    } else {
1468       sprintf(gszMsgBox, "%s%c.mailcap", homeDir, DIR_SEP);
1469       spec = UtilStrDup(gszMsgBox);
1470    }
1471    if (spec == NULL) FailAllocMessage();
1472 
1473    fname = spec;
1474    colon_ptr = strchr(fname, ':');
1475    while (fname != NULL) {
1476       if (colon_ptr != NULL) *colon_ptr = '\0';
1477       if (*fname != '\0') {
1478          FILE *fp=NULL;
1479 
1480          if ((fp=fopen(fname, "r")) == NULL) {
1481             sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_GIVEN_MAILCAP_FILE),
1482                   fname);
1483             Msg(gszMsgBox);
1484          } else {
1485             int line_num=0;
1486             char *buf=NULL;
1487 
1488             while ((buf=UtilGetAContinuedLine(fp)) != NULL) {
1489                line_num++;
1490                UtilTrimBlanks(buf);
1491                if (*buf != '\0' && *buf != '#') {
1492                   char *first_semi_ptr=strchr(buf, ';');
1493                   char *second_semi_ptr=NULL, *sub_type=NULL;
1494                   int ok=TRUE;
1495 
1496                   if (first_semi_ptr == NULL) {
1497                      ok = FALSE;
1498                   } else {
1499                      *first_semi_ptr++ = '\0';
1500                      while (*first_semi_ptr == ' ' && *first_semi_ptr == '\t') {
1501                         first_semi_ptr++;
1502                      }
1503                      second_semi_ptr = strchr(first_semi_ptr, ';');
1504                      if (second_semi_ptr != NULL) {
1505                         *second_semi_ptr++ = '\0';
1506                      }
1507                      if ((sub_type=strchr(buf, '/')) == NULL) {
1508                         ok = FALSE;
1509                      } else {
1510                         *sub_type++ = '\0';
1511                      }
1512                   }
1513                   if (!ok) {
1514                      sprintf(gszMsgBox,
1515                            TgLoadCachedString(CSTID_MALFORMED_LINE_NUM_IN_FILE),
1516                            line_num, fname);
1517                      Msg(gszMsgBox);
1518                   } else {
1519                      if (first_semi_ptr!=NULL) UtilTrimBlanks(first_semi_ptr);
1520                      if (second_semi_ptr!=NULL) UtilTrimBlanks(second_semi_ptr);
1521                      AddAMailCap(buf, sub_type, first_semi_ptr,
1522                            second_semi_ptr);
1523                   }
1524                }
1525                free(buf);
1526             }
1527             fclose(fp);
1528          }
1529       }
1530       if (colon_ptr == NULL) break;
1531       *colon_ptr++ = ':';
1532       fname = colon_ptr;
1533       colon_ptr = strchr(fname, ':');
1534    }
1535    UtilFree(spec);
1536    if (debugRemote) DumpMailCapInfo();
1537 }
1538 
1539 static
MalformedMailCapEntryMessage(mail_cap_ptr)1540 void MalformedMailCapEntryMessage(mail_cap_ptr)
1541    struct MailCapRec *mail_cap_ptr;
1542 {
1543    if (mail_cap_ptr->params == NULL) {
1544       sprintf(gszMsgBox, TgLoadString(STID_MALFORMED_MAILCAP_ENTRY),
1545             mail_cap_ptr->main_type, mail_cap_ptr->sub_type, mail_cap_ptr->cmd);
1546    } else {
1547       sprintf(gszMsgBox, TgLoadString(STID_MALFORMED_MAILCAP_ENTRY_PARAM),
1548             mail_cap_ptr->main_type, mail_cap_ptr->sub_type, mail_cap_ptr->cmd,
1549             mail_cap_ptr->params);
1550    }
1551    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1552 }
1553 
1554 static
GetContentValue(name,params)1555 char *GetContentValue(name, params)
1556    char *name, *params;
1557 {
1558    char *buf, *c_ptr;
1559 
1560    if (params == NULL) return NULL;
1561 
1562    buf = UtilStrDup(params);
1563    if (buf == NULL) { FailAllocMessage(); return NULL; }
1564    for (c_ptr=strtok(buf, ";"); c_ptr != NULL; c_ptr=strtok(NULL, ";")) {
1565       char *equal_ptr=strchr(c_ptr, '-');
1566 
1567       if (equal_ptr != NULL) {
1568          char *c_ptr1=c_ptr;
1569 
1570          while (*c_ptr1 == ' ' || *c_ptr1 == '\t') c_ptr1++;
1571          *equal_ptr = '\0';
1572          if (UtilStrICmp(c_ptr1, name) == 0) {
1573             char *return_buf=UtilStrDup(&equal_ptr[1]);
1574 
1575             free(buf);
1576             return return_buf;
1577          }
1578          *equal_ptr = '=';
1579       }
1580    }
1581    free(buf);
1582    return NULL;
1583 }
1584 
1585 static int mimeViewerInitialized=FALSE;
1586 
1587 static
GetMimeViewer(psz_content_type)1588 char *GetMimeViewer(psz_content_type)
1589    char *psz_content_type;
1590 {
1591    struct MailCapRec *mail_cap_ptr;
1592    struct MimeTypeRec *mime_type_ptr;
1593    char *main_type=UtilStrDup(psz_content_type), *sub_type=NULL;
1594    char *params=NULL, *buf=NULL, *c_ptr;
1595    int buf_sz=0, buf_index=0;
1596 
1597    if (main_type == NULL) { FailAllocMessage(); return NULL; }
1598    UtilTrimBlanks(main_type);
1599    params = strchr(main_type, ';');
1600    if (params != NULL) *params++ = '\0';
1601 
1602    if (UtilStrICmp(main_type, "application/x-tgif") == 0) {
1603       free(main_type);
1604       return NULL;
1605    }
1606    sub_type = strchr(main_type, '/');
1607    if (sub_type == NULL) { free(main_type); return NULL; }
1608    *sub_type++ = '\0';
1609    if (UtilStrICmp(main_type, "multipart") == 0) {
1610       free(main_type);
1611       sprintf(gszMsgBox, TgLoadString(STID_TOOL_CANT_HANDLE_MP_MIME),
1612             TOOL_NAME);
1613       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1614       return NULL;
1615    }
1616 
1617    if (!mimeViewerInitialized) {
1618       mimeViewerInitialized = TRUE;
1619       FillMimeTypesInfo();
1620       FillMailCapInfo();
1621    }
1622    for (mime_type_ptr=topMimeTypesInfo; mime_type_ptr != NULL;
1623          mime_type_ptr=mime_type_ptr->next) {
1624       if (UtilStrICmp(main_type, mime_type_ptr->main_type) == 0) {
1625          if (strcmp(mime_type_ptr->sub_type, "*") == 0) {
1626             break;
1627          } else if (UtilStrICmp(sub_type, mime_type_ptr->sub_type) == 0) {
1628             break;
1629          }
1630       }
1631    }
1632    if (mime_type_ptr == NULL) { free(main_type); return NULL; }
1633 
1634    for (mail_cap_ptr=topMailCapInfo; mail_cap_ptr != NULL;
1635          mail_cap_ptr=mail_cap_ptr->next) {
1636       if (UtilStrICmp(main_type, mail_cap_ptr->main_type) == 0) {
1637          if (strcmp(mail_cap_ptr->sub_type, "*") == 0) {
1638             break;
1639          } else if (UtilStrICmp(sub_type, mail_cap_ptr->sub_type) == 0) {
1640             break;
1641          }
1642       }
1643    }
1644    free(main_type);
1645    if (mail_cap_ptr == NULL) return NULL;
1646 
1647    buf_sz = 0x100;
1648    buf = (char*)malloc((buf_sz+1)*sizeof(char));
1649    if (buf == NULL) { FailAllocMessage(); return NULL; }
1650    c_ptr = mail_cap_ptr->cmd;
1651    while (*c_ptr != '\0') {
1652       if (*c_ptr == '\\' && c_ptr[1] == '\0') {
1653          MalformedMailCapEntryMessage(mail_cap_ptr);
1654          free(buf);
1655          return NULL;
1656       }
1657       if (*c_ptr == '%') {
1658          char *tmp_buf=NULL, *right_bracket;
1659          int num_ch_to_skip=(-1), len;
1660 
1661          switch (c_ptr[1]) {
1662          case 's': tmp_buf=UtilStrDup("%s"); num_ch_to_skip=2; break;
1663          case 'S': tmp_buf=UtilStrDup("%S"); num_ch_to_skip=2; break;
1664          case 't':
1665             len = strlen(main_type)+strlen(sub_type)+1;
1666             tmp_buf = (char*)malloc((len+1)*sizeof(char));
1667             if (tmp_buf == NULL) FailAllocMessage();
1668             sprintf(tmp_buf, "%s/%s", main_type, sub_type);
1669             num_ch_to_skip = 2;
1670             break;
1671          case '{':
1672             if ((right_bracket=strchr(&c_ptr[2], '}')) == NULL) {
1673                if (mail_cap_ptr->params == NULL) {
1674                   sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_RT_BRACK_MC),
1675                         mail_cap_ptr->main_type, mail_cap_ptr->sub_type,
1676                         mail_cap_ptr->cmd);
1677                } else {
1678                   sprintf(gszMsgBox,
1679                         TgLoadString(STID_CANT_FIND_RT_BRACK_MC_PARAM),
1680                         mail_cap_ptr->main_type, mail_cap_ptr->sub_type,
1681                         mail_cap_ptr->cmd, mail_cap_ptr->params);
1682                }
1683                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1684                free(buf);
1685                return NULL;
1686             }
1687             num_ch_to_skip = right_bracket-c_ptr+1;
1688             *right_bracket = '\0';
1689             if ((tmp_buf=GetContentValue(&c_ptr[2], params)) == NULL) {
1690                sprintf(gszMsgBox, TgLoadString(STID_CANT_FIND_NAMED_INFO_IN_CT),
1691                      "HTTP", &c_ptr[2]);
1692                MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1693                *right_bracket = '}';
1694                free(buf);
1695                return NULL;
1696             }
1697             *right_bracket = '}';
1698             break;
1699          default:
1700             MalformedMailCapEntryMessage(mail_cap_ptr);
1701             free(buf);
1702             return NULL;
1703          }
1704          if (num_ch_to_skip < 0 || tmp_buf == NULL) {
1705             free(buf);
1706             FailAllocMessage();
1707             return NULL;
1708          }
1709          len = strlen(tmp_buf);
1710          while (buf_index+len+1 >= buf_sz) {
1711             buf_sz += 0x100;
1712             if ((buf=(char*)realloc(buf, buf_sz+1)) == NULL) return NULL;
1713          }
1714          strcpy(&buf[buf_index], tmp_buf);
1715          buf_index += len;
1716 
1717          free(tmp_buf);
1718          c_ptr += num_ch_to_skip;
1719       } else {
1720          if (buf_index+1 >= buf_sz) {
1721             buf_sz += 0x100;
1722             if ((buf=(char*)realloc(buf, buf_sz+1)) == NULL) return NULL;
1723          }
1724          if (*c_ptr == '\\') c_ptr++;
1725          buf[buf_index++] = *c_ptr++;
1726       }
1727    }
1728    buf[buf_index] = '\0';
1729    return buf;
1730 }
1731 
1732 static
SaveTmpURLToFile(psz_url,no_viewer_found,tmp_fname,new_file_name)1733 int SaveTmpURLToFile(psz_url, no_viewer_found, tmp_fname, new_file_name)
1734    char *psz_url, *tmp_fname, *new_file_name;
1735    int no_viewer_found;
1736 {
1737    char msg[MAXSTRING<<2];
1738    char *msg1=(char*)malloc((strlen(curDirIsLocal ? curDir : curLocalDir)+30) *
1739          sizeof(char));
1740    int rc=TG_REMOTE_STATUS_OK;
1741 
1742    if (msg1 == NULL) { FailAllocMessage(); return INVALID; }
1743 
1744    if (no_viewer_found) {
1745       sprintf(msg, TgLoadString(STID_NO_VIEWER_SAVE_GIVEN_STR_AS), psz_url);
1746    } else {
1747       sprintf(msg, TgLoadString(STID_SAVE_GIVEN_STR_AS), psz_url);
1748    }
1749    sprintf(msg1, TgLoadString(STID_WORKING_DIRECTORY_IS),
1750          (curDirIsLocal ? curDir : curLocalDir));
1751    *new_file_name = '\0';
1752    Dialog(msg, msg1, new_file_name);
1753    free(msg1);
1754    UtilTrimBlanks(new_file_name);
1755 
1756    if (*new_file_name == '\0') return INVALID;
1757    if (!OkayToCreateFile(new_file_name)) return INVALID;
1758 
1759    rc = UtilCopyFile(tmp_fname, new_file_name);
1760    if (rc != TG_REMOTE_STATUS_OK) {
1761       switch (rc) {
1762       case TG_REMOTE_STATUS_READ:
1763          sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_READING),
1764                tmp_fname);
1765          break;
1766       case TG_REMOTE_STATUS_WRITE:
1767          sprintf(gszMsgBox, TgLoadString(STID_CANNOT_OPEN_FILE_FOR_WRITING),
1768                new_file_name);
1769          break;
1770       case TG_REMOTE_STATUS_FILE:
1771          sprintf(gszMsgBox, TgLoadString(STID_FAIL_TO_WRITE_TO_FILE),
1772                new_file_name);
1773          break;
1774       default:
1775          strcpy(gszMsgBox, TgLoadString(STID_UNKNOWN_ERR_IN_COPYING_FILES));
1776          break;
1777       }
1778       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1779       return INVALID;
1780    }
1781    return rc;
1782 }
1783 
1784 static
UseMimeViewer(psz_url,psz_content_type,tmp_fname)1785 int UseMimeViewer(psz_url, psz_content_type, tmp_fname)
1786    char *psz_url, *psz_content_type, *tmp_fname;
1787    /* returns FALSE if psz_url is to be interpreted as a tgif file or text */
1788    /* returns TRUE if external viewer is launched */
1789    /* returns INVALID if there's an error or if the user canceled */
1790 {
1791    char new_file_name[MAXPATHLENGTH+1];
1792    char *viewer=NULL, *cmd=NULL, *big_s=NULL;
1793    int launch_remote_file=FALSE;
1794 
1795    if (psz_content_type == NULL ||
1796          UtilStrICmp(psz_content_type, "application/x-tgif") == 0 ||
1797          strncmp(psz_url, "http:", 5) != 0) {
1798       return FALSE;
1799    }
1800    sprintf(gszMsgBox, "%s", psz_url);
1801    Msg(gszMsgBox);
1802    sprintf(gszMsgBox, "    Content-type: %s", psz_content_type);
1803    Msg(gszMsgBox);
1804    /*
1805     * fprintf(stderr, "URL: %s\n", psz_url);
1806     * fprintf(stderr, "Content-Type: %s\n", psz_content_type);
1807     * fprintf(stderr, "tmp_fname: %s\n", tmp_fname);
1808     */
1809    viewer = GetMimeViewer(psz_content_type);
1810 
1811    if (viewer == NULL) {
1812       char *slash_ptr=(psz_content_type == NULL ? NULL :
1813             strchr(psz_content_type, '/'));
1814 
1815       if (slash_ptr != NULL) {
1816          *slash_ptr = '\0';
1817          if (UtilStrICmp(psz_content_type, "application") == 0 ||
1818                UtilStrICmp(psz_content_type, "audio") == 0 ||
1819                UtilStrICmp(psz_content_type, "image") == 0 ||
1820                UtilStrICmp(psz_content_type, "video") == 0 ||
1821                ((*psz_content_type == 'X' || *psz_content_type == 'x') &&
1822                psz_content_type[1] == '-')) {
1823             *slash_ptr = '/';
1824             SaveTmpURLToFile(psz_url, TRUE, tmp_fname, new_file_name);
1825             return TRUE;
1826          }
1827          *slash_ptr = '/';
1828       }
1829       return FALSE;
1830    }
1831    /*
1832     * fprintf(stderr, "Launch viewer: %s\n", viewer);
1833     */
1834    if ((big_s=strstr(viewer, "%S")) == NULL) {
1835       if (SaveTmpURLToFile(psz_url, FALSE, tmp_fname, new_file_name) ==
1836             INVALID) {
1837          free(viewer);
1838          return INVALID;
1839       }
1840       cmd = (char*)malloc((strlen(viewer)+strlen(new_file_name)+40) *
1841             sizeof(char));
1842    } else {
1843       big_s[1] = 's';
1844       launch_remote_file = TRUE;
1845       cmd = (char*)malloc((strlen(viewer)+strlen(psz_url)+40)*sizeof(char));
1846    }
1847    if (cmd == NULL) {
1848       FailAllocMessage();
1849       free(viewer);
1850       return INVALID;
1851    }
1852    LaunchViewer(launch_remote_file, viewer, psz_url, new_file_name);
1853    free(viewer);
1854    free(cmd);
1855    return TRUE;
1856 }
1857 
1858 static char *gpszViewerInfo=NULL;
1859 
1860 static
GetViewer(ext_str)1861 char *GetViewer(ext_str)
1862    char *ext_str;
1863    /* caller needs to call free() if not return NULL */
1864 {
1865    int ext_len=strlen(ext_str), value_len, orig_len;
1866    char resource_str[MAXSTRING+1];
1867    char *value=NULL, *c_ptr;
1868 
1869    for (c_ptr=gpszViewerInfo; c_ptr != NULL && *c_ptr != '\0'; ) {
1870       char *cr=strchr(c_ptr, '\n'), *next_cr=NULL;
1871       int cmp_result;
1872 
1873       if (cr == NULL) {
1874          free(gpszViewerInfo);
1875          gpszViewerInfo = NULL;
1876          return NULL;
1877       }
1878       *cr = '\0';
1879       cmp_result = UtilStrICmp(c_ptr, ext_str);
1880       *cr++ = '\n';
1881       next_cr = strchr(cr, '\n');
1882       if (next_cr == NULL) {
1883          free(gpszViewerInfo);
1884          gpszViewerInfo = NULL;
1885          return NULL;
1886       }
1887       if (cmp_result == 0) {
1888          char *return_str;
1889 
1890          *next_cr = '\0';
1891          return_str = (*cr == '\0' ? NULL : UtilStrDup(cr));
1892          *next_cr = '\n';
1893          return return_str;
1894       }
1895       c_ptr = &next_cr[1];
1896    }
1897    sprintf(resource_str, "%sViewer", ext_str);
1898    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,resource_str)) != NULL) {
1899       int count=0;
1900 
1901       value = (char*)malloc((strlen(c_ptr)+2)*sizeof(char));
1902       if (value == NULL) {
1903          FailAllocMessage();
1904          return NULL;
1905       }
1906       sprintf(value, "%s\n", c_ptr);
1907       for (c_ptr=strstr(value,"%s"); c_ptr != NULL;
1908             c_ptr=strstr(&c_ptr[2],"%s")) {
1909          count++;
1910       }
1911       for (c_ptr=strstr(value,"%S"); c_ptr != NULL;
1912             c_ptr=strstr(&c_ptr[2],"%S")) {
1913          count++;
1914       }
1915       if (count > 1) {
1916          sprintf(gszMsgBox, TgLoadString(STID_INVALID_XDEF), TOOL_NAME,
1917                resource_str, value);
1918          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
1919          strcpy(value, "\n");
1920       }
1921    } else {
1922       if ((value=UtilStrDup("\n")) == NULL) return NULL;
1923    }
1924    value_len = strlen(value);
1925    orig_len = (gpszViewerInfo == NULL ? 0 : strlen(gpszViewerInfo));
1926    if ((gpszViewerInfo=(gpszViewerInfo == NULL ?
1927          (char*)malloc((orig_len+ext_len+1+value_len+2)*sizeof(char)) :
1928          (char*)realloc(gpszViewerInfo, orig_len+ext_len+1+value_len+2))) ==
1929          NULL) {
1930       FailAllocMessage();
1931       return NULL;
1932    }
1933    sprintf(&gpszViewerInfo[orig_len], "%s\n%s", ext_str, value);
1934    if (value[value_len-1] == '\n') value[--value_len] = '\0';
1935    if (*value == '\0') {
1936       free(value);
1937       return NULL;
1938    }
1939    return value;
1940 }
1941 
1942 static
UseViewer(psz_url,psz_content_type,tmp_fname)1943 int UseViewer(psz_url, psz_content_type, tmp_fname)
1944    char *psz_url, *psz_content_type, *tmp_fname;
1945    /* returns FALSE if psz_url is to be interpreted as a tgif file or text */
1946    /* returns TRUE if external viewer is launched */
1947    /* returns INVALID if there's an error or if the user canceled */
1948 {
1949    char *ext_str=UtilStrRChr(psz_url, (int)'/');
1950    char new_file_name[MAXPATHLENGTH+1];
1951    char *viewer=NULL, *cmd=NULL, *big_s=NULL, *separator, saved_ch='\0';
1952    int launch_remote_file=FALSE;
1953 
1954    if (ext_str == NULL) {
1955       return UseMimeViewer(psz_url, psz_content_type, tmp_fname);
1956    }
1957    for (separator=(&ext_str[1]); *separator != '\0'; separator++) {
1958       if (*separator == '#' || *separator == '?') {
1959          saved_ch = *separator;
1960          *separator = '\0';
1961          break;
1962       }
1963    }
1964    if ((ext_str=strchr(ext_str, '.')) == NULL) {
1965       if (separator != NULL) *separator = saved_ch;
1966       return UseMimeViewer(psz_url, psz_content_type, tmp_fname);
1967    }
1968    ext_str++;
1969    viewer = GetViewer(ext_str);
1970    if (separator != NULL) *separator = saved_ch;
1971    if (viewer == NULL) {
1972       return UseMimeViewer(psz_url, psz_content_type, tmp_fname);
1973    }
1974    if ((big_s=strstr(viewer, "%S")) == NULL) {
1975       if (SaveTmpURLToFile(psz_url, FALSE, tmp_fname, new_file_name) ==
1976             INVALID) {
1977          free(viewer);
1978          return INVALID;
1979       }
1980       cmd = (char*)malloc((strlen(viewer)+strlen(new_file_name)+40) *
1981             sizeof(char));
1982    } else {
1983       big_s[1] = 's';
1984       launch_remote_file = TRUE;
1985       cmd = (char*)malloc((strlen(viewer)+strlen(psz_url)+40)*sizeof(char));
1986    }
1987    if (cmd == NULL) {
1988       FailAllocMessage();
1989       free(viewer);
1990       return INVALID;
1991    }
1992    LaunchViewer(launch_remote_file, viewer, psz_url, new_file_name);
1993    free(viewer);
1994    free(cmd);
1995    return TRUE;
1996 }
1997 
UseExternalViewer(is_html,psz_url,psz_content_type,tmp_fname)1998 int UseExternalViewer(is_html, psz_url, psz_content_type, tmp_fname)
1999    int is_html;
2000    char *psz_url, *psz_content_type, *tmp_fname;
2001    /* returns FALSE if psz_url is to be interpreted as a tgif file or text */
2002    /* returns TRUE if external viewer is launched */
2003    /* returns INVALID if there's an error or if the user canceled */
2004 {
2005    char *viewer=NULL;
2006    int rc=FALSE;
2007    int url_is_html=UrlIsHtml(psz_url);
2008 
2009    if (url_is_html || !is_html) {
2010       if (UseViewer(psz_url, psz_content_type, tmp_fname) != FALSE) {
2011          rc = TRUE;
2012       }
2013    } else if (is_html && (viewer=GetViewer("html")) != NULL) {
2014       char new_file_name[MAXPATHLENGTH+1], *cmd=NULL, *big_s=NULL;
2015       int launch_remote_file=FALSE;
2016 
2017       if ((big_s=strstr(viewer, "%S")) == NULL) {
2018          if (SaveTmpURLToFile(psz_url, FALSE, tmp_fname, new_file_name) ==
2019                INVALID) {
2020             free(viewer);
2021             return INVALID;
2022          }
2023          cmd = (char*)malloc((strlen(viewer)+strlen(new_file_name)+40) *
2024                sizeof(char));
2025       } else {
2026          big_s[1] = 's';
2027          launch_remote_file = TRUE;
2028          cmd = (char*)malloc((strlen(viewer)+strlen(psz_url)+40)*sizeof(char));
2029       }
2030       if (cmd == NULL) {
2031          FailAllocMessage();
2032          free(viewer);
2033          rc = INVALID;
2034       } else {
2035          LaunchViewer(launch_remote_file, viewer, psz_url, new_file_name);
2036          free(viewer);
2037          free(cmd);
2038          rc = TRUE;
2039       }
2040    } else if (UseMimeViewer(psz_url, psz_content_type, tmp_fname) != FALSE) {
2041       rc = TRUE;
2042    }
2043    return rc;
2044 }
2045 
LoadRemoteFileFromMem(psz_url,psz_buf,psz_content_type,buf_sz,is_html)2046 int LoadRemoteFileFromMem(psz_url, psz_buf, psz_content_type, buf_sz, is_html)
2047    char *psz_url, *psz_buf, *psz_content_type;
2048    int buf_sz, is_html;
2049 {
2050    char *tmp_fname=WriteRemoteFileIntoTemp(psz_buf, buf_sz, NULL);
2051    int navigating=navigatingBackAndForth, rc_loadfile;
2052 
2053    if (tmp_fname == NULL) return FALSE;
2054 
2055    if (UseExternalViewer(is_html, psz_url, psz_content_type, tmp_fname) !=
2056          FALSE) {
2057       unlink(tmp_fname);
2058       free(tmp_fname);
2059       return FALSE;
2060    }
2061    if (!navigating) {
2062       BeforeNavigate();
2063       navigatingBackAndForth = TRUE;
2064    }
2065    rc_loadfile = LoadFile(tmp_fname, (-1), FALSE);
2066    if (!navigating) navigatingBackAndForth = FALSE;
2067 
2068    if (!rc_loadfile) {
2069       NewProc();
2070       PasteString(psz_buf, TRUE, TRUE);
2071    }
2072    SetCurDir(psz_url);
2073    curFileDefined = TRUE;
2074    RedrawTitleWindow();
2075    sprintf(gszMsgBox, TgLoadCachedString(CSTID_CUR_FILE_IS), psz_url);
2076    Msg(gszMsgBox);
2077    unlink(tmp_fname);
2078    free(tmp_fname);
2079    if (!navigating) CommitNavigate();
2080    return TRUE;
2081 }
2082 
2083 static
ModifyProxy(proxy_host)2084 void ModifyProxy(proxy_host)
2085    char *proxy_host;
2086 {
2087    char *c_ptr, *host=NULL, *port;
2088 
2089    if ((c_ptr=strstr(proxy_host, "//")) == NULL) {
2090       if ((host=UtilStrDup(proxy_host)) == NULL) return;
2091    } else {
2092       if ((host=UtilStrDup(&c_ptr[2])) == NULL) return;
2093    }
2094    port = strchr(host, ':');
2095    if (port != NULL) *port++ = '\0';
2096    sprintf(proxy_host, "%s%s%s",
2097          host, port==NULL ? "" : ":", port==NULL ? "" : port);
2098    free(host);
2099 }
2100 
InitLocalPID()2101 void InitLocalPID()
2102 {
2103    static int stInitialized=FALSE;
2104 
2105    if (!stInitialized) {
2106       int pid=(int)getpid();
2107       char sz_host_name[MAXSTRING];
2108 
2109       *gszLocalPID = *sz_host_name = '\0';
2110       if (gethostname(sz_host_name, sizeof(sz_host_name)) < 0) {
2111          fprintf(stderr, "%s\n",
2112                TgLoadString(STID_CANT_GETHOSTNAME_USE_LOCALH));
2113          strcpy(sz_host_name, "localhost");
2114       }
2115       sprintf(gszLocalPID, "%1d:%s", pid, sz_host_name);
2116 
2117       stInitialized = TRUE;
2118    }
2119 }
2120 
InitRemote()2121 void InitRemote()
2122 {
2123    char *c_ptr=NULL;
2124    int val=0;
2125 
2126    InitLocalPID();
2127 
2128    autoHyperSpaceOnRemote = TRUE;
2129    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"AutoHyperSpaceOnRemote")) !=
2130          NULL && UtilStrICmp(c_ptr, "false") == 0) {
2131       autoHyperSpaceOnRemote = FALSE;
2132    }
2133    allowLaunchInHyperSpace = FALSE;
2134    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"AllowLaunchInHyperSpace")) !=
2135          NULL && UtilStrICmp(c_ptr, "true") == 0) {
2136       allowLaunchInHyperSpace = TRUE;
2137    }
2138    *gzipCmd = '\0';
2139    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"GZipCmd")) == NULL) {
2140       strcpy(gzipCmd, "gzip -c");
2141    } else {
2142       strcpy(gzipCmd, c_ptr);
2143    }
2144    *gunzipCmd = '\0';
2145    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"GUnZipCmd")) == NULL) {
2146       strcpy(gunzipCmd, "gunzip -c");
2147    } else {
2148       strcpy(gunzipCmd, c_ptr);
2149    }
2150    *uncompressCmd = '\0';
2151    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"UncompressCmd")) == NULL) {
2152       strcpy(uncompressCmd, "uncompress -c");
2153    } else {
2154       strcpy(uncompressCmd, c_ptr);
2155    }
2156    *httpProxy = '\0';
2157    if ((c_ptr=getenv("http_proxy")) != NULL) {
2158       strcpy(httpProxy, c_ptr);
2159       ModifyProxy(httpProxy);
2160    } else if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"HttpProxy")) != NULL) {
2161       strcpy(httpProxy, c_ptr);
2162       ModifyProxy(httpProxy);
2163    } else {
2164       *httpProxy = '\0';
2165    }
2166    *ftpProxy = '\0';
2167    if ((c_ptr=getenv("ftp_proxy")) != NULL) {
2168       strcpy(ftpProxy, c_ptr);
2169       ModifyProxy(ftpProxy);
2170    } else if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"FtpProxy")) != NULL) {
2171       strcpy(ftpProxy, c_ptr);
2172       ModifyProxy(ftpProxy);
2173    } else {
2174       *ftpProxy = '\0';
2175    }
2176    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"DebugHttp")) != NULL &&
2177          sscanf(c_ptr, "%d", &val) == 1 && val >= 0) {
2178       HttpDebug(val);
2179    }
2180    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"DebugFtp")) != NULL &&
2181          sscanf(c_ptr, "%d", &val) == 1 && val >= 0) {
2182       FtpDebug(val);
2183    }
2184    gnHttpKeepAlive = FALSE;
2185    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"HttpKeepAlive")) != NULL &&
2186          UtilStrICmp(c_ptr, "true") == 0) {
2187       gnHttpKeepAlive = TRUE;
2188    }
2189    if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"FakedReferer")) != NULL) {
2190       HttpFakeReferer(c_ptr);
2191    }
2192    InitHttp();
2193    InitMime();
2194 }
2195 
CleanUpRemote()2196 void CleanUpRemote()
2197 {
2198    gnUserAgentInitialized = FALSE;
2199    *gszUserAgentName = '\0';
2200    CleanUpDownloadStats();
2201    CleanUpMime();
2202    CleanUpHttp();
2203    if (gpszViewerInfo != NULL) {
2204       free(gpszViewerInfo);
2205       gpszViewerInfo = NULL;
2206    }
2207    FreeMimeTypesInfo();
2208    FreeMailCapInfo();
2209 }
2210