fetch.c revision 37535
1/*- 2 * Copyright (c) 1998 Dag-Erling Co�dan Sm�rgrav 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer 10 * in this position and unchanged. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 * 28 * $Id$ 29 */ 30 31#include <sys/param.h> 32 33#include <ctype.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37 38#include "fetch.h" 39 40#ifndef NDEBUG 41#define DEBUG(x) do x; while (0) 42#else 43#define DEBUG(x) do { } while (0) 44#endif 45 46 47/* get URL */ 48FILE * 49fetchGetURL(char *URL, char *flags) 50{ 51 url_t *u; 52 FILE *f; 53 54 /* parse URL */ 55 if ((u = fetchParseURL(URL)) == NULL) 56 return NULL; 57 58 /* select appropriate function */ 59 if (strcasecmp(u->scheme, "file") == 0) 60 f = fetchGetFile(u, flags); 61 else if (strcasecmp(u->scheme, "http") == 0) 62 f = fetchGetHTTP(u, flags); 63 else if (strcasecmp(u->scheme, "ftp") == 0) 64 f = fetchGetFTP(u, flags); 65 else f = NULL; 66 67 fetchFreeURL(u); 68 return f; 69} 70 71 72/* put URL */ 73FILE * 74fetchPutURL(char *URL, char *flags) 75{ 76 url_t *u; 77 FILE *f; 78 79 /* parse URL */ 80 if ((u = fetchParseURL(URL)) == NULL) 81 return NULL; 82 83 /* select appropriate function */ 84 if (strcasecmp(u->scheme, "file") == 0) 85 f = fetchPutFile(u, flags); 86 else if (strcasecmp(u->scheme, "http") == 0) 87 f = fetchPutHTTP(u, flags); 88 else if (strcasecmp(u->scheme, "ftp") == 0) 89 f = fetchPutFTP(u, flags); 90 else f = NULL; 91 92 fetchFreeURL(u); 93 return f; 94} 95 96/* 97 * Split an URL into components. URL syntax is: 98 * method:[//[user[:pwd]@]host[:port]]/[document] 99 * This almost, but not quite, RFC1738 URL syntax. 100 */ 101url_t * 102fetchParseURL(char *URL) 103{ 104 char *p, *q; 105 url_t *u; 106 int i; 107 108 /* allocate url_t */ 109 if ((u = calloc(1, sizeof(url_t))) == NULL) 110 return NULL; 111 112 /* scheme name */ 113 for (i = 0; *URL && (*URL != ':'); URL++) 114 if (i < URL_SCHEMELEN) 115 u->scheme[i++] = *URL; 116 if (!URL[0] || (URL[1] != '/')) 117 goto ouch; 118 else URL++; 119 if (URL[1] != '/') { 120 p = URL; 121 goto nohost; 122 } 123 else URL += 2; 124 125 p = strpbrk(URL, "/@"); 126 if (*p == '@') { 127 /* username */ 128 for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++) 129 if (i < URL_USERLEN) 130 u->user[i++] = *q; 131 132 /* password */ 133 if (*q == ':') 134 for (q++, i = 0; (*q != ':') && (*q != '@'); q++) 135 if (i < URL_PWDLEN) 136 u->pwd[i++] = *q; 137 138 p++; 139 } else p = URL; 140 141 /* hostname */ 142 for (i = 0; *p && (*p != '/') && (*p != ':'); p++) 143 if (i < MAXHOSTNAMELEN) 144 u->host[i++] = *p; 145 146 /* port */ 147 if (*p == ':') { 148 for (q = ++p; *q && (*q != '/'); q++) 149 if (isdigit(*q)) 150 u->port = u->port * 10 + (*q - '0'); 151 else return 0; /* invalid port */ 152 while (*p && (*p != '/')) 153 p++; 154 } 155 156nohost: 157 /* document */ 158 if (*p) 159 u->doc = strdup(p); 160 u->doc = strdup(*p ? p : "/"); 161 if (!u->doc) 162 goto ouch; 163 164 DEBUG(fprintf(stderr, 165 "scheme: [\033[1m%s\033[m]\n" 166 "user: [\033[1m%s\033[m]\n" 167 "password: [\033[1m%s\033[m]\n" 168 "host: [\033[1m%s\033[m]\n" 169 "port: [\033[1m%d\033[m]\n" 170 "document: [\033[1m%s\033[m]\n", 171 u->scheme, u->user, u->pwd, 172 u->host, u->port, u->doc)); 173 174 return u; 175 176ouch: 177 free(u); 178 return NULL; 179} 180 181void 182fetchFreeURL(url_t *u) 183{ 184 if (u) { 185 if (u->doc) 186 free(u->doc); 187 free(u); 188 } 189} 190