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; 460fba3a00SDag-Erling Smørgrav 470fba3a00SDag-Erling Smørgrav 48d8acd8dcSDag-Erling Smørgrav /*** Local data **************************************************************/ 49d8acd8dcSDag-Erling Smørgrav 50d8acd8dcSDag-Erling Smørgrav /* 51d8acd8dcSDag-Erling Smørgrav * Error messages for parser errors 52d8acd8dcSDag-Erling Smørgrav */ 53d8acd8dcSDag-Erling Smørgrav #define URL_MALFORMED 1 54d8acd8dcSDag-Erling Smørgrav #define URL_BAD_SCHEME 2 55d8acd8dcSDag-Erling Smørgrav #define URL_BAD_PORT 3 56d8acd8dcSDag-Erling Smørgrav static struct fetcherr _url_errlist[] = { 57d8acd8dcSDag-Erling Smørgrav { URL_MALFORMED, FETCH_URL, "Malformed URL" }, 58d8acd8dcSDag-Erling Smørgrav { URL_BAD_SCHEME, FETCH_URL, "Invalid URL scheme" }, 59d8acd8dcSDag-Erling Smørgrav { URL_BAD_PORT, FETCH_URL, "Invalid server port" }, 60d8acd8dcSDag-Erling Smørgrav { -1, FETCH_UNKNOWN, "Unknown parser error" } 61d8acd8dcSDag-Erling Smørgrav }; 62d8acd8dcSDag-Erling Smørgrav 63d8acd8dcSDag-Erling Smørgrav 64d8acd8dcSDag-Erling Smørgrav /*** Public API **************************************************************/ 654ca1ab94SDag-Erling Smørgrav 66842a95ccSDag-Erling Smørgrav /* 67842a95ccSDag-Erling Smørgrav * Select the appropriate protocol for the URL scheme, and return a 68842a95ccSDag-Erling Smørgrav * read-only stream connected to the document referenced by the URL. 69842a95ccSDag-Erling Smørgrav */ 70ecc91352SDag-Erling Smørgrav FILE * 71d8acd8dcSDag-Erling Smørgrav fetchGet(struct url *URL, char *flags) 72ecc91352SDag-Erling Smørgrav { 73c97925adSHajimu UMEMOTO int direct; 74c97925adSHajimu UMEMOTO 75c97925adSHajimu UMEMOTO direct = (flags && strchr(flags, 'd')); 76ecc91352SDag-Erling Smørgrav if (strcasecmp(URL->scheme, "file") == 0) 77ecc91352SDag-Erling Smørgrav return fetchGetFile(URL, flags); 78ecc91352SDag-Erling Smørgrav else if (strcasecmp(URL->scheme, "http") == 0) 79ecc91352SDag-Erling Smørgrav return fetchGetHTTP(URL, flags); 80c97925adSHajimu UMEMOTO else if (strcasecmp(URL->scheme, "ftp") == 0) { 81c97925adSHajimu UMEMOTO if (!direct && 82c97925adSHajimu UMEMOTO getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 83c97925adSHajimu UMEMOTO return fetchGetHTTP(URL, flags); 84ecc91352SDag-Erling Smørgrav return fetchGetFTP(URL, flags); 85c97925adSHajimu UMEMOTO } else { 86d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 87d8acd8dcSDag-Erling Smørgrav return NULL; 88d8acd8dcSDag-Erling Smørgrav } 89ecc91352SDag-Erling Smørgrav } 90ecc91352SDag-Erling Smørgrav 91842a95ccSDag-Erling Smørgrav /* 92842a95ccSDag-Erling Smørgrav * Select the appropriate protocol for the URL scheme, and return a 93842a95ccSDag-Erling Smørgrav * write-only stream connected to the document referenced by the URL. 94842a95ccSDag-Erling Smørgrav */ 95ecc91352SDag-Erling Smørgrav FILE * 96d8acd8dcSDag-Erling Smørgrav fetchPut(struct url *URL, char *flags) 97ecc91352SDag-Erling Smørgrav { 98c97925adSHajimu UMEMOTO int direct; 99c97925adSHajimu UMEMOTO 100c97925adSHajimu UMEMOTO direct = (flags && strchr(flags, 'd')); 101ecc91352SDag-Erling Smørgrav if (strcasecmp(URL->scheme, "file") == 0) 102ecc91352SDag-Erling Smørgrav return fetchPutFile(URL, flags); 103ecc91352SDag-Erling Smørgrav else if (strcasecmp(URL->scheme, "http") == 0) 104ecc91352SDag-Erling Smørgrav return fetchPutHTTP(URL, flags); 105c97925adSHajimu UMEMOTO else if (strcasecmp(URL->scheme, "ftp") == 0) { 106c97925adSHajimu UMEMOTO if (!direct && 107c97925adSHajimu UMEMOTO getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 108c97925adSHajimu UMEMOTO return fetchPutHTTP(URL, flags); 109ecc91352SDag-Erling Smørgrav return fetchPutFTP(URL, flags); 110c97925adSHajimu UMEMOTO } else { 111d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 112d8acd8dcSDag-Erling Smørgrav return NULL; 113d8acd8dcSDag-Erling Smørgrav } 114d8acd8dcSDag-Erling Smørgrav } 115d8acd8dcSDag-Erling Smørgrav 116d8acd8dcSDag-Erling Smørgrav /* 117d8acd8dcSDag-Erling Smørgrav * Select the appropriate protocol for the URL scheme, and return the 118d8acd8dcSDag-Erling Smørgrav * size of the document referenced by the URL if it exists. 119d8acd8dcSDag-Erling Smørgrav */ 120d8acd8dcSDag-Erling Smørgrav int 121d8acd8dcSDag-Erling Smørgrav fetchStat(struct url *URL, struct url_stat *us, char *flags) 122d8acd8dcSDag-Erling Smørgrav { 123c97925adSHajimu UMEMOTO int direct; 124c97925adSHajimu UMEMOTO 125c97925adSHajimu UMEMOTO direct = (flags && strchr(flags, 'd')); 126d8acd8dcSDag-Erling Smørgrav if (strcasecmp(URL->scheme, "file") == 0) 127d8acd8dcSDag-Erling Smørgrav return fetchStatFile(URL, us, flags); 128d8acd8dcSDag-Erling Smørgrav else if (strcasecmp(URL->scheme, "http") == 0) 129d8acd8dcSDag-Erling Smørgrav return fetchStatHTTP(URL, us, flags); 130c97925adSHajimu UMEMOTO else if (strcasecmp(URL->scheme, "ftp") == 0) { 131c97925adSHajimu UMEMOTO if (!direct && 132c97925adSHajimu UMEMOTO getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 133c97925adSHajimu UMEMOTO return fetchStatHTTP(URL, us, flags); 134d8acd8dcSDag-Erling Smørgrav return fetchStatFTP(URL, us, flags); 135c97925adSHajimu UMEMOTO } else { 136d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 137d8acd8dcSDag-Erling Smørgrav return -1; 138d8acd8dcSDag-Erling Smørgrav } 139ecc91352SDag-Erling Smørgrav } 140ecc91352SDag-Erling Smørgrav 141842a95ccSDag-Erling Smørgrav /* 142ce71b736SDag-Erling Smørgrav * Select the appropriate protocol for the URL scheme, and return a 143ce71b736SDag-Erling Smørgrav * list of files in the directory pointed to by the URL. 144ce71b736SDag-Erling Smørgrav */ 145ce71b736SDag-Erling Smørgrav struct url_ent * 146ce71b736SDag-Erling Smørgrav fetchList(struct url *URL, char *flags) 147ce71b736SDag-Erling Smørgrav { 148c97925adSHajimu UMEMOTO int direct; 149c97925adSHajimu UMEMOTO 150c97925adSHajimu UMEMOTO direct = (flags && strchr(flags, 'd')); 151ce71b736SDag-Erling Smørgrav if (strcasecmp(URL->scheme, "file") == 0) 152ce71b736SDag-Erling Smørgrav return fetchListFile(URL, flags); 153ce71b736SDag-Erling Smørgrav else if (strcasecmp(URL->scheme, "http") == 0) 154ce71b736SDag-Erling Smørgrav return fetchListHTTP(URL, flags); 155c97925adSHajimu UMEMOTO else if (strcasecmp(URL->scheme, "ftp") == 0) { 156c97925adSHajimu UMEMOTO if (!direct && 157c97925adSHajimu UMEMOTO getenv("FTP_PROXY") == NULL && getenv("HTTP_PROXY") != NULL) 158c97925adSHajimu UMEMOTO return fetchListHTTP(URL, flags); 159ce71b736SDag-Erling Smørgrav return fetchListFTP(URL, flags); 160c97925adSHajimu UMEMOTO } else { 161ce71b736SDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 162ce71b736SDag-Erling Smørgrav return NULL; 163ce71b736SDag-Erling Smørgrav } 164ce71b736SDag-Erling Smørgrav } 165ce71b736SDag-Erling Smørgrav 166ce71b736SDag-Erling Smørgrav /* 167842a95ccSDag-Erling Smørgrav * Attempt to parse the given URL; if successful, call fetchGet(). 168842a95ccSDag-Erling Smørgrav */ 1694ca1ab94SDag-Erling Smørgrav FILE * 1704ca1ab94SDag-Erling Smørgrav fetchGetURL(char *URL, char *flags) 1714ca1ab94SDag-Erling Smørgrav { 172d8acd8dcSDag-Erling Smørgrav struct url *u; 1734ca1ab94SDag-Erling Smørgrav FILE *f; 1744ca1ab94SDag-Erling Smørgrav 1754ca1ab94SDag-Erling Smørgrav if ((u = fetchParseURL(URL)) == NULL) 1764ca1ab94SDag-Erling Smørgrav return NULL; 1774ca1ab94SDag-Erling Smørgrav 178ecc91352SDag-Erling Smørgrav f = fetchGet(u, flags); 1794ca1ab94SDag-Erling Smørgrav 18060245e42SDag-Erling Smørgrav fetchFreeURL(u); 1814ca1ab94SDag-Erling Smørgrav return f; 1824ca1ab94SDag-Erling Smørgrav } 1834ca1ab94SDag-Erling Smørgrav 1844ca1ab94SDag-Erling Smørgrav 185842a95ccSDag-Erling Smørgrav /* 186842a95ccSDag-Erling Smørgrav * Attempt to parse the given URL; if successful, call fetchPut(). 187842a95ccSDag-Erling Smørgrav */ 1884ca1ab94SDag-Erling Smørgrav FILE * 1894ca1ab94SDag-Erling Smørgrav fetchPutURL(char *URL, char *flags) 1904ca1ab94SDag-Erling Smørgrav { 191d8acd8dcSDag-Erling Smørgrav struct url *u; 1924ca1ab94SDag-Erling Smørgrav FILE *f; 1934ca1ab94SDag-Erling Smørgrav 1944ca1ab94SDag-Erling Smørgrav if ((u = fetchParseURL(URL)) == NULL) 1954ca1ab94SDag-Erling Smørgrav return NULL; 1964ca1ab94SDag-Erling Smørgrav 197ecc91352SDag-Erling Smørgrav f = fetchPut(u, flags); 1984ca1ab94SDag-Erling Smørgrav 19960245e42SDag-Erling Smørgrav fetchFreeURL(u); 2004ca1ab94SDag-Erling Smørgrav return f; 2014ca1ab94SDag-Erling Smørgrav } 2024ca1ab94SDag-Erling Smørgrav 2034ca1ab94SDag-Erling Smørgrav /* 204d8acd8dcSDag-Erling Smørgrav * Attempt to parse the given URL; if successful, call fetchStat(). 205d8acd8dcSDag-Erling Smørgrav */ 206d8acd8dcSDag-Erling Smørgrav int 207d8acd8dcSDag-Erling Smørgrav fetchStatURL(char *URL, struct url_stat *us, char *flags) 208d8acd8dcSDag-Erling Smørgrav { 209d8acd8dcSDag-Erling Smørgrav struct url *u; 210d8acd8dcSDag-Erling Smørgrav int s; 211d8acd8dcSDag-Erling Smørgrav 212d8acd8dcSDag-Erling Smørgrav if ((u = fetchParseURL(URL)) == NULL) 213d8acd8dcSDag-Erling Smørgrav return -1; 214d8acd8dcSDag-Erling Smørgrav 215d8acd8dcSDag-Erling Smørgrav s = fetchStat(u, us, flags); 216d8acd8dcSDag-Erling Smørgrav 21760245e42SDag-Erling Smørgrav fetchFreeURL(u); 218d8acd8dcSDag-Erling Smørgrav return s; 219d8acd8dcSDag-Erling Smørgrav } 220d8acd8dcSDag-Erling Smørgrav 221d8acd8dcSDag-Erling Smørgrav /* 222ce71b736SDag-Erling Smørgrav * Attempt to parse the given URL; if successful, call fetchList(). 223ce71b736SDag-Erling Smørgrav */ 224ce71b736SDag-Erling Smørgrav struct url_ent * 225ce71b736SDag-Erling Smørgrav fetchListURL(char *URL, char *flags) 226ce71b736SDag-Erling Smørgrav { 227ce71b736SDag-Erling Smørgrav struct url *u; 228ce71b736SDag-Erling Smørgrav struct url_ent *ue; 229ce71b736SDag-Erling Smørgrav 230ce71b736SDag-Erling Smørgrav if ((u = fetchParseURL(URL)) == NULL) 231ce71b736SDag-Erling Smørgrav return NULL; 232ce71b736SDag-Erling Smørgrav 233ce71b736SDag-Erling Smørgrav ue = fetchList(u, flags); 234ce71b736SDag-Erling Smørgrav 23560245e42SDag-Erling Smørgrav fetchFreeURL(u); 236ce71b736SDag-Erling Smørgrav return ue; 237ce71b736SDag-Erling Smørgrav } 238ce71b736SDag-Erling Smørgrav 239ce71b736SDag-Erling Smørgrav /* 2409a964d6aSDag-Erling Smørgrav * Make a URL 2419a964d6aSDag-Erling Smørgrav */ 2429a964d6aSDag-Erling Smørgrav struct url * 2439a964d6aSDag-Erling Smørgrav fetchMakeURL(char *scheme, char *host, int port, char *doc, 2449a964d6aSDag-Erling Smørgrav char *user, char *pwd) 2459a964d6aSDag-Erling Smørgrav { 2469a964d6aSDag-Erling Smørgrav struct url *u; 2479a964d6aSDag-Erling Smørgrav 2489a964d6aSDag-Erling Smørgrav if (!scheme || (!host && !doc)) { 2499a964d6aSDag-Erling Smørgrav _url_seterr(URL_MALFORMED); 2509a964d6aSDag-Erling Smørgrav return NULL; 2519a964d6aSDag-Erling Smørgrav } 2529a964d6aSDag-Erling Smørgrav 2539a964d6aSDag-Erling Smørgrav if (port < 0 || port > 65535) { 2549a964d6aSDag-Erling Smørgrav _url_seterr(URL_BAD_PORT); 2559a964d6aSDag-Erling Smørgrav return NULL; 2569a964d6aSDag-Erling Smørgrav } 2579a964d6aSDag-Erling Smørgrav 2589a964d6aSDag-Erling Smørgrav /* allocate struct url */ 2599a964d6aSDag-Erling Smørgrav if ((u = calloc(1, sizeof *u)) == NULL) { 2609a964d6aSDag-Erling Smørgrav _fetch_syserr(); 2619a964d6aSDag-Erling Smørgrav return NULL; 2629a964d6aSDag-Erling Smørgrav } 2639a964d6aSDag-Erling Smørgrav 2649a964d6aSDag-Erling Smørgrav if ((u->doc = strdup(doc ? doc : "/")) == NULL) { 2659a964d6aSDag-Erling Smørgrav _fetch_syserr(); 2669a964d6aSDag-Erling Smørgrav free(u); 2679a964d6aSDag-Erling Smørgrav return NULL; 2689a964d6aSDag-Erling Smørgrav } 2699a964d6aSDag-Erling Smørgrav 2709a964d6aSDag-Erling Smørgrav #define seturl(x) snprintf(u->x, sizeof u->x, "%s", x) 2719a964d6aSDag-Erling Smørgrav seturl(scheme); 2729a964d6aSDag-Erling Smørgrav seturl(host); 2739a964d6aSDag-Erling Smørgrav seturl(user); 2749a964d6aSDag-Erling Smørgrav seturl(pwd); 2759a964d6aSDag-Erling Smørgrav #undef seturl 2769a964d6aSDag-Erling Smørgrav u->port = port; 2779a964d6aSDag-Erling Smørgrav 2789a964d6aSDag-Erling Smørgrav return u; 2799a964d6aSDag-Erling Smørgrav } 2809a964d6aSDag-Erling Smørgrav 2819a964d6aSDag-Erling Smørgrav /* 2824ca1ab94SDag-Erling Smørgrav * Split an URL into components. URL syntax is: 2834ca1ab94SDag-Erling Smørgrav * method:[//[user[:pwd]@]host[:port]]/[document] 2844ca1ab94SDag-Erling Smørgrav * This almost, but not quite, RFC1738 URL syntax. 2854ca1ab94SDag-Erling Smørgrav */ 286d8acd8dcSDag-Erling Smørgrav struct url * 2874ca1ab94SDag-Erling Smørgrav fetchParseURL(char *URL) 2884ca1ab94SDag-Erling Smørgrav { 2894ca1ab94SDag-Erling Smørgrav char *p, *q; 290d8acd8dcSDag-Erling Smørgrav struct url *u; 2914ca1ab94SDag-Erling Smørgrav int i; 2924ca1ab94SDag-Erling Smørgrav 293d8acd8dcSDag-Erling Smørgrav /* allocate struct url */ 294807c941cSDag-Erling Smørgrav if ((u = calloc(1, sizeof *u)) == NULL) { 295d8acd8dcSDag-Erling Smørgrav _fetch_syserr(); 2964ca1ab94SDag-Erling Smørgrav return NULL; 297d8acd8dcSDag-Erling Smørgrav } 2984ca1ab94SDag-Erling Smørgrav 2994ca1ab94SDag-Erling Smørgrav /* scheme name */ 3004ca1ab94SDag-Erling Smørgrav for (i = 0; *URL && (*URL != ':'); URL++) 3014ca1ab94SDag-Erling Smørgrav if (i < URL_SCHEMELEN) 3024ca1ab94SDag-Erling Smørgrav u->scheme[i++] = *URL; 303d8acd8dcSDag-Erling Smørgrav if (!URL[0] || (URL[1] != '/')) { 304d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_SCHEME); 3054ca1ab94SDag-Erling Smørgrav goto ouch; 306d8acd8dcSDag-Erling Smørgrav } 3074ca1ab94SDag-Erling Smørgrav else URL++; 3084ca1ab94SDag-Erling Smørgrav if (URL[1] != '/') { 3094ca1ab94SDag-Erling Smørgrav p = URL; 3104ca1ab94SDag-Erling Smørgrav goto nohost; 3114ca1ab94SDag-Erling Smørgrav } 3124ca1ab94SDag-Erling Smørgrav else URL += 2; 3134ca1ab94SDag-Erling Smørgrav 3144ca1ab94SDag-Erling Smørgrav p = strpbrk(URL, "/@"); 3150fba3a00SDag-Erling Smørgrav if (p && *p == '@') { 3164ca1ab94SDag-Erling Smørgrav /* username */ 3174ca1ab94SDag-Erling Smørgrav for (q = URL, i = 0; (*q != ':') && (*q != '@'); q++) 3184ca1ab94SDag-Erling Smørgrav if (i < URL_USERLEN) 3194ca1ab94SDag-Erling Smørgrav u->user[i++] = *q; 3204ca1ab94SDag-Erling Smørgrav 3214ca1ab94SDag-Erling Smørgrav /* password */ 3224ca1ab94SDag-Erling Smørgrav if (*q == ':') 3234ca1ab94SDag-Erling Smørgrav for (q++, i = 0; (*q != ':') && (*q != '@'); q++) 3244ca1ab94SDag-Erling Smørgrav if (i < URL_PWDLEN) 3254ca1ab94SDag-Erling Smørgrav u->pwd[i++] = *q; 3264ca1ab94SDag-Erling Smørgrav 3274ca1ab94SDag-Erling Smørgrav p++; 3284ca1ab94SDag-Erling Smørgrav } else p = URL; 3294ca1ab94SDag-Erling Smørgrav 3304ca1ab94SDag-Erling Smørgrav /* hostname */ 33128c645cfSHajimu UMEMOTO #ifdef INET6 33228c645cfSHajimu UMEMOTO if (*p == '[' && (q = strchr(p + 1, ']')) != NULL && 33328c645cfSHajimu UMEMOTO (*++q == '\0' || *q == '/' || *q == ':')) { 33428c645cfSHajimu UMEMOTO if ((i = q - p - 2) > MAXHOSTNAMELEN) 33528c645cfSHajimu UMEMOTO i = MAXHOSTNAMELEN; 33628c645cfSHajimu UMEMOTO strncpy(u->host, ++p, i); 33728c645cfSHajimu UMEMOTO p = q; 33828c645cfSHajimu UMEMOTO } else 33928c645cfSHajimu UMEMOTO #endif 3404ca1ab94SDag-Erling Smørgrav for (i = 0; *p && (*p != '/') && (*p != ':'); p++) 3414ca1ab94SDag-Erling Smørgrav if (i < MAXHOSTNAMELEN) 3424ca1ab94SDag-Erling Smørgrav u->host[i++] = *p; 3434ca1ab94SDag-Erling Smørgrav 3444ca1ab94SDag-Erling Smørgrav /* port */ 3454ca1ab94SDag-Erling Smørgrav if (*p == ':') { 3464ca1ab94SDag-Erling Smørgrav for (q = ++p; *q && (*q != '/'); q++) 3474ca1ab94SDag-Erling Smørgrav if (isdigit(*q)) 3484ca1ab94SDag-Erling Smørgrav u->port = u->port * 10 + (*q - '0'); 349d8acd8dcSDag-Erling Smørgrav else { 350d8acd8dcSDag-Erling Smørgrav /* invalid port */ 351d8acd8dcSDag-Erling Smørgrav _url_seterr(URL_BAD_PORT); 352d8acd8dcSDag-Erling Smørgrav goto ouch; 353d8acd8dcSDag-Erling Smørgrav } 3544ca1ab94SDag-Erling Smørgrav while (*p && (*p != '/')) 3554ca1ab94SDag-Erling Smørgrav p++; 3564ca1ab94SDag-Erling Smørgrav } 3574ca1ab94SDag-Erling Smørgrav 3584ca1ab94SDag-Erling Smørgrav nohost: 3594ca1ab94SDag-Erling Smørgrav /* document */ 36060245e42SDag-Erling Smørgrav if (!*p) 36160245e42SDag-Erling Smørgrav p = "/"; 36260245e42SDag-Erling Smørgrav 36360245e42SDag-Erling Smørgrav if ((u->doc = strdup(p)) == NULL) { 364d8acd8dcSDag-Erling Smørgrav _fetch_syserr(); 3654ca1ab94SDag-Erling Smørgrav goto ouch; 366d8acd8dcSDag-Erling Smørgrav } 3674ca1ab94SDag-Erling Smørgrav 3684ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, 3694ca1ab94SDag-Erling Smørgrav "scheme: [\033[1m%s\033[m]\n" 3704ca1ab94SDag-Erling Smørgrav "user: [\033[1m%s\033[m]\n" 3714ca1ab94SDag-Erling Smørgrav "password: [\033[1m%s\033[m]\n" 3724ca1ab94SDag-Erling Smørgrav "host: [\033[1m%s\033[m]\n" 3734ca1ab94SDag-Erling Smørgrav "port: [\033[1m%d\033[m]\n" 3744ca1ab94SDag-Erling Smørgrav "document: [\033[1m%s\033[m]\n", 3754ca1ab94SDag-Erling Smørgrav u->scheme, u->user, u->pwd, 3764ca1ab94SDag-Erling Smørgrav u->host, u->port, u->doc)); 3774ca1ab94SDag-Erling Smørgrav 3784ca1ab94SDag-Erling Smørgrav return u; 3794ca1ab94SDag-Erling Smørgrav 3804ca1ab94SDag-Erling Smørgrav ouch: 3814ca1ab94SDag-Erling Smørgrav free(u); 3824ca1ab94SDag-Erling Smørgrav return NULL; 3834ca1ab94SDag-Erling Smørgrav } 38460245e42SDag-Erling Smørgrav 38560245e42SDag-Erling Smørgrav /* 38660245e42SDag-Erling Smørgrav * Free a URL 38760245e42SDag-Erling Smørgrav */ 38860245e42SDag-Erling Smørgrav void 38960245e42SDag-Erling Smørgrav fetchFreeURL(struct url *u) 39060245e42SDag-Erling Smørgrav { 39160245e42SDag-Erling Smørgrav free(u->doc); 39260245e42SDag-Erling Smørgrav free(u); 39360245e42SDag-Erling Smørgrav } 394