author | llornkcor <llornkcor> | 2002-11-09 15:27:29 (UTC) |
---|---|---|
committer | llornkcor <llornkcor> | 2002-11-09 15:27:29 (UTC) |
commit | fee37fd9a7c038dbf5cce74172721ca3cdc8745b (patch) (unidiff) | |
tree | dc9ed0da618d4ef6e96777e992cfc88fa619656c /noncore/net/ftplib | |
parent | d5d079c5bfaa10c310628d1ef7905d98b64dfa81 (diff) | |
download | opie-fee37fd9a7c038dbf5cce74172721ca3cdc8745b.zip opie-fee37fd9a7c038dbf5cce74172721ca3cdc8745b.tar.gz opie-fee37fd9a7c038dbf5cce74172721ca3cdc8745b.tar.bz2 |
move ftp stuff from opieftp to shared lib
-rw-r--r-- | noncore/net/ftplib/ftplib.c | 1346 | ||||
-rw-r--r-- | noncore/net/ftplib/ftplib.control | 9 | ||||
-rw-r--r-- | noncore/net/ftplib/ftplib.h | 124 | ||||
-rw-r--r-- | noncore/net/ftplib/ftplib.pro | 6 |
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 | |||
83 | struct 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 | |||
101 | static char *version = | ||
102 | "ftplib Release 3.1-1 9/16/00, copyright 1996-2000 Thomas Pfau"; | ||
103 | |||
104 | GLOBALDEF 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 | */ | ||
120 | void *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 | */ | ||
141 | char *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 | */ | ||
157 | static 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 | */ | ||
196 | static 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 | */ | ||
272 | static 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 | */ | ||
333 | static 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 | */ | ||
368 | GLOBALDEF 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 | */ | ||
383 | GLOBALDEF 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 | */ | ||
395 | GLOBALDEF 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 | */ | ||
543 | GLOBALDEF 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 | */ | ||
583 | static 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 | */ | ||
606 | GLOBALDEF 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 | */ | ||
629 | static 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 | */ | ||
776 | static 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 | */ | ||
848 | GLOBALDEF 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 | */ | ||
919 | GLOBALDEF 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 | */ | ||
952 | GLOBALDEF 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 | */ | ||
982 | GLOBALDEF 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 | */ | ||
1022 | GLOBALDEF 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 | */ | ||
1043 | GLOBALDEF 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 | */ | ||
1062 | GLOBALDEF 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 | */ | ||
1079 | GLOBALDEF 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 | */ | ||
1096 | GLOBALDEF 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 | */ | ||
1108 | GLOBALDEF 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 | */ | ||
1125 | GLOBALDEF 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 | */ | ||
1147 | static 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 | */ | ||
1209 | GLOBALDEF 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 | */ | ||
1220 | GLOBALDEF 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 | */ | ||
1230 | GLOBALDEF 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 | */ | ||
1258 | GLOBALDEF 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 | */ | ||
1278 | GLOBALDEF 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 | */ | ||
1289 | GLOBALDEF 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 | */ | ||
1300 | GLOBALDEF 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 | */ | ||
1321 | GLOBALDEF 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 | */ | ||
1338 | GLOBALDEF 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 @@ | |||
1 | Files: $QTDIR/lib/libftplib.* | ||
2 | Priority: optional | ||
3 | Section: Communications | ||
4 | Maintainer: L.J. Potter <ljp@llornkcor.com> | ||
5 | Architecture: arm | ||
6 | Version: $QPE_VERSION-$SUB_VERSION | ||
7 | Depends: opie-base ($QPE_VERSION) | ||
8 | Description: 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 | ||
62 | extern "C" { | ||
63 | #endif | ||
64 | |||
65 | typedef struct NetBuf netbuf; | ||
66 | typedef int (*FtpCallback)(netbuf *nControl, int xfered, void *arg); | ||
67 | |||
68 | /* v1 compatibility stuff */ | ||
69 | #if !defined(_FTPLIB_NO_COMPAT) | ||
70 | netbuf *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 | |||
90 | GLOBALREF int ftplib_debug; | ||
91 | GLOBALREF void FtpInit(void); | ||
92 | GLOBALREF char *FtpLastResponse(netbuf *nControl); | ||
93 | GLOBALREF int FtpConnect(const char *host, netbuf **nControl); | ||
94 | GLOBALREF int FtpOptions(int opt, long val, netbuf *nControl); | ||
95 | GLOBALREF int FtpLogin(const char *user, const char *pass, netbuf *nControl); | ||
96 | GLOBALREF int FtpAccess(const char *path, int typ, int mode, netbuf *nControl, | ||
97 | netbuf **nData); | ||
98 | GLOBALREF int FtpRead(void *buf, int max, netbuf *nData); | ||
99 | GLOBALREF int FtpWrite(void *buf, int len, netbuf *nData); | ||
100 | GLOBALREF int FtpClose(netbuf *nData); | ||
101 | GLOBALREF int FtpSite(const char *cmd, netbuf *nControl); | ||
102 | GLOBALREF int FtpSysType(char *buf, int max, netbuf *nControl); | ||
103 | GLOBALREF int FtpMkdir(const char *path, netbuf *nControl); | ||
104 | GLOBALREF int FtpChdir(const char *path, netbuf *nControl); | ||
105 | GLOBALREF int FtpCDUp(netbuf *nControl); | ||
106 | GLOBALREF int FtpRmdir(const char *path, netbuf *nControl); | ||
107 | GLOBALREF int FtpPwd(char *path, int max, netbuf *nControl); | ||
108 | GLOBALREF int FtpNlst(const char *output, const char *path, netbuf *nControl); | ||
109 | GLOBALREF int FtpDir(const char *output, const char *path, netbuf *nControl); | ||
110 | GLOBALREF int FtpSize(const char *path, int *size, char mode, netbuf *nControl); | ||
111 | GLOBALREF int FtpModDate(const char *path, char *dt, int max, netbuf *nControl); | ||
112 | GLOBALREF int FtpGet(const char *output, const char *path, char mode, | ||
113 | netbuf *nControl); | ||
114 | GLOBALREF int FtpPut(const char *input, const char *path, char mode, | ||
115 | netbuf *nControl); | ||
116 | GLOBALREF int FtpRename(const char *src, const char *dst, netbuf *nControl); | ||
117 | GLOBALREF int FtpDelete(const char *fnm, netbuf *nControl); | ||
118 | GLOBALREF 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 @@ | |||
1 | TEMPLATE = lib | ||
2 | CONFIG = qt warn_on release | ||
3 | HEADERS = ftplib.h | ||
4 | SOURCES = ftplib.c | ||
5 | DESTDIR = $(QTDIR)/lib$(PROJMAK) | ||
6 | INTERFACES = | ||