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 *
| 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 *
|
29 */ 30 31#include <sys/param.h> 32#include <sys/errno.h> 33 34#include <ctype.h> 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38 39#include "fetch.h" 40#include "common.h" 41 42 43int fetchLastErrCode; 44int fetchTimeout; 45 46 47/*** Local data **************************************************************/ 48 49/* 50 * Error messages for parser errors 51 */ 52#define URL_MALFORMED 1 53#define URL_BAD_SCHEME 2 54#define URL_BAD_PORT 3 55static struct fetcherr _url_errlist[] = { 56 { URL_MALFORMED, FETCH_URL, "Malformed URL" }, 57 { URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" }, 58 { URL_BAD_PORT, FETCH_URL, "Invalid server port" }, 59 { -1, FETCH_UNKNOWN, "Unknown parser error" } 60}; 61 62 63/*** Public API **************************************************************/ 64 65/* 66 * Select the appropriate protocol for the URL scheme, and return a 67 * read-only stream connected to the document referenced by the URL. 68 */ 69FILE * 70fetchGet(struct url *URL, char *flags) 71{ 72 int direct; 73 74 direct = (flags && strchr(flags, 'd')); 75 if (strcasecmp(URL->scheme, "file") == 0) 76 return fetchGetFile(URL, flags); 77 else if (strcasecmp(URL->scheme, "http") == 0) 78 return fetchGetHTTP(URL, flags); 79 else if (strcasecmp(URL->scheme, "ftp") == 0) { 80 if (!direct && 81 getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 82 return fetchGetHTTP(URL, flags); 83 return fetchGetFTP(URL, flags); 84 } else { 85 _url_seterr(URL_BAD_SCHEME); 86 return NULL; 87 } 88} 89 90/* 91 * Select the appropriate protocol for the URL scheme, and return a 92 * write-only stream connected to the document referenced by the URL. 93 */ 94FILE * 95fetchPut(struct url *URL, char *flags) 96{ 97 int direct; 98 99 direct = (flags && strchr(flags, 'd')); 100 if (strcasecmp(URL->scheme, "file") == 0) 101 return fetchPutFile(URL, flags); 102 else if (strcasecmp(URL->scheme, "http") == 0) 103 return fetchPutHTTP(URL, flags); 104 else if (strcasecmp(URL->scheme, "ftp") == 0) { 105 if (!direct && 106 getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 107 return fetchPutHTTP(URL, flags); 108 return fetchPutFTP(URL, flags); 109 } else { 110 _url_seterr(URL_BAD_SCHEME); 111 return NULL; 112 } 113} 114 115/* 116 * Select the appropriate protocol for the URL scheme, and return the 117 * size of the document referenced by the URL if it exists. 118 */ 119int 120fetchStat(struct url *URL, struct url_stat *us, char *flags) 121{ 122 int direct; 123 124 direct = (flags && strchr(flags, 'd')); 125 if (strcasecmp(URL->scheme, "file") == 0) 126 return fetchStatFile(URL, us, flags); 127 else if (strcasecmp(URL->scheme, "http") == 0) 128 return fetchStatHTTP(URL, us, flags); 129 else if (strcasecmp(URL->scheme, "ftp") == 0) { 130 if (!direct && 131 getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 132 return fetchStatHTTP(URL, us, flags); 133 return fetchStatFTP(URL, us, flags); 134 } else { 135 _url_seterr(URL_BAD_SCHEME); 136 return -1; 137 } 138} 139 140/* 141 * Select the appropriate protocol for the URL scheme, and return a 142 * list of files in the directory pointed to by the URL. 143 */ 144struct url_ent * 145fetchList(struct url *URL, char *flags) 146{ 147 int direct; 148 149 direct = (flags && strchr(flags, 'd')); 150 if (strcasecmp(URL->scheme, "file") == 0) 151 return fetchListFile(URL, flags); 152 else if (strcasecmp(URL->scheme, "http") == 0) 153 return fetchListHTTP(URL, flags); 154 else if (strcasecmp(URL->scheme, "ftp") == 0) { 155 if (!direct && 156 getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 157 return fetchListHTTP(URL, flags); 158 return fetchListFTP(URL, flags); 159 } else { 160 _url_seterr(URL_BAD_SCHEME); 161 return NULL; 162 } 163} 164 165/* 166 * Attempt to parse the given URL; if successful, call fetchGet(). 167 */ 168FILE * 169fetchGetURL(char *URL, char *flags) 170{ 171 struct url *u; 172 FILE *f; 173 174 if ((u = fetchParseURL(URL)) == NULL) 175 return NULL; 176 177 f = fetchGet(u, flags); 178 179 fetchFreeURL(u); 180 return f; 181} 182 183 184/* 185 * Attempt to parse the given URL; if successful, call fetchPut(). 186 */ 187FILE * 188fetchPutURL(char *URL, char *flags) 189{ 190 struct url *u; 191 FILE *f; 192 193 if ((u = fetchParseURL(URL)) == NULL) 194 return NULL; 195 196 f = fetchPut(u, flags); 197 198 fetchFreeURL(u); 199 return f; 200} 201 202/* 203 * Attempt to parse the given URL; if successful, call fetchStat(). 204 */ 205int 206fetchStatURL(char *URL, struct url_stat *us, char *flags) 207{ 208 struct url *u; 209 int s; 210 211 if ((u = fetchParseURL(URL)) == NULL) 212 return -1; 213 214 s = fetchStat(u, us, flags); 215 216 fetchFreeURL(u); 217 return s; 218} 219 220/* 221 * Attempt to parse the given URL; if successful, call fetchList(). 222 */ 223struct url_ent * 224fetchListURL(char *URL, char *flags) 225{ 226 struct url *u; 227 struct url_ent *ue; 228 229 if ((u = fetchParseURL(URL)) == NULL) 230 return NULL; 231 232 ue = fetchList(u, flags); 233 234 fetchFreeURL(u); 235 return ue; 236} 237 238/* 239 * Split an URL into components. URL syntax is: 240 * method:[//[user[:pwd]@]host[:port]]/[document] 241 * This almost, but not quite, RFC1738 URL syntax. 242 */ 243struct url * 244fetchParseURL(char *URL) 245{ 246 char *p, *q; 247 struct url *u; 248 int i; 249 250 /* allocate struct url */ 251 if ((u = calloc(1, sizeof *u)) == NULL) { 252 errno = ENOMEM; 253 _fetch_syserr(); 254 return NULL; 255 } 256 257 /* scheme name */ 258 for (i = 0; *URL && (*URL != ':'); URL++) 259 if (i < URL_SCHEMELEN) 260 u->scheme[i++] = *URL; 261 if (!URL[0] || (URL[1] != '/')) { 262 _url_seterr(URL_BAD_SCHEME); 263 goto ouch; 264 } 265 else URL++; 266 if (URL[1] != '/') { 267 p = URL; 268 goto nohost; 269 } 270 else URL += 2; 271 272 p = strpbrk(URL, "/@"); 273 if (p && *p == '@') { 274 /* username */ 275 for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++) 276 if (i < URL_USERLEN) 277 u->user[i++] = *q; 278 279 /* password */ 280 if (*q == ':') 281 for (q++, i = 0; (*q != ':') && (*q != '@'); q++) 282 if (i < URL_PWDLEN) 283 u->pwd[i++] = *q; 284 285 p++; 286 } else p = URL; 287 288 /* hostname */
| 29 */ 30 31#include <sys/param.h> 32#include <sys/errno.h> 33 34#include <ctype.h> 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38 39#include "fetch.h" 40#include "common.h" 41 42 43int fetchLastErrCode; 44int fetchTimeout; 45 46 47/*** Local data **************************************************************/ 48 49/* 50 * Error messages for parser errors 51 */ 52#define URL_MALFORMED 1 53#define URL_BAD_SCHEME 2 54#define URL_BAD_PORT 3 55static struct fetcherr _url_errlist[] = { 56 { URL_MALFORMED, FETCH_URL, "Malformed URL" }, 57 { URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" }, 58 { URL_BAD_PORT, FETCH_URL, "Invalid server port" }, 59 { -1, FETCH_UNKNOWN, "Unknown parser error" } 60}; 61 62 63/*** Public API **************************************************************/ 64 65/* 66 * Select the appropriate protocol for the URL scheme, and return a 67 * read-only stream connected to the document referenced by the URL. 68 */ 69FILE * 70fetchGet(struct url *URL, char *flags) 71{ 72 int direct; 73 74 direct = (flags && strchr(flags, 'd')); 75 if (strcasecmp(URL->scheme, "file") == 0) 76 return fetchGetFile(URL, flags); 77 else if (strcasecmp(URL->scheme, "http") == 0) 78 return fetchGetHTTP(URL, flags); 79 else if (strcasecmp(URL->scheme, "ftp") == 0) { 80 if (!direct && 81 getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 82 return fetchGetHTTP(URL, flags); 83 return fetchGetFTP(URL, flags); 84 } else { 85 _url_seterr(URL_BAD_SCHEME); 86 return NULL; 87 } 88} 89 90/* 91 * Select the appropriate protocol for the URL scheme, and return a 92 * write-only stream connected to the document referenced by the URL. 93 */ 94FILE * 95fetchPut(struct url *URL, char *flags) 96{ 97 int direct; 98 99 direct = (flags && strchr(flags, 'd')); 100 if (strcasecmp(URL->scheme, "file") == 0) 101 return fetchPutFile(URL, flags); 102 else if (strcasecmp(URL->scheme, "http") == 0) 103 return fetchPutHTTP(URL, flags); 104 else if (strcasecmp(URL->scheme, "ftp") == 0) { 105 if (!direct && 106 getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 107 return fetchPutHTTP(URL, flags); 108 return fetchPutFTP(URL, flags); 109 } else { 110 _url_seterr(URL_BAD_SCHEME); 111 return NULL; 112 } 113} 114 115/* 116 * Select the appropriate protocol for the URL scheme, and return the 117 * size of the document referenced by the URL if it exists. 118 */ 119int 120fetchStat(struct url *URL, struct url_stat *us, char *flags) 121{ 122 int direct; 123 124 direct = (flags && strchr(flags, 'd')); 125 if (strcasecmp(URL->scheme, "file") == 0) 126 return fetchStatFile(URL, us, flags); 127 else if (strcasecmp(URL->scheme, "http") == 0) 128 return fetchStatHTTP(URL, us, flags); 129 else if (strcasecmp(URL->scheme, "ftp") == 0) { 130 if (!direct && 131 getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 132 return fetchStatHTTP(URL, us, flags); 133 return fetchStatFTP(URL, us, flags); 134 } else { 135 _url_seterr(URL_BAD_SCHEME); 136 return -1; 137 } 138} 139 140/* 141 * Select the appropriate protocol for the URL scheme, and return a 142 * list of files in the directory pointed to by the URL. 143 */ 144struct url_ent * 145fetchList(struct url *URL, char *flags) 146{ 147 int direct; 148 149 direct = (flags && strchr(flags, 'd')); 150 if (strcasecmp(URL->scheme, "file") == 0) 151 return fetchListFile(URL, flags); 152 else if (strcasecmp(URL->scheme, "http") == 0) 153 return fetchListHTTP(URL, flags); 154 else if (strcasecmp(URL->scheme, "ftp") == 0) { 155 if (!direct && 156 getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 157 return fetchListHTTP(URL, flags); 158 return fetchListFTP(URL, flags); 159 } else { 160 _url_seterr(URL_BAD_SCHEME); 161 return NULL; 162 } 163} 164 165/* 166 * Attempt to parse the given URL; if successful, call fetchGet(). 167 */ 168FILE * 169fetchGetURL(char *URL, char *flags) 170{ 171 struct url *u; 172 FILE *f; 173 174 if ((u = fetchParseURL(URL)) == NULL) 175 return NULL; 176 177 f = fetchGet(u, flags); 178 179 fetchFreeURL(u); 180 return f; 181} 182 183 184/* 185 * Attempt to parse the given URL; if successful, call fetchPut(). 186 */ 187FILE * 188fetchPutURL(char *URL, char *flags) 189{ 190 struct url *u; 191 FILE *f; 192 193 if ((u = fetchParseURL(URL)) == NULL) 194 return NULL; 195 196 f = fetchPut(u, flags); 197 198 fetchFreeURL(u); 199 return f; 200} 201 202/* 203 * Attempt to parse the given URL; if successful, call fetchStat(). 204 */ 205int 206fetchStatURL(char *URL, struct url_stat *us, char *flags) 207{ 208 struct url *u; 209 int s; 210 211 if ((u = fetchParseURL(URL)) == NULL) 212 return -1; 213 214 s = fetchStat(u, us, flags); 215 216 fetchFreeURL(u); 217 return s; 218} 219 220/* 221 * Attempt to parse the given URL; if successful, call fetchList(). 222 */ 223struct url_ent * 224fetchListURL(char *URL, char *flags) 225{ 226 struct url *u; 227 struct url_ent *ue; 228 229 if ((u = fetchParseURL(URL)) == NULL) 230 return NULL; 231 232 ue = fetchList(u, flags); 233 234 fetchFreeURL(u); 235 return ue; 236} 237 238/* 239 * Split an URL into components. URL syntax is: 240 * method:[//[user[:pwd]@]host[:port]]/[document] 241 * This almost, but not quite, RFC1738 URL syntax. 242 */ 243struct url * 244fetchParseURL(char *URL) 245{ 246 char *p, *q; 247 struct url *u; 248 int i; 249 250 /* allocate struct url */ 251 if ((u = calloc(1, sizeof *u)) == NULL) { 252 errno = ENOMEM; 253 _fetch_syserr(); 254 return NULL; 255 } 256 257 /* scheme name */ 258 for (i = 0; *URL && (*URL != ':'); URL++) 259 if (i < URL_SCHEMELEN) 260 u->scheme[i++] = *URL; 261 if (!URL[0] || (URL[1] != '/')) { 262 _url_seterr(URL_BAD_SCHEME); 263 goto ouch; 264 } 265 else URL++; 266 if (URL[1] != '/') { 267 p = URL; 268 goto nohost; 269 } 270 else URL += 2; 271 272 p = strpbrk(URL, "/@"); 273 if (p && *p == '@') { 274 /* username */ 275 for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++) 276 if (i < URL_USERLEN) 277 u->user[i++] = *q; 278 279 /* password */ 280 if (*q == ':') 281 for (q++, i = 0; (*q != ':') && (*q != '@'); q++) 282 if (i < URL_PWDLEN) 283 u->pwd[i++] = *q; 284 285 p++; 286 } else p = URL; 287 288 /* hostname */
|