source: trunk/minix/commands/urlget/urlget.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 12.2 KB
RevLine 
[9]1/* urlget.c Copyright 2000 by Michael Temari All Rights Reserved */
2/* 04/05/2000 Michael Temari <Michael@TemWare.Com> */
3
4#include <sys/types.h>
5#include <sys/ioctl.h>
6#include <sys/wait.h>
7#include <stdio.h>
8#include <ctype.h>
9#include <stdlib.h>
10#include <string.h>
11#include <errno.h>
12#include <fcntl.h>
13#include <signal.h>
14#include <unistd.h>
15#include <time.h>
16
17#include "net.h"
18
19_PROTOTYPE(char *unesc, (char *s));
20_PROTOTYPE(void encode64, (char **pp, char *s));
21_PROTOTYPE(char *auth, (char *user, char *pass));
22_PROTOTYPE(int skipit, (char *buf, int len, int *skip));
23_PROTOTYPE(int httpget, (char *host, int port, char *user, char *pass, char *path, int headers, int discard, int post));
24_PROTOTYPE(void ftppasv, (char *reply));
25_PROTOTYPE(int ftpreply, (FILE *fpr));
26_PROTOTYPE(int ftpcmd, (FILE *fpw, FILE *fpr, char *cmd, char *arg));
27_PROTOTYPE(int ftpget, (char *host, int port, char *user, char *pass, char *path, int type));
28_PROTOTYPE(int tcpget, (char *host, int port, char *user, char *pass, char *path));
29_PROTOTYPE(int main, (int argc, char *argv[]));
30
31char ftpphost[15+1];
32unsigned int ftppport;
33
34#define SCHEME_HTTP 1
35#define SCHEME_FTP 2
36#define SCHEME_TCP 3
37#define SCHEME_NNTP 4
38
39char buffer[16000];
40
41#if 0
42_PROTOTYPE(int strncasecmp, (const char *s1, const char *s2, size_t len));
43int
44strncasecmp(s1, s2, len)
45const char *s1, *s2;
46size_t len;
47{
48 int c1, c2;
49 do {
50 if (len == 0)
51 return 0;
52 len--;
53 } while (c1= toupper(*s1++), c2= toupper(*s2++), c1 == c2 && (c1 & c2))
54 ;
55 if (c1 & c2)
56 return c1 < c2 ? -1 : 1;
57 return c1 ? 1 : (c2 ? -1 : 0);
58}
59#endif
60
61char *unesc(s)
62char *s;
63{
64char *p;
65char *p2;
66unsigned char c;
67
68 p = s;
69 p2 = s;
70 while(*p) {
71 if(*p != '%') {
72 *p2++ = *p++;
73 continue;
74 }
75 p++;
76 if(*p == '%') {
77 *p2++ = *p++;
78 continue;
79 }
80 if(*p >= '0' && *p <= '9') c = *p++ - '0'; else
81 if(*p >= 'a' && *p <= 'f') c = *p++ - 'a' + 10; else
82 if(*p >= 'A' && *p <= 'F') c = *p++ - 'A' + 10; else
83 break;
84 if(*p >= '0' && *p <= '9') c = c << 4 | (*p++ - '0'); else
85 if(*p >= 'a' && *p <= 'f') c = c << 4 | (*p++ - 'a') + 10; else
86 if(*p >= 'A' && *p <= 'F') c = c << 4 | (*p++ - 'A') + 10; else
87 break;
88 *p2++ = c;
89 }
90 *p2 = '\0';
91 return(s);
92}
93
94void encode64(pp, s)
95char **pp;
96char *s;
97{
98char *p;
99char c[3];
100int i;
101int len;
102static char e64[64] = {
103 'A','B','C','D','E','F','G','H','I','J','K','L','M',
104 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
105 'a','b','c','d','e','f','g','h','i','j','k','l','m',
106 'n','o','p','q','r','s','t','u','v','w','x','y','z',
107 '0','1','2','3','4','5','6','7','8','9','+','/' };
108
109 p = *pp;
110 len = strlen(s);
111 for(i=0; i < len; i += 3) {
112 c[0] = *s++;
113 c[1] = *s++;
114 c[2] = *s++;
115 *p++ = e64[ c[0] >> 2];
116 *p++ = e64[((c[0] << 4) & 0x30) | ((c[1] >> 4) & 0x0f)];
117 *p++ = e64[((c[1] << 2) & 0x3c) | ((c[2] >> 6) & 0x03)];
118 *p++ = e64[ c[2] & 0x3f];
119 }
120 if(i == len+1)
121 p[-1] = '=';
122 else
123 if(i == len+2) {
124 p[-1] = '=';
125 p[-2] = '=';
126 }
127 *p = '\0';
128 *pp = p;
129 return;
130}
131
132char *auth(user, pass)
133char *user;
134char *pass;
135{
136static char a[128];
137char up[128];
138char *p;
139
140 strcpy(a, "BASIC ");
141 p = a + 6;
142 sprintf(up, "%s:%s", user, pass);
143 encode64(&p, up);
144
145 return(a);
146}
147
148int skipit(buf, len, skip)
149char *buf;
150int len;
151int *skip;
152{
153static int lf = 0;
154static int crlf = 0;
155char *p;
156
157 p = buf;
158
159 while(--len >= 0) {
160 if((crlf == 0 || crlf == 2) && *p == '\r')
161 crlf++;
162 else
163 if((crlf == 1 || crlf == 3) && *p == '\n')
164 crlf++;
165 else
166 crlf = 0;
167 if(*p == '\n')
168 lf++;
169 else
170 lf = 0;
171 if(crlf == 4 || lf == 2) {
172 *skip = 0;
173 return(len);
174 }
175 p++;
176 }
177
178 return(0);
179}
180
181int httpget(host, port, user, pass, path, headers, discard, post)
182char *host;
183int port;
184char *user;
185char *pass;
186char *path;
187int headers;
188int discard;
189int post;
190{
191int fd;
192int skip;
193int s;
194int s2;
195char *a;
196char *qs;
197int len;
198
199 if(port == 0)
200 port = 80;
201
202 fd = connect(host, port);
203 if(fd < 0) {
204 fprintf(stderr, "httpget: Could not connect to %s:%d\n", host, port);
205 return(-1);
206 }
207
208 if(post) {
209 qs = strrchr(path, '?');
210 if(qs != (char *)NULL) {
211 *qs++ = '\0';
212 len = strlen(qs);
213 } else
214 len = 0;
215 }
216
217 if(post && len > 0)
218 write(fd, "POST ", 5);
219 else
220 write(fd, "GET ", 4);
221 write(fd, path, strlen(path));
222 write(fd, " HTTP/1.0\r\n", 11);
223 write(fd, "User-Agent: urlget\r\n", 20);
224 write(fd, "Connection: Close\r\n", 19);
225 if(*user) {
226 write(fd, "Authorization: ", 15);
227 a = auth(user, pass);
228 write(fd, a, strlen(a));
229 write(fd, "\r\n", 2);
230 }
231 if(post && len > 0) {
232 sprintf(buffer, "Content-Length: %u\r\n", len);
233 write(fd, buffer, strlen(buffer));
234 }
235 write(fd, "Host: ", 6);
236 write(fd, host, strlen(host));
237 write(fd, "\r\n", 2);
238 write(fd, "\r\n", 2);
239 if(post && len > 0)
240 write(fd, qs, len);
241
242 skip = 1;
243 while((s = read(fd, buffer, sizeof(buffer)-1)) > 0) {
244 buffer[s] = '\0';
245 if(skip) {
246 static int firstline = 1;
247 if(firstline) {
248 static char linebuf[1000];
249 int l = 0;
250 int c, v1, v2, e;
251 if(s >= sizeof(linebuf)-l)
252 c = sizeof(linebuf)-1-l;
253 else c = s;
254 memcpy(linebuf+l, buffer, c);
255 linebuf[l+c] = '\0';
256 if(strchr(buffer, '\n') || strchr(buffer, '\r'))
257 firstline = 0;
258 if(sscanf(linebuf, "HTTP/%d.%d %d ", &v1, &v2, &e) == 3
259 && e != 200) {
260 fprintf(stderr, "HTTP error %d\n", e);
261 return -1;
262 }
263 }
264
265 s2 = skipit(buffer, s, &skip);
266 if(headers)
267 write(1, buffer, s - s2);
268 } else
269 s2 = s;
270 if(s2 && !discard)
271 if(write(1, &buffer[s - s2], s2) != s2) {
272 perror("write");
273 return(-1);
274 }
275 }
276 if(s < 0) {
277 fprintf(stderr, "httpget: Read error\n");
278 return(-1);
279 }
280
281 close(fd);
282
283 return(0);
284}
285
286void ftppasv(reply)
287char *reply;
288{
289char *p;
290unsigned char n[6];
291int i;
292
293 ftppport = 0;
294
295 p = reply;
296 while(*p && *p != '(') p++;
297 if(!*p) return;
298 p++;
299 i = 0;
300 while(1) {
301 n[i++] = atoi(p);
302 if(i == 6) break;
303 p = strchr(p, ',');
304 if(p == (char *)NULL) return;
305 p++;
306 }
307 sprintf(ftpphost, "%d.%d.%d.%d", n[0], n[1], n[2], n[3]);
308 ftppport = n[4] * 256 + n[5];
309 return;
310}
311
312int ftpreply(fpr)
313FILE *fpr;
314{
315static char reply[256];
316int s;
317char code[4];
318int ft;
319
320 do {
321 ft = 1;
322 do {
323 if(fgets(reply, sizeof(reply), fpr) == (char *)NULL)
324 return(-1);
325 if(ft) {
326 ft = 0;
327 strncpy(code, reply, 3);
328 code[3] = '\0';
329 }
330 } while(strncmp(reply, code, 3) || reply[3] == '-');
331 s = atoi(code);
332 } while(s < 200 && s != 125 && s != 150);
333 if(s == 227) ftppasv(reply);
334 return(s);
335}
336
337int ftpcmd(fpw, fpr, cmd, arg)
338FILE *fpw;
339FILE *fpr;
340char *cmd;
341char *arg;
342{
343 fprintf(fpw, "%s%s%s\r\n", cmd, *arg ? " " : "", arg);
344 fflush(fpw);
345 return(ftpreply(fpr));
346}
347
348int ftpget(host, port, user, pass, path, type)
349char *host;
350int port;
351char *user;
352char *pass;
353char *path;
354int type;
355{
356int fd;
357int fd2;
358FILE *fpr;
359FILE *fpw;
360int s;
361int s2;
362char *p;
363char *p2;
364char typec[2];
365
366 if(port == 0)
367 port = 21;
368
369 if(type == '\0')
370 type = 'i';
371
372 fd = connect(host, port);
373 if(fd < 0) {
374 fprintf(stderr, "ftpget: Could not connect to %s:%d\n", host, port);
375 return(-1);
376 }
377 fpr = fdopen(fd, "r");
378 fpw = fdopen(fd, "w");
379
380 s = ftpreply(fpr);
381 if(s / 100 != 2) goto error;
382 s = ftpcmd(fpw, fpr, "USER", *user ? user : "ftp");
383 if(s / 100 == 3)
384 s = ftpcmd(fpw, fpr, "PASS", *pass ? pass : "urlget@");
385
386 if(s / 100 != 2) goto error;
387
388 p = path;
389 if(*p == '/') p++;
390 while((p2 = strchr(p, '/')) != (char *)NULL) {
391 *p2++ = '\0';
392 s = ftpcmd(fpw, fpr, "CWD", unesc(p));
393 p = p2;
394 }
395 sprintf(typec, "%c", type == 'd' ? 'A' : type);
396 s = ftpcmd(fpw, fpr, "TYPE", typec);
397 if(s / 100 != 2) goto error;
398 s = ftpcmd(fpw, fpr, "PASV", "");
399 if(s != 227) goto error;
400 fd2 = connect(ftpphost, ftppport);
401 if(fd2 < 0) goto error;
402 s = ftpcmd(fpw, fpr, type == 'd' ? "NLST" : "RETR", unesc(p));
403 if(s / 100 != 1) goto error;
404 while((s = read(fd2, buffer, sizeof(buffer))) > 0) {
405 s2 = write(1, buffer, s);
406 if(s2 != s) break;
407 }
408 if(s2 != s && s != 0) s = -1;
409 close(fd2);
410
411 s = ftpreply(fpr);
412 if(s / 100 == 2) s = 0;
413
414error:
415 (void) ftpcmd(fpw, fpr, "QUIT", "");
416
417 fclose(fpr);
418 fclose(fpw);
419 close(fd);
420
421 return(s == 0 ? 0 : -1);
422}
423
424int tcpget(host, port, user, pass, path)
425char *host;
426int port;
427char *user;
428char *pass;
429char *path;
430{
431int fd;
432int s;
433int s2;
434
435 if(port == 0) {
436 fprintf(stderr, "tcpget: No port specified\n");
437 return(-1);
438 }
439
440 fd = connect(host, port);
441 if(fd < 0) {
442 fprintf(stderr, "httpget: Could not connect to %s:%d\n", host, port);
443 return(-1);
444 }
445 if(*path == '\/')
446 path++;
447
448 write(fd, path, strlen(path));
449 write(fd, "\n", 1);
450 while((s = read(fd, buffer, sizeof(buffer))) > 0) {
451 s2 = write(1, buffer, s);
452 if(s2 != s) break;
453 }
454 close(fd);
455 return(0);
456}
457
458int main(argc, argv)
459int argc;
460char *argv[];
461{
462char *prog;
463char *url;
464char scheme;
465char user[64];
466char pass[64];
467char host[64];
468int port;
469char *path;
470int type;
471char *ps;
472char *p;
473char *at;
474int s, c;
475int opt_h = 0;
476int opt_d = 0;
477int opt_p = 0;
478
479 prog = strrchr(*argv, '/');
480 if(prog == (char *)NULL)
481 prog = *argv;
482 argv++;
483 argc--;
484
485 while(argc && argv[0][0] == '-') {
486 char *opt = *argv++ + 1;
487 argc--;
488
489 if (opt[0] == '-' && opt[1] == 0) break;
490
491 while (*opt) switch (*opt++) {
492 case 'h': opt_h = -1; break;
493 case 'd': opt_d = -1; break;
494 case 'p': opt_p = -1; break;
495 default: argc = 0; break;
496 }
497 }
498
499 if(strcmp(prog, "ftpget") == 0) {
500 if(argc < 2 || argc > 4) {
501 fprintf(stderr, "Usage: %s host path [user [pass]]\n", prog);
502 return(-1);
503 }
504 strncpy(host, *argv++, sizeof(host));
505 port = 21;
506 path = *argv++;
507 if(argc) {
508 strncpy(user, *argv++, sizeof(user));
509 argc++;
510 } else
511 *user = '\0';
512 if(argc) {
513 strncpy(pass, *argv++, sizeof(pass));
514 argc++;
515 } else
516 *pass = '\0';
517 s = ftpget(host, port, user, path, path, 'i');
518 return(s);
519 }
520 if(strcmp(prog, "httpget") == 0) {
521 if(argc != 2) {
522 fprintf(stderr, "Usage: %s [-h] [-d] [-p] host path\n", prog);
523 return(-1);
524 }
525 strncpy(host, *argv++, sizeof(host));
526 port = 80;
527 path = *argv++;
528 s = httpget(host, port, user, path, path, opt_h, opt_d, opt_p);
529 return(s);
530 }
531
532 if(argc != 1) {
533 usage:
534 fprintf(stderr, "Usage: %s [-h] [-p] url\n", prog);
535 return(-1);
536 }
537
538 url = *argv++;
539 argc--;
540
541 if(strncasecmp(url, "http://", 7) == 0) {
542 scheme = SCHEME_HTTP;
543 ps = url + 7;
544 } else
545 if(strncasecmp(url, "ftp://", 6) == 0) {
546 scheme = SCHEME_FTP;
547 ps = url + 6;
548 } else
549 if(strncasecmp(url, "tcp://", 6) == 0) {
550 scheme = SCHEME_TCP;
551 ps = url + 6;
552 } else {
553 fprintf(stderr, "%s: I do not handle this scheme\n", prog);
554 return(-1);
555 }
556
557 user[0] = '\0';
558 pass[0] = '\0';
559 host[0] = '\0';
560 port = 0;
561
562 p = ps;
563 while(*p && *p != '/') p++;
564 path = p;
565 c = *path;
566 *path = '\0';
567
568 at = strchr(ps, '@');
569 if(at != (char *)NULL) {
570 *at = '\0';
571 p = ps;
572 while(*p && *p != ':') p++;
573 if(*p)
574 *p++ = '\0';
575 strcpy(user, ps);
576 strcpy(pass, p);
577 ps = at + 1;
578 }
579
580 *path = c;
581 p = ps;
582 while(*p && *p != '/' && *p != ':') p++;
583 strncpy(host, ps, p - ps);
584 host[p - ps] = '\0';
585 if(*p == ':') {
586 p++;
587 ps = p;
588 while(*p && *p != '/')
589 port = port * 10 + (*p++ - '0');
590 }
591 if(*p == '/')
592 path = p;
593 else
594 path = "/";
595 if(scheme == SCHEME_FTP) {
596 p = path;
597 while(*p && *p != ';') p++;
598 if(*p) {
599 *p++ = '\0';
600 if(strncasecmp(p, "type=", 5) == 0) {
601 p += 5;
602 type = tolower(*p);
603 }
604 }
605 }
606
607#if 0
608 fprintf(stderr, "Host: %s\n", host);
609 fprintf(stderr, "Port: %d\n", port);
610 fprintf(stderr, "User: %s\n", user);
611 fprintf(stderr, "Pass: %s\n", pass);
612 fprintf(stderr, "Path: %s\n", path);
613 fprintf(stderr, "Type: %c\n", type);
614#endif
615
616 switch(scheme) {
617 case SCHEME_HTTP:
618 s = httpget(host, port, user, pass, path, opt_h, opt_d, opt_p);
619 break;
620 case SCHEME_FTP:
621 s = ftpget(host, port, user, pass, path, type);
622 break;
623 case SCHEME_TCP:
624 s = tcpget(host, port, user, pass, path);
625 break;
626 }
627
628 return(s);
629}
Note: See TracBrowser for help on using the repository browser.