1 /*
2  * Some code in this file is derived from the public domain code in
3  *              WWW/Library/Implementation/HTFTP.c distributed with lynx-2.2,
4  *              whose original author is Tim Berners-lee <timbl@info.cern.ch>.
5  *
6  * Author:      William Chia-Wei Cheng (bill.cheng@acm.org)
7  *
8  * Copyright (C) 2001-2009, William Chia-Wei Cheng.
9  *
10  * This file may be distributed under the terms of the Q Public License
11  * as defined by Trolltech AS of Norway and appearing in the file
12  * LICENSE.QPL included in the packaging of this file.
13  *
14  * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING
15  * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL,
17  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
18  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
19  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
20  * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21  *
22  * @(#)$Header: /mm2/home/cvs/bc-src/tgif/ftp.c,v 1.10 2011/05/16 16:21:57 william Exp $
23  */
24 
25 #define _INCLUDE_FROM_FTP_C_
26 
27 #include "tgifdefs.h"
28 
29 #include "dialog.e"
30 #include "file.e"
31 #include "ftp.e"
32 #include "msg.e"
33 #include "remote.e"
34 #include "strtbl.e"
35 #include "tcp.e"
36 #include "util.e"
37 
38 int debugFtp=0;
39 
40 static int gnReadyToReceiveData=FALSE;
41 
FtpFreeBuf(buf)42 void FtpFreeBuf(buf)
43    char *buf;
44 {
45    free(buf);
46 }
47 
FtpDebug(val)48 void FtpDebug(val)
49    int val;
50 {
51    debugFtp = val;
52 }
53 
FtpDoConnect(psz_host,us_port,pn_socket)54 int FtpDoConnect(psz_host, us_port, pn_socket)
55    char *psz_host;
56    int us_port, *pn_socket;
57 {
58    int rc, len=strlen(psz_host)+80;
59    char *msg=(char*)malloc((len+1)*sizeof(char));
60 
61    if (msg == NULL) {
62       FailAllocMessage();
63       return TG_REMOTE_STATUS_MEM;
64    }
65    sprintf(msg, TgLoadCachedString(CSTID_MAKING_CONN_TO_HOST), "FTP", psz_host);
66    ShowRemoteStatus(msg);
67 
68    rc = TcpDoConnect(psz_host, us_port, pn_socket);
69 
70    if (rc == TG_REMOTE_STATUS_OK) {
71       sprintf(msg, TgLoadCachedString(CSTID_CONN_TO_HOST_ESTABLISHED), "FTP",
72             psz_host);
73    } else {
74       sprintf(msg, TgLoadString(STID_FAIL_TO_CONN_TO_HOST), "FTP", psz_host);
75    }
76    ShowRemoteStatus(msg);
77    free(msg);
78 
79    return rc;
80 }
81 
82 static
AppendSimpleString(buf,value)83 char *AppendSimpleString(buf, value)
84    char *buf, *value;
85 {
86    int cur_len=(buf==NULL ? 0 : strlen(buf));
87 
88    if (value == NULL) {
89       int new_len=cur_len+2;
90 
91       if (buf == NULL) {
92          buf = (char*)malloc((new_len+1)*sizeof(char));
93       } else {
94          buf = (char*)realloc(buf, new_len+1);
95       }
96       if (buf == NULL) return NULL;
97       sprintf(&buf[cur_len], "\r\n");
98    } else {
99       int new_len=cur_len+strlen(value)+2;
100 
101       if (buf == NULL) {
102          buf = (char*)malloc((new_len+1)*sizeof(char));
103       } else {
104          buf = (char*)realloc(buf, new_len+1);
105       }
106       if (buf == NULL) return NULL;
107       sprintf(&buf[cur_len], "%s\r\n", value);
108    }
109    return buf;
110 }
111 
FtpDoWrite(n_socket,psz_path)112 int FtpDoWrite(n_socket, psz_path)
113    int n_socket;
114    char *psz_path;
115 {
116    int status=TG_REMOTE_STATUS_OK;
117 
118    if (psz_path == NULL) return TG_REMOTE_STATUS_OK;
119 
120    status = TcpDoWrite(n_socket, psz_path, (int)strlen(psz_path));
121    return status;
122 }
123 
124 static
FtpDumpResponse(func_name,buf)125 void FtpDumpResponse(func_name, buf)
126    char *func_name, *buf;
127 {
128    char *c_ptr=strchr(buf, '\n'), *line_ptr=buf;
129    FILE *fp=stdout;
130 
131    /* debug, do not translate */
132    if (debugFtp > 0) fprintf(fp, "In %s:\n", func_name);
133    while (c_ptr != NULL) {
134       char *prev_ptr=c_ptr;
135 
136       if (prev_ptr != line_ptr && *(--prev_ptr) == '\r') {
137          *prev_ptr = '\0';
138       } else {
139          prev_ptr = NULL;
140          *c_ptr = '\0';
141       }
142       if (debugFtp > 0) fprintf(fp, "  %s\n", line_ptr);
143       if (prev_ptr == NULL) {
144          *c_ptr = '\n';
145       } else {
146          *prev_ptr = '\r';
147       }
148       line_ptr = &c_ptr[1];
149       c_ptr = strchr(line_ptr, '\n');
150    }
151    if (line_ptr != NULL) {
152       int len=strlen(line_ptr);
153 
154       if (len > 0 && line_ptr[len-1] == '\r') {
155          line_ptr[len-1] = '\0';
156          if (debugFtp > 0) fprintf(fp, "  %s\n", line_ptr);
157          line_ptr[len-1] = '\r';
158       } else {
159          if (debugFtp > 0) fprintf(fp, "  %s\n", line_ptr);
160       }
161    }
162 }
163 
164 #define MIN_READ_SIZE 0x100
165 
166 static int ftpReadData=FALSE;
167 
FtpDoRead(n_socket,ppsz_buf,pn_buf_sz)168 int FtpDoRead(n_socket, ppsz_buf, pn_buf_sz)
169    int n_socket, *pn_buf_sz;
170    char **ppsz_buf;
171 {
172    int buf_sz=0x400, len=0, end_of_file=FALSE;
173    int rc=(-1);
174    char *buf=(char*)malloc(buf_sz*sizeof(char));
175 
176    if (pn_buf_sz != NULL) *pn_buf_sz = 0;
177    *ppsz_buf = NULL;
178    if (buf == NULL) {
179       FailAllocMessage();
180       return TG_REMOTE_STATUS_MEM;
181    }
182    CleanUpDownloadStats();
183    do {
184       int bytes_read;
185       char progress_buf[MAXSTRING];
186 
187       *progress_buf = '\0';
188       if (buf_sz - len < MIN_READ_SIZE) {
189          buf_sz += 0x400;
190          if ((buf=(char*)realloc(buf, buf_sz)) == NULL) {
191             FailAllocMessage();
192             if (PRTGIF && cmdLineDumpURL && cmdLineDumpURLShowStatus &&
193                   pn_buf_sz != NULL) {
194                fprintf(stderr, "\n");
195             }
196             return TG_REMOTE_STATUS_MEM;
197          }
198       }
199       bytes_read = read(n_socket, &buf[len], buf_sz-len-1);
200       /* debug, do not translate */
201       if (debugFtp >= 3) fprintf(stderr, "      read %1d bytes\n", bytes_read);
202       if (bytes_read <= 0) {
203          if (bytes_read < 0 && (errno == ENOTCONN || errno == ECONNRESET ||
204                errno == EPIPE)) {
205             free(buf);
206             fprintf(stderr, TgLoadString(STID_NETWORK_READ_ERROR), "FTP");
207             fprintf(stderr, "\n");
208             if (PRTGIF && cmdLineDumpURL && cmdLineDumpURLShowStatus &&
209                   pn_buf_sz != NULL) {
210                fprintf(stderr, "\n");
211             }
212             return TG_REMOTE_STATUS_READ;
213          } else if (bytes_read < 0) {
214             free(buf);
215             fprintf(stderr, TgLoadString(STID_NETWORK_ERROR), "FTP");
216             fprintf(stderr, "\n");
217             if (PRTGIF && cmdLineDumpURL && cmdLineDumpURLShowStatus &&
218                   pn_buf_sz != NULL) {
219                fprintf(stderr, "\n");
220             }
221             return TG_REMOTE_STATUS_NET;
222          }
223          if (!UpdateDownloadStats(0, progress_buf)) {
224             *progress_buf = '\0';
225          }
226          end_of_file = TRUE;
227       } else {
228          if (!UpdateDownloadStats(bytes_read, progress_buf)) {
229             *progress_buf = '\0';
230          }
231          len += bytes_read;
232       }
233       if (!end_of_file && UserAbortComm()) {
234          if (buf != NULL) free(buf);
235          sprintf(gszMsgBox, TgLoadString(STID_CONN_ABORT_BY_USER), "FTP");
236          ShowRemoteStatus(gszMsgBox);
237          if (PRTGIF && cmdLineDumpURL && cmdLineDumpURLShowStatus &&
238                pn_buf_sz != NULL) {
239             fprintf(stderr, "\n");
240          }
241          return TG_REMOTE_STATUS_INTR;
242       } else {
243          char msg[MAXSTRING], *c_ptr;
244          int cont_code=(-1);
245 
246          /* do not translate -- program constants */
247          sprintf(msg, "FTP: %1d bytes %s...", len,
248                (*progress_buf=='\0' ? "" : progress_buf));
249          ShowRemoteStatus(msg);
250          if (PRTGIF && cmdLineDumpURL && cmdLineDumpURLShowStatus &&
251                pn_buf_sz != NULL) {
252             /* do not translate -- program constants */
253             fprintf(stderr, "FTP: %1d bytes %s...\r", len,
254                   (*progress_buf=='\0' ? "" : progress_buf));
255          }
256          buf[len] = '\0';
257          if (!ftpReadData) {
258             for (c_ptr=buf; *c_ptr != '\0'; c_ptr++) {
259                char cont_ch;
260 
261                if (sscanf(c_ptr, "%d%c", &rc, &cont_ch) == 2) {
262                   if (cont_code == (-1)) {
263                      if (cont_ch == '-') {
264                         cont_code = rc;
265                      } else {
266                         end_of_file = TRUE;
267                         break;
268                      }
269                   } else if (cont_code == rc && cont_ch == ' ') {
270                      cont_code = (-1);
271                      end_of_file = TRUE;
272                      break;
273                   }
274                }
275                c_ptr = strchr(c_ptr, '\n');
276                if (c_ptr == NULL) break;
277             }
278          }
279       }
280    } while (!end_of_file);
281    if (PRTGIF && cmdLineDumpURL && cmdLineDumpURLShowStatus &&
282          pn_buf_sz != NULL) {
283       fprintf(stderr, "\n");
284    }
285    /* debug, do not translate */
286    if (debugFtp >= 2) fprintf(stderr, "    rc = %1d in FtpDoRead().\n", rc);
287    if (rc == 421) {
288       free(buf);
289       fprintf(stderr, TgLoadString(STID_CONN_TERM_BY_SERVER), "FTP");
290       fprintf(stderr, "\n");
291       return TG_REMOTE_STATUS_TERM;
292    } else {
293       buf[len] = '\0';
294       *ppsz_buf = buf;
295       if (pn_buf_sz != NULL) *pn_buf_sz = len;
296       return TG_REMOTE_STATUS_OK;
297    }
298 }
299 
300 static
FtpSendSimpleCmd(n_socket,value)301 int FtpSendSimpleCmd(n_socket, value)
302    int n_socket;
303    char *value;
304 {
305    int status=TG_REMOTE_STATUS_OK;
306    char *cmd;
307 
308    if ((cmd=AppendSimpleString(NULL, value)) == NULL) {
309       FailAllocMessage();
310       return TG_REMOTE_STATUS_MEM;
311    }
312    status = FtpDoWrite(n_socket, cmd);
313    free(cmd);
314    return status;
315 }
316 
317 static
FtpSendUserName(n_socket,value)318 int FtpSendUserName(n_socket, value)
319    int n_socket;
320    char *value;
321 {
322    return FtpSendSimpleCmd(n_socket, value);
323 }
324 
325 static
FtpSendPassword(n_socket,password)326 int FtpSendPassword(n_socket, password)
327    int n_socket;
328    char *password;
329 {
330    return FtpSendSimpleCmd(n_socket, password);
331 }
332 
333 static
FtpSendType(n_socket,type_cmd)334 int FtpSendType(n_socket, type_cmd)
335    int n_socket;
336    char *type_cmd;
337 {
338    return FtpSendSimpleCmd(n_socket, type_cmd);
339 }
340 
341 static
FtpSendRetrieveCmd(n_socket,psz_path)342 int FtpSendRetrieveCmd(n_socket, psz_path)
343    int n_socket;
344    char *psz_path;
345 {
346    int status=TG_REMOTE_STATUS_OK;
347    char *cmd;
348 
349    /* do not translate -- program constants */
350    cmd = (char*)malloc((strlen("RETR")+1+strlen(psz_path)+2+1)*sizeof(char));
351    if (cmd == NULL) {
352       FailAllocMessage();
353       return TG_REMOTE_STATUS_MEM;
354    }
355    /* do not translate -- program constants */
356    sprintf(cmd, "RETR %s\r\n", psz_path);
357    status = FtpDoWrite(n_socket, cmd);
358    free(cmd);
359    return status;
360 }
361 
362 static
FtpSendListCmd(n_socket)363 int FtpSendListCmd(n_socket)
364    int n_socket;
365 {
366    /* do not translate -- program constants */
367    return FtpSendSimpleCmd(n_socket, "NLST");
368 }
369 
370 static
FtpSendCWDCmd(n_socket,psz_path)371 int FtpSendCWDCmd(n_socket, psz_path)
372    int n_socket;
373    char *psz_path;
374 {
375    int status=TG_REMOTE_STATUS_OK;
376    char *cmd;
377 
378    /* do not translate -- program constants */
379    cmd = (char*)malloc((strlen("CWD")+1+strlen(psz_path)+2+1)*sizeof(char));
380    if (cmd == NULL) {
381       FailAllocMessage();
382       return TG_REMOTE_STATUS_MEM;
383    }
384    /* do not translate -- program constants */
385    sprintf(cmd, "CWD %s\r\n", psz_path);
386    status = FtpDoWrite(n_socket, cmd);
387    free(cmd);
388    return status;
389 }
390 
391 static
FtpSendPortCmd(n_socket,pn_data_socket)392 int FtpSendPortCmd(n_socket, pn_data_socket)
393    int n_socket, *pn_data_socket;
394 {
395    struct sockaddr_in soc_address;
396    struct sockaddr_in *sin=(&soc_address);
397    char port_cmd[20];
398 
399    *pn_data_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
400    if (*pn_data_socket < 0) {
401       fprintf(stderr, TgLoadString(STID_FAIL_TO_OPEN_DATA_SOCKET), "FTP");
402       fprintf(stderr, "\n");
403       return TG_REMOTE_STATUS_FILE;
404    }
405 
406    sin->sin_family = AF_INET;
407    sin->sin_addr.s_addr = INADDR_ANY;
408    {
409       int rc, addr_sz;
410 
411       addr_sz = sizeof(soc_address);
412       rc = getsockname(n_socket, (struct sockaddr *)&soc_address,
413             (void*)(&addr_sz));
414       if (rc < 0) {
415          close(*pn_data_socket);
416          *pn_data_socket = (-1);
417          return TG_REMOTE_STATUS_HOST;
418       }
419       soc_address.sin_port = 0;
420       rc = bind(*pn_data_socket, (struct sockaddr*)&soc_address,
421             sizeof(soc_address));
422       if (rc < 0) {
423          close(*pn_data_socket);
424          *pn_data_socket = (-1);
425          return TG_REMOTE_STATUS_HOST;
426       }
427       addr_sz = sizeof(soc_address);
428       rc = getsockname(*pn_data_socket, (struct sockaddr *)&soc_address,
429             (void*)(&addr_sz));
430       if (rc < 0) {
431          close(*pn_data_socket);
432          *pn_data_socket = (-1);
433          return TG_REMOTE_STATUS_HOST;
434       }
435    }
436    /* do not translate -- program constants */
437    sprintf(port_cmd, "PORT %d,%d,%d,%d,%d,%d",
438          (int)*((unsigned char *)(&sin->sin_addr)+0),
439          (int)*((unsigned char *)(&sin->sin_addr)+1),
440          (int)*((unsigned char *)(&sin->sin_addr)+2),
441          (int)*((unsigned char *)(&sin->sin_addr)+3),
442          (int)*((unsigned char *)(&sin->sin_port)+0),
443          (int)*((unsigned char *)(&sin->sin_port)+1));
444    if (listen(*pn_data_socket, 1) < 0) {
445       close(*pn_data_socket);
446       *pn_data_socket = (-1);
447       return TG_REMOTE_STATUS_HOST;
448    }
449    return FtpSendSimpleCmd(n_socket, port_cmd);
450 }
451 
452 static
FtpReadCmd(n_socket,ppsz_buf,pn_cmd)453 int FtpReadCmd(n_socket, ppsz_buf, pn_cmd)
454    int n_socket, *pn_cmd;
455    char **ppsz_buf;
456    /* if returns TG_REMOTE_STATUS_OK, caller must call FtpFreeBuf(*ppsz_buf) */
457 {
458    int status;
459 
460    if ((status=FtpDoRead(n_socket, ppsz_buf, NULL)) == TG_REMOTE_STATUS_OK) {
461       status = TG_REMOTE_STATUS_FORMAT;
462       if (*ppsz_buf != NULL) {
463          if (sscanf(*ppsz_buf, "%d", pn_cmd) == 1) {
464             *pn_cmd = (int)(*pn_cmd / 100);
465             status = TG_REMOTE_STATUS_OK;
466          }
467       }
468    }
469    if (status != TG_REMOTE_STATUS_OK && *ppsz_buf != NULL) {
470       FtpFreeBuf(*ppsz_buf);
471       *ppsz_buf = NULL;
472    }
473    return status;
474 }
475 
476 static
FtpLogin(n_socket)477 int FtpLogin(n_socket)
478    int n_socket;
479 {
480    char *buf=NULL;
481    int status, ftp_cmd=(-1);
482 
483    if ((status=FtpReadCmd(n_socket, &buf, &ftp_cmd)) == TG_REMOTE_STATUS_OK) {
484       /* debug, do not translate */
485       FtpDumpResponse("FtpLogin", buf);
486       status = TG_REMOTE_STATUS_FORMAT;
487       if (ftp_cmd == 2) {
488          /* do not translate -- program constants */
489          status = FtpSendUserName(n_socket, "USER anonymous");
490       }
491       FtpFreeBuf(buf);
492    }
493    return status;
494 }
495 
496 static char SZ_PASSWORD[128];
497 
498 static int gnPasswordInitialized=FALSE;
499 
500 static
InitPassword()501 void InitPassword()
502 {
503    char user_name[128];
504 
505    if (gnPasswordInitialized) return;
506    gnPasswordInitialized = TRUE;
507 
508    GetUserID(user_name, sizeof(user_name));
509 
510    /* do not translate -- program constants */
511    sprintf(SZ_PASSWORD, "PASS %s", user_name);
512 }
513 
514 static
FtpPassword(n_socket)515 int FtpPassword(n_socket)
516    int n_socket;
517 {
518    char *buf=NULL;
519    int status, ftp_cmd=(-1);
520 
521    if ((status=FtpReadCmd(n_socket, &buf, &ftp_cmd)) == TG_REMOTE_STATUS_OK) {
522       /* debug, do not translate */
523       FtpDumpResponse("FtpPassword", buf);
524       status = TG_REMOTE_STATUS_FORMAT;
525       if (ftp_cmd == 3) {
526          InitPassword();
527          status = FtpSendPassword(n_socket, SZ_PASSWORD);
528       }
529       FtpFreeBuf(buf);
530    }
531    return status;
532 }
533 
534 static
FtpPort(n_socket,pn_data_socket)535 int FtpPort(n_socket, pn_data_socket)
536    int n_socket, *pn_data_socket;
537 {
538    char *buf=NULL;
539    int status, ftp_cmd=(-1);
540 
541    if ((status=FtpReadCmd(n_socket, &buf, &ftp_cmd)) == TG_REMOTE_STATUS_OK) {
542       /* debug, do not translate */
543       FtpDumpResponse("FtpPort", buf);
544       status = TG_REMOTE_STATUS_FORMAT;
545       if (ftp_cmd == 2) {
546          status = FtpSendPortCmd(n_socket, pn_data_socket);
547       } else if (ftp_cmd == 3) {
548          FtpFreeBuf(buf);
549          /* do not translate -- program constants */
550          status = FtpSendPassword(n_socket, "ACCT noaccount");
551          if ((status=FtpReadCmd(n_socket, &buf, &ftp_cmd)) ==
552                TG_REMOTE_STATUS_OK) {
553             /* debug, do not translate */
554             FtpDumpResponse("FtpPort", buf);
555             status = TG_REMOTE_STATUS_FORMAT;
556             if (ftp_cmd == 2) {
557                status = FtpSendPortCmd(n_socket, pn_data_socket);
558             }
559             FtpFreeBuf(buf);
560             buf = NULL;
561          }
562       }
563       if (buf != NULL) FtpFreeBuf(buf);
564    }
565    return status;
566 }
567 
568 static
FtpType(n_socket)569 int FtpType(n_socket)
570    int n_socket;
571 {
572    char *buf=NULL;
573    int status, ftp_cmd=(-1);
574 
575    if ((status=FtpReadCmd(n_socket, &buf, &ftp_cmd)) == TG_REMOTE_STATUS_OK) {
576       /* debug, do not translate */
577       FtpDumpResponse("FtpType", buf);
578       status = TG_REMOTE_STATUS_FORMAT;
579       if (ftp_cmd == 2) {
580          /* do not translate -- program constants */
581          status = FtpSendType(n_socket, "TYPE I");
582       }
583       FtpFreeBuf(buf);
584    }
585    return status;
586 }
587 
588 static
FtpRetr(n_socket,psz_path)589 int FtpRetr(n_socket, psz_path)
590    int n_socket;
591    char *psz_path;
592 {
593    char *buf=NULL;
594    int status, ftp_cmd=(-1);
595 
596    if ((status=FtpReadCmd(n_socket, &buf, &ftp_cmd)) == TG_REMOTE_STATUS_OK) {
597       /* debug, do not translate */
598       FtpDumpResponse("FtpRetr", buf);
599       status = TG_REMOTE_STATUS_FORMAT;
600       if (ftp_cmd == 2) {
601          status = FtpSendRetrieveCmd(n_socket, psz_path);
602       }
603       FtpFreeBuf(buf);
604    }
605    return status;
606 }
607 
608 static
FtpCwd(n_socket,psz_path,pn_is_dir)609 int FtpCwd(n_socket, psz_path, pn_is_dir)
610    int n_socket, *pn_is_dir;
611    char *psz_path;
612 {
613    char *buf=NULL;
614    int status, ftp_cmd=(-1);
615 
616    *pn_is_dir = FALSE;
617    if ((status=FtpReadCmd(n_socket, &buf, &ftp_cmd)) == TG_REMOTE_STATUS_OK) {
618       /* debug, do not translate */
619       FtpDumpResponse("FtpCwd", buf);
620       status = TG_REMOTE_STATUS_FORMAT;
621       if (ftp_cmd != 1) {
622          FtpFreeBuf(buf);
623          status = FtpSendCWDCmd(n_socket, psz_path);
624          if ((status=FtpReadCmd(n_socket, &buf, &ftp_cmd)) ==
625                TG_REMOTE_STATUS_OK) {
626             /* debug, do not translate */
627             FtpDumpResponse("FtpCwd", buf);
628             if (ftp_cmd == 2) {
629                *pn_is_dir = TRUE;
630                gnReadyToReceiveData = TRUE;
631                status = FtpSendListCmd(n_socket);
632             }
633             FtpFreeBuf(buf);
634             buf = NULL;
635          }
636       } else {
637          gnReadyToReceiveData = TRUE;
638          status = TG_REMOTE_STATUS_OK;
639       }
640       if (buf != NULL) FtpFreeBuf(buf);
641    }
642    return status;
643 }
644 
645 static
FtpGetContent(n_socket,data_socket,is_dir,ppsz_buf,pn_buf_sz)646 int FtpGetContent(n_socket, data_socket, is_dir, ppsz_buf, pn_buf_sz)
647    int n_socket, data_socket, is_dir, *pn_buf_sz;
648    char **ppsz_buf;
649 {
650    struct sockaddr_in soc_address;
651    int soc_addrlen=sizeof(soc_address), accepted_socket;
652    int status=TG_REMOTE_STATUS_OK;
653 
654    if (pn_buf_sz != NULL) *pn_buf_sz = 0;
655    *ppsz_buf = NULL;
656    accepted_socket = accept(data_socket, (struct sockaddr *)&soc_address,
657          (void*)(&soc_addrlen));
658    if (accepted_socket < 0) return TG_REMOTE_STATUS_HOST;
659 
660    ftpReadData = TRUE;
661    if (is_dir) {
662       /* a directory */
663       status = FtpDoRead(accepted_socket, ppsz_buf, pn_buf_sz);
664    } else {
665       /* a file */
666       status = FtpDoRead(accepted_socket, ppsz_buf, pn_buf_sz);
667    }
668    ftpReadData = FALSE;
669    close(accepted_socket);
670    return TG_REMOTE_STATUS_OK;
671 }
672 
FtpDoTalk(n_socket,psz_path,ppsz_buf,pn_buf_sz)673 int FtpDoTalk(n_socket, psz_path, ppsz_buf, pn_buf_sz)
674    int n_socket, *pn_buf_sz;
675    char *psz_path, **ppsz_buf;
676 {
677    int status=TG_REMOTE_STATUS_OK, data_socket=(-1), is_dir=FALSE;
678    char msg[80];
679 
680    *ppsz_buf = NULL;
681    if ((status=FtpLogin(n_socket)) != TG_REMOTE_STATUS_OK) return status;
682    if ((status=FtpPassword(n_socket)) != TG_REMOTE_STATUS_OK) return status;
683    if ((status=FtpPort(n_socket, &data_socket)) != TG_REMOTE_STATUS_OK) {
684       return status;
685    }
686    if ((status=FtpType(n_socket)) != TG_REMOTE_STATUS_OK) return status;
687    if ((status=FtpRetr(n_socket, psz_path)) != TG_REMOTE_STATUS_OK) {
688       if (data_socket != (-1)) close(data_socket);
689       return (FTP_LOGGED_IN|status);
690    }
691    gnReadyToReceiveData = FALSE;
692    if ((status=FtpCwd(n_socket, psz_path, &is_dir)) != TG_REMOTE_STATUS_OK) {
693       if (data_socket != (-1)) close(data_socket);
694       return (FTP_LOGGED_IN|status);
695    }
696    if (gnReadyToReceiveData) {
697       sprintf(msg, TgLoadCachedString(CSTID_LOGIN_SUCC_RETRIEVE_DATA), "FTP");
698       ShowRemoteStatus(msg);
699 
700       status = FtpGetContent(n_socket, data_socket, is_dir, ppsz_buf,
701             pn_buf_sz);
702    }
703    if (data_socket != (-1)) close(data_socket);
704    return (FTP_LOGGED_IN|status);
705 }
706 
707