summaryrefslogtreecommitdiff
path: root/noncore/net/ftplib
authorllornkcor <llornkcor>2002-11-09 15:27:29 (UTC)
committer llornkcor <llornkcor>2002-11-09 15:27:29 (UTC)
commitfee37fd9a7c038dbf5cce74172721ca3cdc8745b (patch) (unidiff)
treedc9ed0da618d4ef6e96777e992cfc88fa619656c /noncore/net/ftplib
parentd5d079c5bfaa10c310628d1ef7905d98b64dfa81 (diff)
downloadopie-fee37fd9a7c038dbf5cce74172721ca3cdc8745b.zip
opie-fee37fd9a7c038dbf5cce74172721ca3cdc8745b.tar.gz
opie-fee37fd9a7c038dbf5cce74172721ca3cdc8745b.tar.bz2
move ftp stuff from opieftp to shared lib
Diffstat (limited to 'noncore/net/ftplib') (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/net/ftplib/ftplib.c1346
-rw-r--r--noncore/net/ftplib/ftplib.control9
-rw-r--r--noncore/net/ftplib/ftplib.h124
-rw-r--r--noncore/net/ftplib/ftplib.pro6
4 files changed, 1485 insertions, 0 deletions
diff --git a/noncore/net/ftplib/ftplib.c b/noncore/net/ftplib/ftplib.c
new file mode 100644
index 0000000..421f855
--- a/dev/null
+++ b/noncore/net/ftplib/ftplib.c
@@ -0,0 +1,1346 @@
1/***************************************************************************/
2/* ftplib.c - callable ftp access routines */
3/* Copyright (C) 1996-2000 Thomas Pfau, pfau@cnj.digex.net */
4/* 73 Catherine Street, South Bound Brook, NJ, 08880 */
5/* */
6/* This library is free software; you can redistribute it and/or */
7/* modify it under the terms of the GNU Library General Public */
8/* License as published by the Free Software Foundation; either */
9/* version 2 of the License, or (at your option) any later version. */
10/* */
11/* This library is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
14/* Library General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU Library General Public */
17/* License along with this progam; if not, write to the */
18/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
19/* Boston, MA 02111-1307, USA. */
20/* */
21/***************************************************************************/
22// changes made by Lorn Potter <llornkcor@handhelds.org>
23//
24#if defined(__unix__) || defined(__VMS)
25#include <unistd.h>
26#endif
27#if defined(_WIN32)
28#include <windows.h>
29#endif
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34#include <errno.h>
35#include <ctype.h>
36
37#if defined(__unix__)
38
39#include <sys/types.h>
40#include <unistd.h>
41#include <fcntl.h>
42#include <sys/time.h>
43#include <sys/types.h>
44#include <sys/socket.h>
45#include <netinet/in.h>
46#include <netdb.h>
47#include <arpa/inet.h>
48
49#elif defined(VMS)
50
51#include <types.h>
52#include <socket.h>
53#include <in.h>
54#include <netdb.h>
55#include <inet.h>
56
57#elif defined(_WIN32)
58
59#include <winsock.h>
60
61#endif
62
63#define BUILDING_LIBRARY
64#include "ftplib.h"
65
66#if defined(_WIN32)
67#define SETSOCKOPT_OPTVAL_TYPE (const char *)
68#else
69#define SETSOCKOPT_OPTVAL_TYPE (void *)
70#endif
71
72#define FTPLIB_BUFSIZ 8192
73#define ACCEPT_TIMEOUT 10
74
75#define FTPLIB_CONTROL 0
76#define FTPLIB_READ 1
77#define FTPLIB_WRITE 2
78
79#if !defined FTPLIB_DEFMODE
80#define FTPLIB_DEFMODE FTPLIB_PASSIVE
81#endif
82
83struct NetBuf {
84 char *cput,*cget;
85 int handle;
86 int cavail,cleft;
87 char *buf;
88 int dir;
89 netbuf *ctrl;
90 netbuf *data;
91 int cmode;
92 struct timeval idletime;
93 FtpCallback idlecb;
94 void *idlearg;
95 int xfered;
96 int cbbytes;
97 int xfered1;
98 char response[256];
99};
100
101static char *version =
102"ftplib Release 3.1-1 9/16/00, copyright 1996-2000 Thomas Pfau";
103
104GLOBALDEF int ftplib_debug = 0;
105
106#if defined(__unix__) || defined(VMS)
107#define net_read read
108#define net_write write
109#define net_close close
110#elif defined(_WIN32)
111#define net_read(x,y,z) recv(x,y,z,0)
112#define net_write(x,y,z) send(x,y,z,0)
113#define net_close closesocket
114#endif
115
116#if defined(NEED_MEMCCPY)
117/*
118 * VAX C does not supply a memccpy routine so I provide my own
119 */
120void *memccpy(void *dest, const void *src, int c, size_t n)
121{
122 int i=0;
123 const unsigned char *ip=src;
124 unsigned char *op=dest;
125
126 while (i < n)
127 {
128 if ((*op++ = *ip++) == c)
129 break;
130 i++;
131 }
132 if (i == n)
133 return NULL;
134 return op;
135}
136#endif
137#if defined(NEED_STRDUP)
138/*
139 * strdup - return a malloc'ed copy of a string
140 */
141char *strdup(const char *src)
142{
143 int l = strlen(src) + 1;
144 char *dst = malloc(l);
145 if (dst)
146 strcpy(dst,src);
147 return dst;
148}
149#endif
150
151/*
152 * socket_wait - wait for socket to receive or flush data
153 *
154 * return 1 if no user callback, otherwise, return value returned by
155 * user callback
156 */
157static int socket_wait(netbuf *ctl)
158{
159 fd_set fd,*rfd = NULL,*wfd = NULL;
160 struct timeval tv;
161 int rv = 0;
162 if ((ctl->dir == FTPLIB_CONTROL) || (ctl->idlecb == NULL))
163 return 1;
164 if (ctl->dir == FTPLIB_WRITE)
165 wfd = &fd;
166 else
167 rfd = &fd;
168 FD_ZERO(&fd);
169 do
170 {
171 FD_SET(ctl->handle,&fd);
172 tv = ctl->idletime;
173 rv = select(ctl->handle+1, rfd, wfd, NULL, &tv);
174 if (rv == -1)
175 {
176 rv = 0;
177 strncpy(ctl->ctrl->response, strerror(errno),
178 sizeof(ctl->ctrl->response));
179 break;
180 }
181 else if (rv > 0)
182 {
183 rv = 1;
184 break;
185 }
186 }
187 while ((rv = ctl->idlecb(ctl, ctl->xfered, ctl->idlearg)));
188 return rv;
189}
190
191/*
192 * read a line of text
193 *
194 * return -1 on error or bytecount
195 */
196static int readline(char *buf,int max,netbuf *ctl)
197{
198 int x,retval = 0;
199 char *end,*bp=buf;
200 int eof = 0;
201
202 if ((ctl->dir != FTPLIB_CONTROL) && (ctl->dir != FTPLIB_READ))
203 return -1;
204 if (max == 0)
205 return 0;
206 do
207 {
208 if (ctl->cavail > 0)
209 {
210 x = (max >= ctl->cavail) ? ctl->cavail : max-1;
211 end = memccpy(bp,ctl->cget,'\n',x);
212 if (end != NULL)
213 x = end - bp;
214 retval += x;
215 bp += x;
216 *bp = '\0';
217 max -= x;
218 ctl->cget += x;
219 ctl->cavail -= x;
220 if (end != NULL)
221 {
222 bp -= 2;
223 if (strcmp(bp,"\r\n") == 0)
224 {
225 *bp++ = '\n';
226 *bp++ = '\0';
227 --retval;
228 }
229 break;
230 }
231 }
232 if (max == 1)
233 {
234 *buf = '\0';
235 break;
236 }
237 if (ctl->cput == ctl->cget)
238 {
239 ctl->cput = ctl->cget = ctl->buf;
240 ctl->cavail = 0;
241 ctl->cleft = FTPLIB_BUFSIZ;
242 }
243 if (eof)
244 {
245 if (retval == 0)
246 retval = -1;
247 break;
248 }
249 if (!socket_wait(ctl))
250 return retval;
251 if ((x = net_read(ctl->handle,ctl->cput,ctl->cleft)) == -1)
252 {
253 perror("read");
254 retval = -1;
255 break;
256 }
257 if (x == 0)
258 eof = 1;
259 ctl->cleft -= x;
260 ctl->cavail += x;
261 ctl->cput += x;
262 }
263 while (1);
264 return retval;
265}
266
267/*
268 * write lines of text
269 *
270 * return -1 on error or bytecount
271 */
272static int writeline(char *buf, int len, netbuf *nData)
273{
274 int x, nb=0, w;
275 char *ubp = buf, *nbp;
276 char lc=0;
277
278 if (nData->dir != FTPLIB_WRITE)
279 return -1;
280 nbp = nData->buf;
281 for (x=0; x < len; x++)
282 {
283 if ((*ubp == '\n') && (lc != '\r'))
284 {
285 if (nb == FTPLIB_BUFSIZ)
286 {
287 if (!socket_wait(nData))
288 return x;
289 w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
290 if (w != FTPLIB_BUFSIZ)
291 {
292 printf("net_write(1) returned %d, errno = %d\n", w, errno);
293 return(-1);
294 }
295 nb = 0;
296 }
297 nbp[nb++] = '\r';
298 }
299 if (nb == FTPLIB_BUFSIZ)
300 {
301 if (!socket_wait(nData))
302 return x;
303 w = net_write(nData->handle, nbp, FTPLIB_BUFSIZ);
304 if (w != FTPLIB_BUFSIZ)
305 {
306 printf("net_write(2) returned %d, errno = %d\n", w, errno);
307 return(-1);
308 }
309 nb = 0;
310 }
311 nbp[nb++] = lc = *ubp++;
312 }
313 if (nb)
314 {
315 if (!socket_wait(nData))
316 return x;
317 w = net_write(nData->handle, nbp, nb);
318 if (w != nb)
319 {
320 printf("net_write(3) returned %d, errno = %d\n", w, errno);
321 return(-1);
322 }
323 }
324 return len;
325}
326
327/*
328 * read a response from the server
329 *
330 * return 0 if first char doesn't match
331 * return 1 if first char matches
332 */
333static int readresp(char c, netbuf *nControl)
334{
335 char match[5];
336 if (readline(nControl->response,256,nControl) == -1)
337 {
338 perror("Control socket read failed");
339 return 0;
340 }
341 if (ftplib_debug > 1)
342 fprintf(stderr,"%s",nControl->response);
343 if (nControl->response[3] == '-')
344 {
345 strncpy(match,nControl->response,3);
346 match[3] = ' ';
347 match[4] = '\0';
348 do
349 {
350 if (readline(nControl->response,256,nControl) == -1)
351 {
352 perror("Control socket read failed");
353 return 0;
354 }
355 if (ftplib_debug > 1)
356 fprintf(stderr,"%s",nControl->response);
357 }
358 while (strncmp(nControl->response,match,4));
359 }
360 if (nControl->response[0] == c)
361 return 1;
362 return 0;
363}
364
365/*
366 * FtpInit for stupid operating systems that require it (Windows NT)
367 */
368GLOBALDEF void FtpInit(void)
369{
370#if defined(_WIN32)
371 WORD wVersionRequested;
372 WSADATA wsadata;
373 int err;
374 wVersionRequested = MAKEWORD(1,1);
375 if ((err = WSAStartup(wVersionRequested,&wsadata)) != 0)
376 fprintf(stderr,"Network failed to start: %d\n",err);
377#endif
378}
379
380/*
381 * FtpLastResponse - return a pointer to the last response received
382 */
383GLOBALDEF char *FtpLastResponse(netbuf *nControl)
384{
385 if ((nControl) && (nControl->dir == FTPLIB_CONTROL))
386 return nControl->response;
387 return NULL;
388}
389
390/*
391 * FtpConnect - connect to remote server
392 *
393 * return 1 if connected, 0 if not
394 */
395GLOBALDEF int FtpConnect(const char *host, netbuf **nControl)
396{
397 int sControl, stat, flags, oldflags;
398 struct sockaddr_in sin;
399 struct hostent *phe;
400 struct servent *pse;
401 int on=1;
402 netbuf *ctrl;
403 char *lhost;
404 char *pnum;
405 struct timeval tv;
406 fd_set wr;
407
408 memset(&sin,0,sizeof(sin));
409 sin.sin_family = AF_INET;
410 lhost = strdup(host);
411 pnum = strchr(lhost,':');
412 if (pnum == NULL)
413 {
414#if defined(VMS)
415 sin.sin_port = htons(21);
416#else
417 if ((pse = getservbyname("ftp","tcp")) == NULL)
418 {
419 perror("getservbyname");
420 return 0;
421 }
422 sin.sin_port = pse->s_port;
423#endif
424 }
425 else
426 {
427 *pnum++ = '\0';
428 if (isdigit(*pnum))
429 sin.sin_port = htons(atoi(pnum));
430 else
431 {
432 pse = getservbyname(pnum,"tcp");
433 sin.sin_port = pse->s_port;
434 }
435 }
436 if ((sin.sin_addr.s_addr = inet_addr(lhost)) == -1)
437 {
438 if ((phe = gethostbyname(lhost)) == NULL)
439 {
440 perror("gethostbyname");
441 return 0;
442 }
443
444 memcpy((char *)&sin.sin_addr, phe->h_addr, phe->h_length);
445
446 }
447 free(lhost);
448
449 sControl = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
450 if (sControl == -1)
451 {
452 perror("socket");
453 return 0;
454 }
455
456 if ( setsockopt(sControl,SOL_SOCKET,SO_REUSEADDR,
457 SETSOCKOPT_OPTVAL_TYPE &on, sizeof(on)) == -1)
458 {
459 perror("setsockopt");
460 net_close(sControl);
461 return 0;
462 }
463
464 //set nonblocking for connection timeout
465 flags = fcntl( sControl, F_GETFL,0);
466 oldflags=flags;
467 fcntl( sControl, F_SETFL, O_NONBLOCK|flags);
468
469 stat=connect( sControl, (struct sockaddr *)&sin, sizeof(sin));
470 if (stat < 0)
471 {
472 if (errno != EWOULDBLOCK && errno != EINPROGRESS)
473 {
474 perror("connect");
475 net_close(sControl);
476 return 0;
477 }
478 }
479
480 FD_ZERO(&wr);
481 FD_SET( sControl, &wr);
482
483 tv.tv_sec = ACCEPT_TIMEOUT;
484 tv.tv_usec = 0;
485
486 stat = select(sControl+1, 0, &wr, 0, &tv);
487
488 if (stat < 1)
489 {
490 // time out has expired,
491 // or an error has ocurred
492 perror("timeout");
493 net_close(sControl);
494 return 0;
495 }
496
497 printf("connected\n");
498
499 //set original flags
500 fcntl( sControl, F_SETFL, oldflags);
501
502 ctrl = calloc(1,sizeof(netbuf));
503 if (ctrl == NULL)
504 {
505 perror("calloc");
506 net_close(sControl);
507 return 0;
508 }
509 ctrl->buf = malloc(FTPLIB_BUFSIZ);
510 if (ctrl->buf == NULL)
511 {
512 perror("calloc");
513 net_close(sControl);
514 free(ctrl);
515 return 0;
516 }
517 ctrl->handle = sControl;
518 ctrl->dir = FTPLIB_CONTROL;
519 ctrl->ctrl = NULL;
520 ctrl->cmode = FTPLIB_DEFMODE;
521 ctrl->idlecb = NULL;
522 ctrl->idletime.tv_sec = ctrl->idletime.tv_usec = 0;
523 ctrl->idlearg = NULL;
524 ctrl->xfered = 0;
525 ctrl->xfered1 = 0;
526 ctrl->cbbytes = 0;
527 if (readresp('2', ctrl) == 0)
528 {
529 net_close(sControl);
530 free(ctrl->buf);
531 free(ctrl);
532 return 0;
533 }
534 *nControl = ctrl;
535 return 1;
536}
537
538/*
539 * FtpOptions - change connection options
540 *
541 * returns 1 if successful, 0 on error
542 */
543GLOBALDEF int FtpOptions(int opt, long val, netbuf *nControl)
544{
545 int v,rv=0;
546 switch (opt)
547 {
548 case FTPLIB_CONNMODE:
549 v = (int) val;
550 if ((v == FTPLIB_PASSIVE) || (v == FTPLIB_PORT))
551 {
552 nControl->cmode = v;
553 rv = 1;
554 }
555 break;
556 case FTPLIB_CALLBACK:
557 nControl->idlecb = (FtpCallback) val;
558 rv = 1;
559 break;
560 case FTPLIB_IDLETIME:
561 v = (int) val;
562 rv = 1;
563 nControl->idletime.tv_sec = v / 1000;
564 nControl->idletime.tv_usec = (v % 1000) * 1000;
565 break;
566 case FTPLIB_CALLBACKARG:
567 rv = 1;
568 nControl->idlearg = (void *) val;
569 break;
570 case FTPLIB_CALLBACKBYTES:
571 rv = 1;
572 nControl->cbbytes = (int) val;
573 break;
574 }
575 return rv;
576}
577
578/*
579 * FtpSendCmd - send a command and wait for expected response
580 *
581 * return 1 if proper response received, 0 otherwise
582 */
583static int FtpSendCmd(const char *cmd, char expresp, netbuf *nControl)
584{
585 char buf[256];
586 if (nControl->dir != FTPLIB_CONTROL)
587 return 0;
588 if (ftplib_debug > 2)
589 fprintf(stderr,"%s\n",cmd);
590 if ((strlen(cmd) + 3) > sizeof(buf))
591 return 0;
592 sprintf(buf,"%s\r\n",cmd);
593 if (net_write(nControl->handle,buf,strlen(buf)) <= 0)
594 {
595 perror("write");
596 return 0;
597 }
598 return readresp(expresp, nControl);
599}
600
601/*
602 * FtpLogin - log in to remote server
603 *
604 * return 1 if logged in, 0 otherwise
605 */
606GLOBALDEF int FtpLogin(const char *user, const char *pass, netbuf *nControl)
607{
608 char tempbuf[64];
609
610 if (((strlen(user) + 7) > sizeof(tempbuf)) ||
611 ((strlen(pass) + 7) > sizeof(tempbuf)))
612 return 0;
613 sprintf(tempbuf,"USER %s",user);
614 if (!FtpSendCmd(tempbuf,'3',nControl))
615 {
616 if (nControl->response[0] == '2')
617 return 1;
618 return 0;
619 }
620 sprintf(tempbuf,"PASS %s",pass);
621 return FtpSendCmd(tempbuf,'2',nControl);
622}
623
624/*
625 * FtpOpenPort - set up data connection
626 *
627 * return 1 if successful, 0 otherwise
628 */
629static int FtpOpenPort(netbuf *nControl, netbuf **nData, int mode, int dir)
630{
631 int sData;
632 union {
633 struct sockaddr sa;
634 struct sockaddr_in in;
635 } sin;
636 struct linger lng = { 0, 0 };
637 unsigned int l;
638 int on=1;
639 netbuf *ctrl;
640 char *cp;
641 unsigned int v[6];
642 char buf[256];
643
644 if (nControl->dir != FTPLIB_CONTROL)
645 return -1;
646 if ((dir != FTPLIB_READ) && (dir != FTPLIB_WRITE))
647 {
648 sprintf(nControl->response, "Invalid direction %d\n", dir);
649 return -1;
650 }
651 if ((mode != FTPLIB_ASCII) && (mode != FTPLIB_IMAGE))
652 {
653 sprintf(nControl->response, "Invalid mode %c\n", mode);
654 return -1;
655 }
656 l = sizeof(sin);
657 if (nControl->cmode == FTPLIB_PASSIVE)
658 {
659 memset(&sin, 0, l);
660 sin.in.sin_family = AF_INET;
661 if (!FtpSendCmd("PASV",'2',nControl))
662 return -1;
663 cp = strchr(nControl->response,'(');
664 if (cp == NULL)
665 return -1;
666 cp++;
667 sscanf(cp,"%u,%u,%u,%u,%u,%u",&v[2],&v[3],&v[4],&v[5],&v[0],&v[1]);
668 sin.sa.sa_data[2] = v[2];
669 sin.sa.sa_data[3] = v[3];
670 sin.sa.sa_data[4] = v[4];
671 sin.sa.sa_data[5] = v[5];
672 sin.sa.sa_data[0] = v[0];
673 sin.sa.sa_data[1] = v[1];
674 }
675 else
676 {
677 if (getsockname(nControl->handle, &sin.sa, &l) < 0)
678 {
679 perror("getsockname");
680 return 0;
681 }
682 }
683 sData = socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
684 if (sData == -1)
685 {
686 perror("socket");
687 return -1;
688 }
689 if (setsockopt(sData,SOL_SOCKET,SO_REUSEADDR,
690 SETSOCKOPT_OPTVAL_TYPE &on,sizeof(on)) == -1)
691 {
692 perror("setsockopt");
693 net_close(sData);
694 return -1;
695 }
696 if (setsockopt(sData,SOL_SOCKET,SO_LINGER,
697 SETSOCKOPT_OPTVAL_TYPE &lng,sizeof(lng)) == -1)
698 {
699 perror("setsockopt");
700 net_close(sData);
701 return -1;
702 }
703 if (nControl->cmode == FTPLIB_PASSIVE)
704 {
705 if (connect(sData, &sin.sa, sizeof(sin.sa)) == -1)
706 {
707 perror("connect");
708 net_close(sData);
709 return -1;
710 }
711 }
712 else
713 {
714 sin.in.sin_port = 0;
715 if (bind(sData, &sin.sa, sizeof(sin)) == -1)
716 {
717 perror("bind");
718 net_close(sData);
719 return 0;
720 }
721 if (listen(sData, 1) < 0)
722 {
723 perror("listen");
724 net_close(sData);
725 return 0;
726 }
727 if (getsockname(sData, &sin.sa, &l) < 0)
728 return 0;
729 sprintf(buf, "PORT %d,%d,%d,%d,%d,%d",
730 (unsigned char) sin.sa.sa_data[2],
731 (unsigned char) sin.sa.sa_data[3],
732 (unsigned char) sin.sa.sa_data[4],
733 (unsigned char) sin.sa.sa_data[5],
734 (unsigned char) sin.sa.sa_data[0],
735 (unsigned char) sin.sa.sa_data[1]);
736 if (!FtpSendCmd(buf,'2',nControl))
737 {
738 net_close(sData);
739 return 0;
740 }
741 }
742 ctrl = calloc(1,sizeof(netbuf));
743 if (ctrl == NULL)
744 {
745 perror("calloc");
746 net_close(sData);
747 return -1;
748 }
749 if ((mode == 'A') && ((ctrl->buf = malloc(FTPLIB_BUFSIZ)) == NULL))
750 {
751 perror("calloc");
752 net_close(sData);
753 free(ctrl);
754 return -1;
755 }
756 ctrl->handle = sData;
757 ctrl->dir = dir;
758 ctrl->idletime = nControl->idletime;
759 ctrl->idlearg = nControl->idlearg;
760 ctrl->xfered = 0;
761 ctrl->xfered1 = 0;
762 ctrl->cbbytes = nControl->cbbytes;
763 if (ctrl->idletime.tv_sec || ctrl->idletime.tv_usec || ctrl->cbbytes)
764 ctrl->idlecb = nControl->idlecb;
765 else
766 ctrl->idlecb = NULL;
767 *nData = ctrl;
768 return 1;
769}
770
771/*
772 * FtpAcceptConnection - accept connection from server
773 *
774 * return 1 if successful, 0 otherwise
775 */
776static int FtpAcceptConnection(netbuf *nData, netbuf *nControl)
777{
778 int sData;
779 struct sockaddr addr;
780 unsigned int l;
781 int i;
782 struct timeval tv;
783 fd_set mask;
784 int rv;
785
786 FD_ZERO(&mask);
787 FD_SET(nControl->handle, &mask);
788 FD_SET(nData->handle, &mask);
789 tv.tv_usec = 0;
790 tv.tv_sec = ACCEPT_TIMEOUT;
791 printf("<<<<<<<<<<<<<<<<%d\n",ACCEPT_TIMEOUT);
792 i = nControl->handle;
793 if (i < nData->handle)
794 i = nData->handle;
795 i = select(i+1, &mask, NULL, NULL, &tv);
796 if (i == -1)
797 {
798 strncpy(nControl->response, strerror(errno),
799 sizeof(nControl->response));
800 net_close(nData->handle);
801 nData->handle = 0;
802 rv = 0;
803 }
804 else if (i == 0)
805 {
806 strcpy(nControl->response, "timed out waiting for connection");
807 net_close(nData->handle);
808 nData->handle = 0;
809 rv = 0;
810 }
811 else
812 {
813 if (FD_ISSET(nData->handle, &mask))
814 {
815 l = sizeof(addr);
816 sData = accept(nData->handle, &addr, &l);
817 i = errno;
818 net_close(nData->handle);
819 if (sData > 0)
820 {
821 rv = 1;
822 nData->handle = sData;
823 }
824 else
825 {
826 strncpy(nControl->response, strerror(i),
827 sizeof(nControl->response));
828 nData->handle = 0;
829 rv = 0;
830 }
831 }
832 else if (FD_ISSET(nControl->handle, &mask))
833 {
834 net_close(nData->handle);
835 nData->handle = 0;
836 readresp('2', nControl);
837 rv = 0;
838 }
839 }
840 return rv;
841}
842
843/*
844 * FtpAccess - return a handle for a data stream
845 *
846 * return 1 if successful, 0 otherwise
847 */
848GLOBALDEF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl,
849 netbuf **nData)
850{
851 char buf[256];
852 int dir;
853 if ((path == NULL) &&
854 ((typ == FTPLIB_FILE_WRITE) || (typ == FTPLIB_FILE_READ)))
855 {
856 sprintf(nControl->response,
857 "Missing path argument for file transfer\n");
858 return 0;
859 }
860 sprintf(buf, "TYPE %c", mode);
861 if (!FtpSendCmd(buf, '2', nControl))
862 return 0;
863 switch (typ)
864 {
865 case FTPLIB_DIR:
866 strcpy(buf,"NLST");
867 dir = FTPLIB_READ;
868 break;
869 case FTPLIB_DIR_VERBOSE:
870 strcpy(buf,"LIST");
871 dir = FTPLIB_READ;
872 break;
873 case FTPLIB_FILE_READ:
874 strcpy(buf,"RETR");
875 dir = FTPLIB_READ;
876 break;
877 case FTPLIB_FILE_WRITE:
878 strcpy(buf,"STOR");
879 dir = FTPLIB_WRITE;
880 break;
881 default:
882 sprintf(nControl->response, "Invalid open type %d\n", typ);
883 return 0;
884 }
885 if (path != NULL)
886 {
887 int i = strlen(buf);
888 buf[i++] = ' ';
889 if ((strlen(path) + i) >= sizeof(buf))
890 return 0;
891 strcpy(&buf[i],path);
892 }
893 if (FtpOpenPort(nControl, nData, mode, dir) == -1)
894 return 0;
895 if (!FtpSendCmd(buf, '1', nControl))
896 {
897 FtpClose(*nData);
898 *nData = NULL;
899 return 0;
900 }
901 (*nData)->ctrl = nControl;
902 nControl->data = *nData;
903 if (nControl->cmode == FTPLIB_PORT)
904 {
905 if (!FtpAcceptConnection(*nData,nControl))
906 {
907 FtpClose(*nData);
908 *nData = NULL;
909 nControl->data = NULL;
910 return 0;
911 }
912 }
913 return 1;
914}
915
916/*
917 * FtpRead - read from a data connection
918 */
919GLOBALDEF int FtpRead(void *buf, int max, netbuf *nData)
920{
921 int i;
922 if (nData->dir != FTPLIB_READ)
923 return 0;
924 if (nData->buf)
925 i = readline(buf, max, nData);
926 else
927 {
928 i = socket_wait(nData);
929 if (i != 1)
930 return 0;
931 i = net_read(nData->handle, buf, max);
932 }
933 if (i == -1)
934 return 0;
935 nData->xfered += i;
936 if (nData->idlecb && nData->cbbytes)
937 {
938 nData->xfered1 += i;
939 if (nData->xfered1 > nData->cbbytes)
940 {
941 if (nData->idlecb(nData, nData->xfered, nData->idlearg) == 0)
942 return 0;
943 nData->xfered1 = 0;
944 }
945 }
946 return i;
947}
948
949/*
950 * FtpWrite - write to a data connection
951 */
952GLOBALDEF int FtpWrite(void *buf, int len, netbuf *nData)
953{
954 int i;
955 if (nData->dir != FTPLIB_WRITE)
956 return 0;
957 if (nData->buf)
958 i = writeline(buf, len, nData);
959 else
960 {
961 socket_wait(nData);
962 i = net_write(nData->handle, buf, len);
963 }
964 if (i == -1)
965 return 0;
966 nData->xfered += i;
967 if (nData->idlecb && nData->cbbytes)
968 {
969 nData->xfered1 += i;
970 if (nData->xfered1 > nData->cbbytes)
971 {
972 nData->idlecb(nData, nData->xfered, nData->idlearg);
973 nData->xfered1 = 0;
974 }
975 }
976 return i;
977}
978
979/*
980 * FtpClose - close a data connection
981 */
982GLOBALDEF int FtpClose(netbuf *nData)
983{
984 netbuf *ctrl;
985 switch (nData->dir)
986 {
987 case FTPLIB_WRITE:
988 /* potential problem - if buffer flush fails, how to notify user? */
989 if (nData->buf != NULL)
990 writeline(NULL, 0, nData);
991 case FTPLIB_READ:
992 if (nData->buf)
993 free(nData->buf);
994 shutdown(nData->handle,2);
995 net_close(nData->handle);
996 ctrl = nData->ctrl;
997 free(nData);
998 if (ctrl)
999 {
1000 ctrl->data = NULL;
1001 return(readresp('2', ctrl));
1002 }
1003 return 1;
1004 case FTPLIB_CONTROL:
1005 if (nData->data)
1006 {
1007 nData->ctrl = NULL;
1008 FtpClose(nData);
1009 }
1010 net_close(nData->handle);
1011 free(nData);
1012 return 0;
1013 }
1014 return 1;
1015}
1016
1017/*
1018 * FtpSite - send a SITE command
1019 *
1020 * return 1 if command successful, 0 otherwise
1021 */
1022GLOBALDEF int FtpSite(const char *cmd, netbuf *nControl)
1023{
1024 char buf[256];
1025
1026 if ((strlen(cmd) + 7) > sizeof(buf))
1027 return 0;
1028 sprintf(buf,"SITE %s",cmd);
1029 if (!FtpSendCmd(buf,'2',nControl))
1030 return 0;
1031 return 1;
1032}
1033
1034/*
1035 * FtpSysType - send a SYST command
1036 *
1037 * Fills in the user buffer with the remote system type. If more
1038 * information from the response is required, the user can parse
1039 * it out of the response buffer returned by FtpLastResponse().
1040 *
1041 * return 1 if command successful, 0 otherwise
1042 */
1043GLOBALDEF int FtpSysType(char *buf, int max, netbuf *nControl)
1044{
1045 int l = max;
1046 char *b = buf;
1047 char *s;
1048 if (!FtpSendCmd("SYST",'2',nControl))
1049 return 0;
1050 s = &nControl->response[4];
1051 while ((--l) && (*s != ' '))
1052 *b++ = *s++;
1053 *b++ = '\0';
1054 return 1;
1055}
1056
1057/*
1058 * FtpMkdir - create a directory at server
1059 *
1060 * return 1 if successful, 0 otherwise
1061 */
1062GLOBALDEF int FtpMkdir(const char *path, netbuf *nControl)
1063{
1064 char buf[256];
1065
1066 if ((strlen(path) + 6) > sizeof(buf))
1067 return 0;
1068 sprintf(buf,"MKD %s",path);
1069 if (!FtpSendCmd(buf,'2', nControl))
1070 return 0;
1071 return 1;
1072}
1073
1074/*
1075 * FtpChdir - change path at remote
1076 *
1077 * return 1 if successful, 0 otherwise
1078 */
1079GLOBALDEF int FtpChdir(const char *path, netbuf *nControl)
1080{
1081 char buf[256];
1082
1083 if ((strlen(path) + 6) > sizeof(buf))
1084 return 0;
1085 sprintf(buf,"CWD %s",path);
1086 if (!FtpSendCmd(buf,'2',nControl))
1087 return 0;
1088 return 1;
1089}
1090
1091/*
1092 * FtpCDUp - move to parent directory at remote
1093 *
1094 * return 1 if successful, 0 otherwise
1095 */
1096GLOBALDEF int FtpCDUp(netbuf *nControl)
1097{
1098 if (!FtpSendCmd("CDUP",'2',nControl))
1099 return 0;
1100 return 1;
1101}
1102
1103/*
1104 * FtpRmdir - remove directory at remote
1105 *
1106 * return 1 if successful, 0 otherwise
1107 */
1108GLOBALDEF int FtpRmdir(const char *path, netbuf *nControl)
1109{
1110 char buf[256];
1111
1112 if ((strlen(path) + 6) > sizeof(buf))
1113 return 0;
1114 sprintf(buf,"RMD %s",path);
1115 if (!FtpSendCmd(buf,'2',nControl))
1116 return 0;
1117 return 1;
1118}
1119
1120/*
1121 * FtpPwd - get working directory at remote
1122 *
1123 * return 1 if successful, 0 otherwise
1124 */
1125GLOBALDEF int FtpPwd(char *path, int max, netbuf *nControl)
1126{
1127 int l = max;
1128 char *b = path;
1129 char *s;
1130 if (!FtpSendCmd("PWD",'2',nControl))
1131 return 0;
1132 s = strchr(nControl->response, '"');
1133 if (s == NULL)
1134 return 0;
1135 s++;
1136 while ((--l) && (*s) && (*s != '"'))
1137 *b++ = *s++;
1138 *b++ = '\0';
1139 return 1;
1140}
1141
1142/*
1143 * FtpXfer - issue a command and transfer data
1144 *
1145 * return 1 if successful, 0 otherwise
1146 */
1147static int FtpXfer(const char *localfile, const char *path,
1148 netbuf *nControl, int typ, int mode)
1149{
1150 int l,c;
1151 char *dbuf;
1152 FILE *local = NULL;
1153 netbuf *nData;
1154 int rv=1;
1155
1156 if (localfile != NULL)
1157 {
1158 char ac[4] = "w";
1159 if (typ == FTPLIB_FILE_WRITE)
1160 ac[0] = 'r';
1161 if (mode == FTPLIB_IMAGE)
1162 ac[1] = 'b';
1163 local = fopen(localfile, ac);
1164 if (local == NULL)
1165 {
1166 strncpy(nControl->response, strerror(errno),
1167 sizeof(nControl->response));
1168 return 0;
1169 }
1170 }
1171 if (local == NULL)
1172 local = (typ == FTPLIB_FILE_WRITE) ? stdin : stdout;
1173 if (!FtpAccess(path, typ, mode, nControl, &nData))
1174 return 0;
1175 dbuf = malloc(FTPLIB_BUFSIZ);
1176 if (typ == FTPLIB_FILE_WRITE)
1177 {
1178 while ((l = fread(dbuf, 1, FTPLIB_BUFSIZ, local)) > 0)
1179 if ((c = FtpWrite(dbuf, l, nData)) < l)
1180 {
1181 printf("short write: passed %d, wrote %d\n", l, c);
1182 rv = 0;
1183 break;
1184 }
1185 }
1186 else
1187 {
1188 while ((l = FtpRead(dbuf, FTPLIB_BUFSIZ, nData)) > 0)
1189 if (fwrite(dbuf, 1, l, local) <= 0)
1190 {
1191 perror("localfile write");
1192 rv = 0;
1193 break;
1194 }
1195 }
1196 free(dbuf);
1197 fflush(local);
1198 if (localfile != NULL)
1199 fclose(local);
1200 FtpClose(nData);
1201 return rv;
1202}
1203
1204/*
1205 * FtpNlst - issue an NLST command and write response to output
1206 *
1207 * return 1 if successful, 0 otherwise
1208 */
1209GLOBALDEF int FtpNlst(const char *outputfile, const char *path,
1210 netbuf *nControl)
1211{
1212 return FtpXfer(outputfile, path, nControl, FTPLIB_DIR, FTPLIB_ASCII);
1213}
1214
1215/*
1216 * FtpDir - issue a LIST command and write response to output
1217 *
1218 * return 1 if successful, 0 otherwise
1219 */
1220GLOBALDEF int FtpDir(const char *outputfile, const char *path, netbuf *nControl)
1221{
1222 return FtpXfer(outputfile, path, nControl, FTPLIB_DIR_VERBOSE, FTPLIB_ASCII);
1223}
1224
1225/*
1226 * FtpSize - determine the size of a remote file
1227 *
1228 * return 1 if successful, 0 otherwise
1229 */
1230GLOBALDEF int FtpSize(const char *path, int *size, char mode, netbuf *nControl)
1231{
1232 char cmd[256];
1233 int resp,sz,rv=1;
1234
1235 if ((strlen(path) + 7) > sizeof(cmd))
1236 return 0;
1237 sprintf(cmd, "TYPE %c", mode);
1238 if (!FtpSendCmd(cmd, '2', nControl))
1239 return 0;
1240 sprintf(cmd,"SIZE %s",path);
1241 if (!FtpSendCmd(cmd,'2',nControl))
1242 rv = 0;
1243 else
1244 {
1245 if (sscanf(nControl->response, "%d %d", &resp, &sz) == 2)
1246 *size = sz;
1247 else
1248 rv = 0;
1249 }
1250 return rv;
1251}
1252
1253/*
1254 * FtpModDate - determine the modification date of a remote file
1255 *
1256 * return 1 if successful, 0 otherwise
1257 */
1258GLOBALDEF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl)
1259{
1260 char buf[256];
1261 int rv = 1;
1262
1263 if ((strlen(path) + 7) > sizeof(buf))
1264 return 0;
1265 sprintf(buf,"MDTM %s",path);
1266 if (!FtpSendCmd(buf,'2',nControl))
1267 rv = 0;
1268 else
1269 strncpy(dt, &nControl->response[4], max);
1270 return rv;
1271}
1272
1273/*
1274 * FtpGet - issue a GET command and write received data to output
1275 *
1276 * return 1 if successful, 0 otherwise
1277 */
1278GLOBALDEF int FtpGet(const char *outputfile, const char *path,
1279 char mode, netbuf *nControl)
1280{
1281 return FtpXfer(outputfile, path, nControl, FTPLIB_FILE_READ, mode);
1282}
1283
1284/*
1285 * FtpPut - issue a PUT command and send data from input
1286 *
1287 * return 1 if successful, 0 otherwise
1288 */
1289GLOBALDEF int FtpPut(const char *inputfile, const char *path, char mode,
1290 netbuf *nControl)
1291{
1292 return FtpXfer(inputfile, path, nControl, FTPLIB_FILE_WRITE, mode);
1293}
1294
1295/*
1296 * FtpRename - rename a file at remote
1297 *
1298 * return 1 if successful, 0 otherwise
1299 */
1300GLOBALDEF int FtpRename(const char *src, const char *dst, netbuf *nControl)
1301{
1302 char cmd[256];
1303
1304 if (((strlen(src) + 7) > sizeof(cmd)) ||
1305 ((strlen(dst) + 7) > sizeof(cmd)))
1306 return 0;
1307 sprintf(cmd,"RNFR %s",src);
1308 if (!FtpSendCmd(cmd,'3',nControl))
1309 return 0;
1310 sprintf(cmd,"RNTO %s",dst);
1311 if (!FtpSendCmd(cmd,'2',nControl))
1312 return 0;
1313 return 1;
1314}
1315
1316/*
1317 * FtpDelete - delete a file at remote
1318 *
1319 * return 1 if successful, 0 otherwise
1320 */
1321GLOBALDEF int FtpDelete(const char *fnm, netbuf *nControl)
1322{
1323 char cmd[256];
1324
1325 if ((strlen(fnm) + 7) > sizeof(cmd))
1326 return 0;
1327 sprintf(cmd,"DELE %s",fnm);
1328 if (!FtpSendCmd(cmd,'2', nControl))
1329 return 0;
1330 return 1;
1331}
1332
1333/*
1334 * FtpQuit - disconnect from remote
1335 *
1336 * return 1 if successful, 0 otherwise
1337 */
1338GLOBALDEF void FtpQuit(netbuf *nControl)
1339{
1340 if (nControl->dir != FTPLIB_CONTROL)
1341 return;
1342 FtpSendCmd("QUIT",'2',nControl);
1343 net_close(nControl->handle);
1344 free(nControl->buf);
1345 free(nControl);
1346}
diff --git a/noncore/net/ftplib/ftplib.control b/noncore/net/ftplib/ftplib.control
new file mode 100644
index 0000000..67765ad
--- a/dev/null
+++ b/noncore/net/ftplib/ftplib.control
@@ -0,0 +1,9 @@
1Files: $QTDIR/lib/libftplib.*
2Priority: optional
3Section: Communications
4Maintainer: L.J. Potter <ljp@llornkcor.com>
5Architecture: arm
6Version: $QPE_VERSION-$SUB_VERSION
7Depends: opie-base ($QPE_VERSION)
8Description: Libftp
9 The ftp library for the Opie environment.
diff --git a/noncore/net/ftplib/ftplib.h b/noncore/net/ftplib/ftplib.h
new file mode 100644
index 0000000..75a90ae
--- a/dev/null
+++ b/noncore/net/ftplib/ftplib.h
@@ -0,0 +1,124 @@
1/***************************************************************************/
2/* ftplib.h - header file for callable ftp access routines */
3/* Copyright (C) 1996, 1997 Thomas Pfau, pfau@cnj.digex.net */
4/* 73 Catherine Street, South Bound Brook, NJ, 08880 */
5/* */
6/* This library is free software; you can redistribute it and/or */
7/* modify it under the terms of the GNU Library General Public */
8/* License as published by the Free Software Foundation; either */
9/* version 2 of the License, or (at your option) any later version. */
10/* */
11/* This library is distributed in the hope that it will be useful, */
12/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
14/* Library General Public License for more details. */
15/* */
16/* You should have received a copy of the GNU Library General Public */
17/* License along with this progam; if not, write to the */
18/* Free Software Foundation, Inc., 59 Temple Place - Suite 330, */
19/* Boston, MA 02111-1307, USA. */
20/* */
21/***************************************************************************/
22
23#if !defined(__FTPLIB_H)
24#define __FTPLIB_H
25
26#if defined(__unix__) || defined(VMS)
27#define GLOBALDEF
28#define GLOBALREF extern
29#elif defined(_WIN32)
30#if defined BUILDING_LIBRARY
31#define GLOBALDEF __declspec(dllexport)
32#define GLOBALREF __declspec(dllexport)
33#else
34#define GLOBALREF __declspec(dllimport)
35#endif
36#endif
37
38/* FtpAccess() type codes */
39#define FTPLIB_DIR 1
40#define FTPLIB_DIR_VERBOSE 2
41#define FTPLIB_FILE_READ 3
42#define FTPLIB_FILE_WRITE 4
43
44/* FtpAccess() mode codes */
45#define FTPLIB_ASCII 'A'
46#define FTPLIB_IMAGE 'I'
47#define FTPLIB_TEXT FTPLIB_ASCII
48#define FTPLIB_BINARY FTPLIB_IMAGE
49
50/* connection modes */
51#define FTPLIB_PASSIVE 1
52#define FTPLIB_PORT 2
53
54/* connection option names */
55#define FTPLIB_CONNMODE 1
56#define FTPLIB_CALLBACK 2
57#define FTPLIB_IDLETIME 3
58#define FTPLIB_CALLBACKARG 4
59#define FTPLIB_CALLBACKBYTES 5
60
61#ifdef __cplusplus
62extern "C" {
63#endif
64
65typedef struct NetBuf netbuf;
66typedef int (*FtpCallback)(netbuf *nControl, int xfered, void *arg);
67
68/* v1 compatibility stuff */
69#if !defined(_FTPLIB_NO_COMPAT)
70netbuf *DefaultNetbuf;
71
72#define ftplib_lastresp FtpLastResponse(DefaultNetbuf)
73#define ftpInit FtpInit
74#define ftpOpen(x) FtpConnect(x, &DefaultNetbuf)
75#define ftpLogin(x,y) FtpLogin(x, y, DefaultNetbuf)
76#define ftpSite(x) FtpSite(x, DefaultNetbuf)
77#define ftpMkdir(x) FtpMkdir(x, DefaultNetbuf)
78#define ftpChdir(x) FtpChdir(x, DefaultNetbuf)
79#define ftpRmdir(x) FtpRmdir(x, DefaultNetbuf)
80#define ftpNlst(x, y) FtpNlst(x, y, DefaultNetbuf)
81#define ftpDir(x, y) FtpDir(x, y, DefaultNetbuf)
82#define ftpGet(x, y, z) FtpGet(x, y, z, DefaultNetbuf)
83#define ftpPut(x, y, z) FtpPut(x, y, z, DefaultNetbuf)
84#define ftpRename(x, y) FtpRename(x, y, DefaultNetbuf)
85#define ftpDelete(x) FtpDelete(x, DefaultNetbuf)
86#define ftpQuit() FtpQuit(DefaultNetbuf)
87#endif /* (_FTPLIB_NO_COMPAT) */
88/* end v1 compatibility stuff */
89
90GLOBALREF int ftplib_debug;
91GLOBALREF void FtpInit(void);
92GLOBALREF char *FtpLastResponse(netbuf *nControl);
93GLOBALREF int FtpConnect(const char *host, netbuf **nControl);
94GLOBALREF int FtpOptions(int opt, long val, netbuf *nControl);
95GLOBALREF int FtpLogin(const char *user, const char *pass, netbuf *nControl);
96GLOBALREF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl,
97 netbuf **nData);
98GLOBALREF int FtpRead(void *buf, int max, netbuf *nData);
99GLOBALREF int FtpWrite(void *buf, int len, netbuf *nData);
100GLOBALREF int FtpClose(netbuf *nData);
101GLOBALREF int FtpSite(const char *cmd, netbuf *nControl);
102GLOBALREF int FtpSysType(char *buf, int max, netbuf *nControl);
103GLOBALREF int FtpMkdir(const char *path, netbuf *nControl);
104GLOBALREF int FtpChdir(const char *path, netbuf *nControl);
105GLOBALREF int FtpCDUp(netbuf *nControl);
106GLOBALREF int FtpRmdir(const char *path, netbuf *nControl);
107GLOBALREF int FtpPwd(char *path, int max, netbuf *nControl);
108GLOBALREF int FtpNlst(const char *output, const char *path, netbuf *nControl);
109GLOBALREF int FtpDir(const char *output, const char *path, netbuf *nControl);
110GLOBALREF int FtpSize(const char *path, int *size, char mode, netbuf *nControl);
111GLOBALREF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl);
112GLOBALREF int FtpGet(const char *output, const char *path, char mode,
113 netbuf *nControl);
114GLOBALREF int FtpPut(const char *input, const char *path, char mode,
115 netbuf *nControl);
116GLOBALREF int FtpRename(const char *src, const char *dst, netbuf *nControl);
117GLOBALREF int FtpDelete(const char *fnm, netbuf *nControl);
118GLOBALREF void FtpQuit(netbuf *nControl);
119
120#ifdef __cplusplus
121};
122#endif
123
124#endif /* __FTPLIB_H */
diff --git a/noncore/net/ftplib/ftplib.pro b/noncore/net/ftplib/ftplib.pro
new file mode 100644
index 0000000..9ee3605
--- a/dev/null
+++ b/noncore/net/ftplib/ftplib.pro
@@ -0,0 +1,6 @@
1TEMPLATE = lib
2CONFIG = qt warn_on release
3HEADERS = ftplib.h
4SOURCES = ftplib.c
5DESTDIR = $(QTDIR)/lib$(PROJMAK)
6INTERFACES =