14ca1ab94SDag-Erling Smørgrav /*- 24ca1ab94SDag-Erling Smørgrav * Copyright (c) 1998 Dag-Erling Co�dan Sm�rgrav 34ca1ab94SDag-Erling Smørgrav * All rights reserved. 44ca1ab94SDag-Erling Smørgrav * 54ca1ab94SDag-Erling Smørgrav * Redistribution and use in source and binary forms, with or without 64ca1ab94SDag-Erling Smørgrav * modification, are permitted provided that the following conditions 74ca1ab94SDag-Erling Smørgrav * are met: 84ca1ab94SDag-Erling Smørgrav * 1. Redistributions of source code must retain the above copyright 94ca1ab94SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer 104ca1ab94SDag-Erling Smørgrav * in this position and unchanged. 114ca1ab94SDag-Erling Smørgrav * 2. Redistributions in binary form must reproduce the above copyright 124ca1ab94SDag-Erling Smørgrav * notice, this list of conditions and the following disclaimer in the 134ca1ab94SDag-Erling Smørgrav * documentation and/or other materials provided with the distribution. 144ca1ab94SDag-Erling Smørgrav * 3. The name of the author may not be used to endorse or promote products 154ca1ab94SDag-Erling Smørgrav * derived from this software without specific prior written permission 164ca1ab94SDag-Erling Smørgrav * 174ca1ab94SDag-Erling Smørgrav * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 184ca1ab94SDag-Erling Smørgrav * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 194ca1ab94SDag-Erling Smørgrav * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 204ca1ab94SDag-Erling Smørgrav * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 214ca1ab94SDag-Erling Smørgrav * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 224ca1ab94SDag-Erling Smørgrav * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 234ca1ab94SDag-Erling Smørgrav * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 244ca1ab94SDag-Erling Smørgrav * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 254ca1ab94SDag-Erling Smørgrav * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 264ca1ab94SDag-Erling Smørgrav * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 274ca1ab94SDag-Erling Smørgrav * 287f3dea24SPeter Wemm * $FreeBSD$ 294ca1ab94SDag-Erling Smørgrav */ 304ca1ab94SDag-Erling Smørgrav 314ca1ab94SDag-Erling Smørgrav #include <sys/param.h> 32d8acd8dcSDag-Erling Smørgrav #include <sys/errno.h> 334ca1ab94SDag-Erling Smørgrav 344ca1ab94SDag-Erling Smørgrav #include <ctype.h> 354ca1ab94SDag-Erling Smørgrav #include <stdio.h> 364ca1ab94SDag-Erling Smørgrav #include <stdlib.h> 374ca1ab94SDag-Erling Smørgrav #include <string.h> 384ca1ab94SDag-Erling Smørgrav 394ca1ab94SDag-Erling Smørgrav #include "fetch.h" 40d8acd8dcSDag-Erling Smørgrav #include "common.h" 414ca1ab94SDag-Erling Smørgrav 424ca1ab94SDag-Erling Smørgrav 430fba3a00SDag-Erling Smørgrav int fetchLastErrCode; 44ba101983SDag-Erling Smørgrav char fetchLastErrString[MAXERRSTRING]; 45fc6e9e65SDag-Erling Smørgrav int fetchTimeout; 46a1bb3f48SDag-Erling Smørgrav int fetchRestartCalls = 1; 470fba3a00SDag-Erling Smørgrav 480fba3a00SDag-Erling Smørgrav 49d8acd8dcSDag-Erling Smørgrav /*** Local data **************************************************************/ 50d8acd8dcSDag-Erling Smørgrav 51d8acd8dcSDag-Erling Smørgrav /* 52d8acd8dcSDag-Erling Smørgrav * Error messages for parser errors 53d8acd8dcSDag-Erling Smørgrav */ 54d8acd8dcSDag-Erling Smørgrav #define URL_MALFORMED 1 55d8acd8dcSDag-Erling Smørgrav #define URL_BAD_SCHEME 2 56d8acd8dcSDag-Erling Smørgrav #define URL_BAD_PORT 3 57d8acd8dcSDag-Erling Smørgrav static struct fetcherr _url_errlist[] = { 58d8acd8dcSDag-Erling Smørgrav { URL_MALFORMED, FETCH_URL, "Malformed URL" }, 59d8acd8dcSDag-Erling Smørgrav { URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" }, 60d8acd8dcSDag-Erling Smørgrav { URL_BAD_PORT, FETCH_URL, "Invalid server port" }, 61d8acd8dcSDag-Erling Smørgrav { -1, FETCH_UNKNOWN, "Unknown parser error" } 62d8acd8dcSDag-Erling Smørgrav }; 63d8acd8dcSDag-Erling Smørgrav 64d8acd8dcSDag-Erling Smørgrav 65d8acd8dcSDag-Erling Smørgrav /*** Public API **************************************************************/ 664ca1ab94SDag-Erling Smørgrav 67842a95ccSDag-Erling Smørgrav /* 68842a95ccSDag-Erling Smørgrav * Select the appropriate protocol for the URL scheme, and return a 69842a95ccSDag-Erling Smørgrav * read-only stream connected to the document referenced by the URL. 701a5faa10SDag-Erling Smørgrav * Also fill out the struct url_stat. 71842a95ccSDag-Erling Smørgrav */ 72ecc91352SDag-Erling Smørgrav FILE * 731a5faa10SDag-Erling Smørgrav fetchXGet(struct url *URL, struct url_stat *us, char *flags) 74ecc91352SDag-Erling Smørgrav { 75c97925adSHajimu UMEMOTO int direct; 76c97925adSHajimu UMEMOTO 77c97925adSHajimu UMEMOTO direct = (flags && strchr(flags, 'd')); 78ecc91352SDag-Erling Smørgrav if (strcasecmp(URL->scheme, "file") == 0) 791a5faa10SDag-Erling Smørgrav return fetchXGetFile(URL, us, flags); 80ecc91352SDag-Erling Smørgrav else if (strcasecmp(URL->scheme, "http") == 0) 811a5faa10SDag-Erling Smørgrav return fetchXGetHTTP(URL, us, flags); 82c97925adSHajimu UMEMOTO else if (strcasecmp(URL->scheme, "ftp") == 0) { 83c97925adSHajimu UMEMOTO if (!direct && 84c97925adSHajimu UMEMOTO getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 851a5faa10SDag-Erling Smørgrav return fetchXGetHTTP(URL, us, flags); 861a5faa10SDag-Erling Smørgrav return fetchXGetFTP(URL, us, flags); 87c97925adSHajimu UMEMOTO } else { 88d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 89d8acd8dcSDag-Erling Smørgrav return NULL; 90d8acd8dcSDag-Erling Smørgrav } 91ecc91352SDag-Erling Smørgrav } 92ecc91352SDag-Erling Smørgrav 93842a95ccSDag-Erling Smørgrav /* 94842a95ccSDag-Erling Smørgrav * Select the appropriate protocol for the URL scheme, and return a 951a5faa10SDag-Erling Smørgrav * read-only stream connected to the document referenced by the URL. 961a5faa10SDag-Erling Smørgrav */ 971a5faa10SDag-Erling Smørgrav FILE * 981a5faa10SDag-Erling Smørgrav fetchGet(struct url *URL, char *flags) 991a5faa10SDag-Erling Smørgrav { 1001a5faa10SDag-Erling Smørgrav return fetchXGet(URL, NULL, flags); 1011a5faa10SDag-Erling Smørgrav } 1021a5faa10SDag-Erling Smørgrav 1031a5faa10SDag-Erling Smørgrav /* 1041a5faa10SDag-Erling Smørgrav * Select the appropriate protocol for the URL scheme, and return a 105842a95ccSDag-Erling Smørgrav * write-only stream connected to the document referenced by the URL. 106842a95ccSDag-Erling Smørgrav */ 107ecc91352SDag-Erling Smørgrav FILE * 108d8acd8dcSDag-Erling Smørgrav fetchPut(struct url *URL, char *flags) 109ecc91352SDag-Erling Smørgrav { 110c97925adSHajimu UMEMOTO int direct; 111c97925adSHajimu UMEMOTO 112c97925adSHajimu UMEMOTO direct = (flags && strchr(flags, 'd')); 113ecc91352SDag-Erling Smørgrav if (strcasecmp(URL->scheme, "file") == 0) 114ecc91352SDag-Erling Smørgrav return fetchPutFile(URL, flags); 115ecc91352SDag-Erling Smørgrav else if (strcasecmp(URL->scheme, "http") == 0) 116ecc91352SDag-Erling Smørgrav return fetchPutHTTP(URL, flags); 117c97925adSHajimu UMEMOTO else if (strcasecmp(URL->scheme, "ftp") == 0) { 118c97925adSHajimu UMEMOTO if (!direct && 119c97925adSHajimu UMEMOTO getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 120c97925adSHajimu UMEMOTO return fetchPutHTTP(URL, flags); 121ecc91352SDag-Erling Smørgrav return fetchPutFTP(URL, flags); 122c97925adSHajimu UMEMOTO } else { 123d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 124d8acd8dcSDag-Erling Smørgrav return NULL; 125d8acd8dcSDag-Erling Smørgrav } 126d8acd8dcSDag-Erling Smørgrav } 127d8acd8dcSDag-Erling Smørgrav 128d8acd8dcSDag-Erling Smørgrav /* 129d8acd8dcSDag-Erling Smørgrav * Select the appropriate protocol for the URL scheme, and return the 130d8acd8dcSDag-Erling Smørgrav * size of the document referenced by the URL if it exists. 131d8acd8dcSDag-Erling Smørgrav */ 132d8acd8dcSDag-Erling Smørgrav int 133d8acd8dcSDag-Erling Smørgrav fetchStat(struct url *URL, struct url_stat *us, char *flags) 134d8acd8dcSDag-Erling Smørgrav { 135c97925adSHajimu UMEMOTO int direct; 136c97925adSHajimu UMEMOTO 137c97925adSHajimu UMEMOTO direct = (flags && strchr(flags, 'd')); 138d8acd8dcSDag-Erling Smørgrav if (strcasecmp(URL->scheme, "file") == 0) 139d8acd8dcSDag-Erling Smørgrav return fetchStatFile(URL, us, flags); 140d8acd8dcSDag-Erling Smørgrav else if (strcasecmp(URL->scheme, "http") == 0) 141d8acd8dcSDag-Erling Smørgrav return fetchStatHTTP(URL, us, flags); 142c97925adSHajimu UMEMOTO else if (strcasecmp(URL->scheme, "ftp") == 0) { 143c97925adSHajimu UMEMOTO if (!direct && 144c97925adSHajimu UMEMOTO getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 145c97925adSHajimu UMEMOTO return fetchStatHTTP(URL, us, flags); 146d8acd8dcSDag-Erling Smørgrav return fetchStatFTP(URL, us, flags); 147c97925adSHajimu UMEMOTO } else { 148d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 149d8acd8dcSDag-Erling Smørgrav return -1; 150d8acd8dcSDag-Erling Smørgrav } 151ecc91352SDag-Erling Smørgrav } 152ecc91352SDag-Erling Smørgrav 153842a95ccSDag-Erling Smørgrav /* 154ce71b736SDag-Erling Smørgrav * Select the appropriate protocol for the URL scheme, and return a 155ce71b736SDag-Erling Smørgrav * list of files in the directory pointed to by the URL. 156ce71b736SDag-Erling Smørgrav */ 157ce71b736SDag-Erling Smørgrav struct url_ent * 158ce71b736SDag-Erling Smørgrav fetchList(struct url *URL, char *flags) 159ce71b736SDag-Erling Smørgrav { 160c97925adSHajimu UMEMOTO int direct; 161c97925adSHajimu UMEMOTO 162c97925adSHajimu UMEMOTO direct = (flags && strchr(flags, 'd')); 163ce71b736SDag-Erling Smørgrav if (strcasecmp(URL->scheme, "file") == 0) 164ce71b736SDag-Erling Smørgrav return fetchListFile(URL, flags); 165ce71b736SDag-Erling Smørgrav else if (strcasecmp(URL->scheme, "http") == 0) 166ce71b736SDag-Erling Smørgrav return fetchListHTTP(URL, flags); 167c97925adSHajimu UMEMOTO else if (strcasecmp(URL->scheme, "ftp") == 0) { 168c97925adSHajimu UMEMOTO if (!direct && 169c97925adSHajimu UMEMOTO getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 170c97925adSHajimu UMEMOTO return fetchListHTTP(URL, flags); 171ce71b736SDag-Erling Smørgrav return fetchListFTP(URL, flags); 172c97925adSHajimu UMEMOTO } else { 173ce71b736SDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 174ce71b736SDag-Erling Smørgrav return NULL; 175ce71b736SDag-Erling Smørgrav } 176ce71b736SDag-Erling Smørgrav } 177ce71b736SDag-Erling Smørgrav 178ce71b736SDag-Erling Smørgrav /* 1791a5faa10SDag-Erling Smørgrav * Attempt to parse the given URL; if successful, call fetchXGet(). 180842a95ccSDag-Erling Smørgrav */ 1814ca1ab94SDag-Erling Smørgrav FILE * 1821a5faa10SDag-Erling Smørgrav fetchXGetURL(char *URL, struct url_stat *us, char *flags) 1834ca1ab94SDag-Erling Smørgrav { 184d8acd8dcSDag-Erling Smørgrav struct url *u; 1854ca1ab94SDag-Erling Smørgrav FILE *f; 1864ca1ab94SDag-Erling Smørgrav 1874ca1ab94SDag-Erling Smørgrav if ((u = fetchParseURL(URL)) == NULL) 1884ca1ab94SDag-Erling Smørgrav return NULL; 1894ca1ab94SDag-Erling Smørgrav 1901a5faa10SDag-Erling Smørgrav f = fetchXGet(u, us, flags); 1914ca1ab94SDag-Erling Smørgrav 19260245e42SDag-Erling Smørgrav fetchFreeURL(u); 1934ca1ab94SDag-Erling Smørgrav return f; 1944ca1ab94SDag-Erling Smørgrav } 1954ca1ab94SDag-Erling Smørgrav 1961a5faa10SDag-Erling Smørgrav /* 1971a5faa10SDag-Erling Smørgrav * Attempt to parse the given URL; if successful, call fetchGet(). 1981a5faa10SDag-Erling Smørgrav */ 1991a5faa10SDag-Erling Smørgrav FILE * 2001a5faa10SDag-Erling Smørgrav fetchGetURL(char *URL, char *flags) 2011a5faa10SDag-Erling Smørgrav { 2021a5faa10SDag-Erling Smørgrav return fetchXGetURL(URL, NULL, flags); 2031a5faa10SDag-Erling Smørgrav } 2044ca1ab94SDag-Erling Smørgrav 205842a95ccSDag-Erling Smørgrav /* 206842a95ccSDag-Erling Smørgrav * Attempt to parse the given URL; if successful, call fetchPut(). 207842a95ccSDag-Erling Smørgrav */ 2084ca1ab94SDag-Erling Smørgrav FILE * 2094ca1ab94SDag-Erling Smørgrav fetchPutURL(char *URL, char *flags) 2104ca1ab94SDag-Erling Smørgrav { 211d8acd8dcSDag-Erling Smørgrav struct url *u; 2124ca1ab94SDag-Erling Smørgrav FILE *f; 2134ca1ab94SDag-Erling Smørgrav 2144ca1ab94SDag-Erling Smørgrav if ((u = fetchParseURL(URL)) == NULL) 2154ca1ab94SDag-Erling Smørgrav return NULL; 2164ca1ab94SDag-Erling Smørgrav 217ecc91352SDag-Erling Smørgrav f = fetchPut(u, flags); 2184ca1ab94SDag-Erling Smørgrav 21960245e42SDag-Erling Smørgrav fetchFreeURL(u); 2204ca1ab94SDag-Erling Smørgrav return f; 2214ca1ab94SDag-Erling Smørgrav } 2224ca1ab94SDag-Erling Smørgrav 2234ca1ab94SDag-Erling Smørgrav /* 224d8acd8dcSDag-Erling Smørgrav * Attempt to parse the given URL; if successful, call fetchStat(). 225d8acd8dcSDag-Erling Smørgrav */ 226d8acd8dcSDag-Erling Smørgrav int 227d8acd8dcSDag-Erling Smørgrav fetchStatURL(char *URL, struct url_stat *us, char *flags) 228d8acd8dcSDag-Erling Smørgrav { 229d8acd8dcSDag-Erling Smørgrav struct url *u; 230d8acd8dcSDag-Erling Smørgrav int s; 231d8acd8dcSDag-Erling Smørgrav 232d8acd8dcSDag-Erling Smørgrav if ((u = fetchParseURL(URL)) == NULL) 233d8acd8dcSDag-Erling Smørgrav return -1; 234d8acd8dcSDag-Erling Smørgrav 235d8acd8dcSDag-Erling Smørgrav s = fetchStat(u, us, flags); 236d8acd8dcSDag-Erling Smørgrav 23760245e42SDag-Erling Smørgrav fetchFreeURL(u); 238d8acd8dcSDag-Erling Smørgrav return s; 239d8acd8dcSDag-Erling Smørgrav } 240d8acd8dcSDag-Erling Smørgrav 241d8acd8dcSDag-Erling Smørgrav /* 242ce71b736SDag-Erling Smørgrav * Attempt to parse the given URL; if successful, call fetchList(). 243ce71b736SDag-Erling Smørgrav */ 244ce71b736SDag-Erling Smørgrav struct url_ent * 245ce71b736SDag-Erling Smørgrav fetchListURL(char *URL, char *flags) 246ce71b736SDag-Erling Smørgrav { 247ce71b736SDag-Erling Smørgrav struct url *u; 248ce71b736SDag-Erling Smørgrav struct url_ent *ue; 249ce71b736SDag-Erling Smørgrav 250ce71b736SDag-Erling Smørgrav if ((u = fetchParseURL(URL)) == NULL) 251ce71b736SDag-Erling Smørgrav return NULL; 252ce71b736SDag-Erling Smørgrav 253ce71b736SDag-Erling Smørgrav ue = fetchList(u, flags); 254ce71b736SDag-Erling Smørgrav 25560245e42SDag-Erling Smørgrav fetchFreeURL(u); 256ce71b736SDag-Erling Smørgrav return ue; 257ce71b736SDag-Erling Smørgrav } 258ce71b736SDag-Erling Smørgrav 259ce71b736SDag-Erling Smørgrav /* 2609a964d6aSDag-Erling Smørgrav * Make a URL 2619a964d6aSDag-Erling Smørgrav */ 2629a964d6aSDag-Erling Smørgrav struct url * 2639a964d6aSDag-Erling Smørgrav fetchMakeURL(char *scheme, char *host, int port, char *doc, 2649a964d6aSDag-Erling Smørgrav char *user, char *pwd) 2659a964d6aSDag-Erling Smørgrav { 2669a964d6aSDag-Erling Smørgrav struct url *u; 2679a964d6aSDag-Erling Smørgrav 2689a964d6aSDag-Erling Smørgrav if (!scheme || (!host && !doc)) { 2699a964d6aSDag-Erling Smørgrav _url_seterr(URL_MALFORMED); 2709a964d6aSDag-Erling Smørgrav return NULL; 2719a964d6aSDag-Erling Smørgrav } 2729a964d6aSDag-Erling Smørgrav 2739a964d6aSDag-Erling Smørgrav if (port < 0 || port > 65535) { 2749a964d6aSDag-Erling Smørgrav _url_seterr(URL_BAD_PORT); 2759a964d6aSDag-Erling Smørgrav return NULL; 2769a964d6aSDag-Erling Smørgrav } 2779a964d6aSDag-Erling Smørgrav 2789a964d6aSDag-Erling Smørgrav /* allocate struct url */ 2799a964d6aSDag-Erling Smørgrav if ((u = calloc(1, sizeof *u)) == NULL) { 2809a964d6aSDag-Erling Smørgrav _fetch_syserr(); 2819a964d6aSDag-Erling Smørgrav return NULL; 2829a964d6aSDag-Erling Smørgrav } 2839a964d6aSDag-Erling Smørgrav 2849a964d6aSDag-Erling Smørgrav if ((u->doc = strdup(doc ? doc : "/")) == NULL) { 2859a964d6aSDag-Erling Smørgrav _fetch_syserr(); 2869a964d6aSDag-Erling Smørgrav free(u); 2879a964d6aSDag-Erling Smørgrav return NULL; 2889a964d6aSDag-Erling Smørgrav } 2899a964d6aSDag-Erling Smørgrav 2909a964d6aSDag-Erling Smørgrav #define seturl(x) snprintf(u->x, sizeof u->x, "%s", x) 2919a964d6aSDag-Erling Smørgrav seturl(scheme); 2929a964d6aSDag-Erling Smørgrav seturl(host); 2939a964d6aSDag-Erling Smørgrav seturl(user); 2949a964d6aSDag-Erling Smørgrav seturl(pwd); 2959a964d6aSDag-Erling Smørgrav #undef seturl 2969a964d6aSDag-Erling Smørgrav u->port = port; 2979a964d6aSDag-Erling Smørgrav 2989a964d6aSDag-Erling Smørgrav return u; 2999a964d6aSDag-Erling Smørgrav } 3009a964d6aSDag-Erling Smørgrav 3019a964d6aSDag-Erling Smørgrav /* 3024ca1ab94SDag-Erling Smørgrav * Split an URL into components. URL syntax is: 3034ca1ab94SDag-Erling Smørgrav * method:[//[user[:pwd]@]host[:port]]/[document] 3044ca1ab94SDag-Erling Smørgrav * This almost, but not quite, RFC1738 URL syntax. 3054ca1ab94SDag-Erling Smørgrav */ 306d8acd8dcSDag-Erling Smørgrav struct url * 3074ca1ab94SDag-Erling Smørgrav fetchParseURL(char *URL) 3084ca1ab94SDag-Erling Smørgrav { 3094ca1ab94SDag-Erling Smørgrav char *p, *q; 310d8acd8dcSDag-Erling Smørgrav struct url *u; 3114ca1ab94SDag-Erling Smørgrav int i; 3124ca1ab94SDag-Erling Smørgrav 313d8acd8dcSDag-Erling Smørgrav /* allocate struct url */ 314807c941cSDag-Erling Smørgrav if ((u = calloc(1, sizeof *u)) == NULL) { 315d8acd8dcSDag-Erling Smørgrav _fetch_syserr(); 3164ca1ab94SDag-Erling Smørgrav return NULL; 317d8acd8dcSDag-Erling Smørgrav } 3184ca1ab94SDag-Erling Smørgrav 3194ca1ab94SDag-Erling Smørgrav /* scheme name */ 3204ca1ab94SDag-Erling Smørgrav for (i = 0; *URL && (*URL != ':'); URL++) 3214ca1ab94SDag-Erling Smørgrav if (i < URL_SCHEMELEN) 3224ca1ab94SDag-Erling Smørgrav u->scheme[i++] = *URL; 323d8acd8dcSDag-Erling Smørgrav if (!URL[0] || (URL[1] != '/')) { 324d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 3254ca1ab94SDag-Erling Smørgrav goto ouch; 326d8acd8dcSDag-Erling Smørgrav } 3274ca1ab94SDag-Erling Smørgrav else URL++; 3284ca1ab94SDag-Erling Smørgrav if (URL[1] != '/') { 3294ca1ab94SDag-Erling Smørgrav p = URL; 3304ca1ab94SDag-Erling Smørgrav goto nohost; 3314ca1ab94SDag-Erling Smørgrav } 3324ca1ab94SDag-Erling Smørgrav else URL += 2; 3334ca1ab94SDag-Erling Smørgrav 3344ca1ab94SDag-Erling Smørgrav p = strpbrk(URL, "/@"); 3350fba3a00SDag-Erling Smørgrav if (p && *p == '@') { 3364ca1ab94SDag-Erling Smørgrav /* username */ 3374ca1ab94SDag-Erling Smørgrav for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++) 3384ca1ab94SDag-Erling Smørgrav if (i < URL_USERLEN) 3394ca1ab94SDag-Erling Smørgrav u->user[i++] = *q; 3404ca1ab94SDag-Erling Smørgrav 3414ca1ab94SDag-Erling Smørgrav /* password */ 3424ca1ab94SDag-Erling Smørgrav if (*q == ':') 3434ca1ab94SDag-Erling Smørgrav for (q++, i = 0; (*q != ':') && (*q != '@'); q++) 3444ca1ab94SDag-Erling Smørgrav if (i < URL_PWDLEN) 3454ca1ab94SDag-Erling Smørgrav u->pwd[i++] = *q; 3464ca1ab94SDag-Erling Smørgrav 3474ca1ab94SDag-Erling Smørgrav p++; 3484ca1ab94SDag-Erling Smørgrav } else p = URL; 3494ca1ab94SDag-Erling Smørgrav 3504ca1ab94SDag-Erling Smørgrav /* hostname */ 35128c645cfSHajimu UMEMOTO #ifdef INET6 35228c645cfSHajimu UMEMOTO if (*p == '[' && (q = strchr(p + 1, ']')) != NULL && 35328c645cfSHajimu UMEMOTO (*++q == '\0' || *q == '/' || *q == ':')) { 35428c645cfSHajimu UMEMOTO if ((i = q - p - 2) > MAXHOSTNAMELEN) 35528c645cfSHajimu UMEMOTO i = MAXHOSTNAMELEN; 35628c645cfSHajimu UMEMOTO strncpy(u->host, ++p, i); 35728c645cfSHajimu UMEMOTO p = q; 35828c645cfSHajimu UMEMOTO } else 35928c645cfSHajimu UMEMOTO #endif 3604ca1ab94SDag-Erling Smørgrav for (i = 0; *p && (*p != '/') && (*p != ':'); p++) 3614ca1ab94SDag-Erling Smørgrav if (i < MAXHOSTNAMELEN) 3624ca1ab94SDag-Erling Smørgrav u->host[i++] = *p; 3634ca1ab94SDag-Erling Smørgrav 3644ca1ab94SDag-Erling Smørgrav /* port */ 3654ca1ab94SDag-Erling Smørgrav if (*p == ':') { 3664ca1ab94SDag-Erling Smørgrav for (q = ++p; *q && (*q != '/'); q++) 3674ca1ab94SDag-Erling Smørgrav if (isdigit(*q)) 3684ca1ab94SDag-Erling Smørgrav u->port = u->port * 10 + (*q - '0'); 369d8acd8dcSDag-Erling Smørgrav else { 370d8acd8dcSDag-Erling Smørgrav /* invalid port */ 371d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_PORT); 372d8acd8dcSDag-Erling Smørgrav goto ouch; 373d8acd8dcSDag-Erling Smørgrav } 3744ca1ab94SDag-Erling Smørgrav while (*p && (*p != '/')) 3754ca1ab94SDag-Erling Smørgrav p++; 3764ca1ab94SDag-Erling Smørgrav } 3774ca1ab94SDag-Erling Smørgrav 3784ca1ab94SDag-Erling Smørgrav nohost: 3794ca1ab94SDag-Erling Smørgrav /* document */ 38060245e42SDag-Erling Smørgrav if (!*p) 38160245e42SDag-Erling Smørgrav p = "/"; 38260245e42SDag-Erling Smørgrav 38360245e42SDag-Erling Smørgrav if ((u->doc = strdup(p)) == NULL) { 384d8acd8dcSDag-Erling Smørgrav _fetch_syserr(); 3854ca1ab94SDag-Erling Smørgrav goto ouch; 386d8acd8dcSDag-Erling Smørgrav } 3874ca1ab94SDag-Erling Smørgrav 3884ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, 3894ca1ab94SDag-Erling Smørgrav "scheme: [\033[1m%s\033[m]\n" 3904ca1ab94SDag-Erling Smørgrav "user: [\033[1m%s\033[m]\n" 3914ca1ab94SDag-Erling Smørgrav "password: [\033[1m%s\033[m]\n" 3924ca1ab94SDag-Erling Smørgrav "host: [\033[1m%s\033[m]\n" 3934ca1ab94SDag-Erling Smørgrav "port: [\033[1m%d\033[m]\n" 3944ca1ab94SDag-Erling Smørgrav "document: [\033[1m%s\033[m]\n", 3954ca1ab94SDag-Erling Smørgrav u->scheme, u->user, u->pwd, 3964ca1ab94SDag-Erling Smørgrav u->host, u->port, u->doc)); 3974ca1ab94SDag-Erling Smørgrav 3984ca1ab94SDag-Erling Smørgrav return u; 3994ca1ab94SDag-Erling Smørgrav 4004ca1ab94SDag-Erling Smørgrav ouch: 4014ca1ab94SDag-Erling Smørgrav free(u); 4024ca1ab94SDag-Erling Smørgrav return NULL; 4034ca1ab94SDag-Erling Smørgrav } 40460245e42SDag-Erling Smørgrav 40560245e42SDag-Erling Smørgrav /* 40660245e42SDag-Erling Smørgrav * Free a URL 40760245e42SDag-Erling Smørgrav */ 40860245e42SDag-Erling Smørgrav void 40960245e42SDag-Erling Smørgrav fetchFreeURL(struct url *u) 41060245e42SDag-Erling Smørgrav { 41160245e42SDag-Erling Smørgrav free(u->doc); 41260245e42SDag-Erling Smørgrav free(u); 41360245e42SDag-Erling Smørgrav } 414