fetch.c revision 40939
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: fetch.c,v 1.4 1998/08/17 09:30:19 des Exp $ 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 46int fetchLastErrCode; 47const char *fetchLastErrText; 48 49/* 50 * Select the appropriate protocol for the URL scheme, and return a 51 * read-only stream connected to the document referenced by the URL. 52 */ 53FILE * 54fetchGet(url_t *URL, char *flags) 55{ 56 if (strcasecmp(URL->scheme, "file") == 0) 57 return fetchGetFile(URL, flags); 58 else if (strcasecmp(URL->scheme, "http") == 0) 59 return fetchGetHTTP(URL, flags); 60 else if (strcasecmp(URL->scheme, "ftp") == 0) 61 return fetchGetFTP(URL, flags); 62 else return NULL; 63 64} 65 66/* 67 * Select the appropriate protocol for the URL scheme, and return a 68 * write-only stream connected to the document referenced by the URL. 69 */ 70FILE * 71fetchPut(url_t *URL, char *flags) 72{ 73 if (strcasecmp(URL->scheme, "file") == 0) 74 return fetchPutFile(URL, flags); 75 else if (strcasecmp(URL->scheme, "http") == 0) 76 return fetchPutHTTP(URL, flags); 77 else if (strcasecmp(URL->scheme, "ftp") == 0) 78 return fetchPutFTP(URL, flags); 79 else return NULL; 80} 81 82/* 83 * Attempt to parse the given URL; if successful, call fetchGet(). 84 */ 85FILE * 86fetchGetURL(char *URL, char *flags) 87{ 88 url_t *u; 89 FILE *f; 90 91 if ((u = fetchParseURL(URL)) == NULL) 92 return NULL; 93 94 f = fetchGet(u, flags); 95 96 free(u); 97 return f; 98} 99 100 101/* 102 * Attempt to parse the given URL; if successful, call fetchPut(). 103 */ 104FILE * 105fetchPutURL(char *URL, char *flags) 106{ 107 url_t *u; 108 FILE *f; 109 110 if ((u = fetchParseURL(URL)) == NULL) 111 return NULL; 112 113 f = fetchPut(u, flags); 114 115 free(u); 116 return f; 117} 118 119/* 120 * Split an URL into components. URL syntax is: 121 * method:[//[user[:pwd]@]host[:port]]/[document] 122 * This almost, but not quite, RFC1738 URL syntax. 123 */ 124url_t * 125fetchParseURL(char *URL) 126{ 127 char *p, *q; 128 url_t *u; 129 int i; 130 131 /* allocate url_t */ 132 if ((u = calloc(1, sizeof(url_t))) == NULL) 133 return NULL; 134 135 /* scheme name */ 136 for (i = 0; *URL && (*URL != ':'); URL++) 137 if (i < URL_SCHEMELEN) 138 u->scheme[i++] = *URL; 139 if (!URL[0] || (URL[1] != '/')) 140 goto ouch; 141 else URL++; 142 if (URL[1] != '/') { 143 p = URL; 144 goto nohost; 145 } 146 else URL += 2; 147 148 p = strpbrk(URL, "/@"); 149 if (*p == '@') { 150 /* username */ 151 for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++) 152 if (i < URL_USERLEN) 153 u->user[i++] = *q; 154 155 /* password */ 156 if (*q == ':') 157 for (q++, i = 0; (*q != ':') && (*q != '@'); q++) 158 if (i < URL_PWDLEN) 159 u->pwd[i++] = *q; 160 161 p++; 162 } else p = URL; 163 164 /* hostname */ 165 for (i = 0; *p && (*p != '/') && (*p != ':'); p++) 166 if (i < MAXHOSTNAMELEN) 167 u->host[i++] = *p; 168 169 /* port */ 170 if (*p == ':') { 171 for (q = ++p; *q && (*q != '/'); q++) 172 if (isdigit(*q)) 173 u->port = u->port * 10 + (*q - '0'); 174 else return 0; /* invalid port */ 175 while (*p && (*p != '/')) 176 p++; 177 } 178 179nohost: 180 /* document */ 181 if (*p) { 182 url_t *t; 183 t = realloc(u, sizeof(*u)+strlen(p)-1); 184 if (t == NULL) 185 goto ouch; 186 u = t; 187 strcpy(u->doc, p); 188 } else { 189 u->doc[0] = '/'; 190 u->doc[1] = 0; 191 } 192 193 DEBUG(fprintf(stderr, 194 "scheme: [\033[1m%s\033[m]\n" 195 "user: [\033[1m%s\033[m]\n" 196 "password: [\033[1m%s\033[m]\n" 197 "host: [\033[1m%s\033[m]\n" 198 "port: [\033[1m%d\033[m]\n" 199 "document: [\033[1m%s\033[m]\n", 200 u->scheme, u->user, u->pwd, 201 u->host, u->port, u->doc)); 202 203 return u; 204 205ouch: 206 free(u); 207 return NULL; 208} 209