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 * 28*8e3986eaSDag-Erling Smørgrav * $Id: http.c,v 1.1.1.1 1998/07/09 16:52:41 des Exp $ 294ca1ab94SDag-Erling Smørgrav */ 304ca1ab94SDag-Erling Smørgrav 314ca1ab94SDag-Erling Smørgrav #include <sys/param.h> 324ca1ab94SDag-Erling Smørgrav #include <sys/errno.h> 334ca1ab94SDag-Erling Smørgrav #include <sys/socket.h> 344ca1ab94SDag-Erling Smørgrav #include <sys/types.h> 354ca1ab94SDag-Erling Smørgrav 364ca1ab94SDag-Erling Smørgrav #include <netinet/in.h> 374ca1ab94SDag-Erling Smørgrav 384ca1ab94SDag-Erling Smørgrav #include <err.h> 394ca1ab94SDag-Erling Smørgrav #include <ctype.h> 404ca1ab94SDag-Erling Smørgrav #include <netdb.h> 414ca1ab94SDag-Erling Smørgrav #include <stdio.h> 424ca1ab94SDag-Erling Smørgrav #include <stdlib.h> 434ca1ab94SDag-Erling Smørgrav #include <string.h> 444ca1ab94SDag-Erling Smørgrav #include <unistd.h> 454ca1ab94SDag-Erling Smørgrav 464ca1ab94SDag-Erling Smørgrav #include "fetch.h" 474ca1ab94SDag-Erling Smørgrav #include "httperr.c" 484ca1ab94SDag-Erling Smørgrav 494ca1ab94SDag-Erling Smørgrav #ifndef NDEBUG 504ca1ab94SDag-Erling Smørgrav #define DEBUG(x) do x; while (0) 514ca1ab94SDag-Erling Smørgrav #else 524ca1ab94SDag-Erling Smørgrav #define DEBUG(x) do { } while (0) 534ca1ab94SDag-Erling Smørgrav #endif 544ca1ab94SDag-Erling Smørgrav 554ca1ab94SDag-Erling Smørgrav extern char *__progname; 564ca1ab94SDag-Erling Smørgrav 574ca1ab94SDag-Erling Smørgrav extern int fprint64(FILE *f, const unsigned char *buf); 584ca1ab94SDag-Erling Smørgrav 594ca1ab94SDag-Erling Smørgrav #define ENDL "\r\n" 604ca1ab94SDag-Erling Smørgrav 614ca1ab94SDag-Erling Smørgrav struct cookie 624ca1ab94SDag-Erling Smørgrav { 634ca1ab94SDag-Erling Smørgrav FILE *real_f; 644ca1ab94SDag-Erling Smørgrav #define ENC_NONE 0 654ca1ab94SDag-Erling Smørgrav #define ENC_CHUNKED 1 664ca1ab94SDag-Erling Smørgrav int encoding; /* 1 = chunked, 0 = none */ 674ca1ab94SDag-Erling Smørgrav #define HTTPCTYPELEN 59 684ca1ab94SDag-Erling Smørgrav char content_type[HTTPCTYPELEN+1]; 694ca1ab94SDag-Erling Smørgrav char *buf; 704ca1ab94SDag-Erling Smørgrav int b_cur, eof; 714ca1ab94SDag-Erling Smørgrav unsigned b_len, chunksize; 724ca1ab94SDag-Erling Smørgrav }; 734ca1ab94SDag-Erling Smørgrav 74*8e3986eaSDag-Erling Smørgrav static const char * 75*8e3986eaSDag-Erling Smørgrav _http_errstring(int e) 764ca1ab94SDag-Erling Smørgrav { 77*8e3986eaSDag-Erling Smørgrav struct httperr *p = _http_errlist; 784ca1ab94SDag-Erling Smørgrav 79*8e3986eaSDag-Erling Smørgrav while ((p->num != -1) && (p->num != e)) 80*8e3986eaSDag-Erling Smørgrav p++; 814ca1ab94SDag-Erling Smørgrav 82*8e3986eaSDag-Erling Smørgrav return p->string; 834ca1ab94SDag-Erling Smørgrav } 844ca1ab94SDag-Erling Smørgrav 854ca1ab94SDag-Erling Smørgrav static char * 864ca1ab94SDag-Erling Smørgrav _http_fillbuf(struct cookie *c) 874ca1ab94SDag-Erling Smørgrav { 884ca1ab94SDag-Erling Smørgrav char *ln; 894ca1ab94SDag-Erling Smørgrav unsigned int len; 904ca1ab94SDag-Erling Smørgrav 914ca1ab94SDag-Erling Smørgrav if (c->eof) 924ca1ab94SDag-Erling Smørgrav return NULL; 934ca1ab94SDag-Erling Smørgrav 944ca1ab94SDag-Erling Smørgrav if (c->encoding == ENC_NONE) { 954ca1ab94SDag-Erling Smørgrav c->buf = fgetln(c->real_f, &(c->b_len)); 964ca1ab94SDag-Erling Smørgrav c->b_cur = 0; 974ca1ab94SDag-Erling Smørgrav } else if (c->encoding == ENC_CHUNKED) { 984ca1ab94SDag-Erling Smørgrav if (c->chunksize == 0) { 994ca1ab94SDag-Erling Smørgrav ln = fgetln(c->real_f, &len); 1004ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, "\033[1m_http_fillbuf(): new chunk: " 1014ca1ab94SDag-Erling Smørgrav "%*.*s\033[m\n", (int)len-2, (int)len-2, ln)); 1024ca1ab94SDag-Erling Smørgrav sscanf(ln, "%x", &(c->chunksize)); 1034ca1ab94SDag-Erling Smørgrav if (!c->chunksize) { 1044ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, "\033[1m_http_fillbuf(): " 1054ca1ab94SDag-Erling Smørgrav "end of last chunk\033[m\n")); 1064ca1ab94SDag-Erling Smørgrav c->eof = 1; 1074ca1ab94SDag-Erling Smørgrav return NULL; 1084ca1ab94SDag-Erling Smørgrav } 1094ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, "\033[1m_http_fillbuf(): " 1104ca1ab94SDag-Erling Smørgrav "new chunk: %X\033[m\n", c->chunksize)); 1114ca1ab94SDag-Erling Smørgrav } 1124ca1ab94SDag-Erling Smørgrav c->buf = fgetln(c->real_f, &(c->b_len)); 1134ca1ab94SDag-Erling Smørgrav if (c->b_len > c->chunksize) 1144ca1ab94SDag-Erling Smørgrav c->b_len = c->chunksize; 1154ca1ab94SDag-Erling Smørgrav c->chunksize -= c->b_len; 1164ca1ab94SDag-Erling Smørgrav c->b_cur = 0; 1174ca1ab94SDag-Erling Smørgrav } 1184ca1ab94SDag-Erling Smørgrav else return NULL; /* unknown encoding */ 1194ca1ab94SDag-Erling Smørgrav return c->buf; 1204ca1ab94SDag-Erling Smørgrav } 1214ca1ab94SDag-Erling Smørgrav 1224ca1ab94SDag-Erling Smørgrav static int 1234ca1ab94SDag-Erling Smørgrav _http_readfn(struct cookie *c, char *buf, int len) 1244ca1ab94SDag-Erling Smørgrav { 1254ca1ab94SDag-Erling Smørgrav int l, pos = 0; 1264ca1ab94SDag-Erling Smørgrav while (len) { 1274ca1ab94SDag-Erling Smørgrav /* empty buffer */ 1284ca1ab94SDag-Erling Smørgrav if (!c->buf || (c->b_cur == c->b_len)) 1294ca1ab94SDag-Erling Smørgrav if (!_http_fillbuf(c)) 1304ca1ab94SDag-Erling Smørgrav break; 1314ca1ab94SDag-Erling Smørgrav 1324ca1ab94SDag-Erling Smørgrav l = c->b_len - c->b_cur; 1334ca1ab94SDag-Erling Smørgrav if (len < l) l = len; 1344ca1ab94SDag-Erling Smørgrav memcpy(buf + pos, c->buf + c->b_cur, l); 1354ca1ab94SDag-Erling Smørgrav c->b_cur += l; 1364ca1ab94SDag-Erling Smørgrav pos += l; 1374ca1ab94SDag-Erling Smørgrav len -= l; 1384ca1ab94SDag-Erling Smørgrav } 1394ca1ab94SDag-Erling Smørgrav 1404ca1ab94SDag-Erling Smørgrav if (ferror(c->real_f)) 1414ca1ab94SDag-Erling Smørgrav return -1; 1424ca1ab94SDag-Erling Smørgrav else return pos; 1434ca1ab94SDag-Erling Smørgrav } 1444ca1ab94SDag-Erling Smørgrav 1454ca1ab94SDag-Erling Smørgrav static int 1464ca1ab94SDag-Erling Smørgrav _http_writefn(struct cookie *c, const char *buf, int len) 1474ca1ab94SDag-Erling Smørgrav { 1484ca1ab94SDag-Erling Smørgrav size_t r = fwrite(buf, 1, (size_t)len, c->real_f); 1494ca1ab94SDag-Erling Smørgrav return r ? r : -1; 1504ca1ab94SDag-Erling Smørgrav } 1514ca1ab94SDag-Erling Smørgrav 1524ca1ab94SDag-Erling Smørgrav static int 1534ca1ab94SDag-Erling Smørgrav _http_closefn(struct cookie *c) 1544ca1ab94SDag-Erling Smørgrav { 1554ca1ab94SDag-Erling Smørgrav int r = fclose(c->real_f); 1564ca1ab94SDag-Erling Smørgrav free(c); 1574ca1ab94SDag-Erling Smørgrav return (r == EOF) ? -1 : 0; 1584ca1ab94SDag-Erling Smørgrav } 1594ca1ab94SDag-Erling Smørgrav 1604ca1ab94SDag-Erling Smørgrav char * 1614ca1ab94SDag-Erling Smørgrav fetchContentType(FILE *f) 1624ca1ab94SDag-Erling Smørgrav { 1634ca1ab94SDag-Erling Smørgrav /* 1644ca1ab94SDag-Erling Smørgrav * We have no way of making sure this really *is* one of our cookies, 1654ca1ab94SDag-Erling Smørgrav * so just check for a null pointer and hope for the best. 1664ca1ab94SDag-Erling Smørgrav */ 1674ca1ab94SDag-Erling Smørgrav return f->_cookie ? (((struct cookie *)f->_cookie)->content_type) : NULL; 1684ca1ab94SDag-Erling Smørgrav } 1694ca1ab94SDag-Erling Smørgrav 1704ca1ab94SDag-Erling Smørgrav FILE * 1714ca1ab94SDag-Erling Smørgrav fetchGetHTTP(url_t *URL, char *flags) 1724ca1ab94SDag-Erling Smørgrav { 173*8e3986eaSDag-Erling Smørgrav int sd = -1, err, i, enc = ENC_NONE; 1744ca1ab94SDag-Erling Smørgrav struct cookie *c; 1754ca1ab94SDag-Erling Smørgrav char *ln, *p, *q; 1764ca1ab94SDag-Erling Smørgrav FILE *f, *cf; 1774ca1ab94SDag-Erling Smørgrav size_t len; 1784ca1ab94SDag-Erling Smørgrav 1794ca1ab94SDag-Erling Smørgrav /* allocate cookie */ 1804ca1ab94SDag-Erling Smørgrav if ((c = calloc(1, sizeof(struct cookie))) == NULL) 1814ca1ab94SDag-Erling Smørgrav return NULL; 1824ca1ab94SDag-Erling Smørgrav 1834ca1ab94SDag-Erling Smørgrav /* check port */ 1844ca1ab94SDag-Erling Smørgrav if (!URL->port) 1854ca1ab94SDag-Erling Smørgrav URL->port = 80; /* default HTTP port */ 1864ca1ab94SDag-Erling Smørgrav 1874ca1ab94SDag-Erling Smørgrav /* attempt to connect to proxy server */ 1884ca1ab94SDag-Erling Smørgrav if (getenv("HTTP_PROXY")) { 1894ca1ab94SDag-Erling Smørgrav char *px, host[MAXHOSTNAMELEN]; 1904ca1ab94SDag-Erling Smørgrav int port = 3128; /* XXX I think 3128 is default... check? */ 1914ca1ab94SDag-Erling Smørgrav size_t len; 1924ca1ab94SDag-Erling Smørgrav 1934ca1ab94SDag-Erling Smørgrav /* measure length */ 1944ca1ab94SDag-Erling Smørgrav px = getenv("HTTP_PROXY"); 1954ca1ab94SDag-Erling Smørgrav len = strcspn(px, ":"); 1964ca1ab94SDag-Erling Smørgrav 1974ca1ab94SDag-Erling Smørgrav /* get port (atoi is a little too tolerant perhaps?) */ 1984ca1ab94SDag-Erling Smørgrav if (px[len] == ':') 1994ca1ab94SDag-Erling Smørgrav port = atoi(px+len+1); 2004ca1ab94SDag-Erling Smørgrav 2014ca1ab94SDag-Erling Smørgrav /* get host name */ 2024ca1ab94SDag-Erling Smørgrav if (len >= MAXHOSTNAMELEN) 2034ca1ab94SDag-Erling Smørgrav len = MAXHOSTNAMELEN - 1; 2044ca1ab94SDag-Erling Smørgrav strncpy(host, px, len); 2054ca1ab94SDag-Erling Smørgrav host[len] = 0; 2064ca1ab94SDag-Erling Smørgrav 2074ca1ab94SDag-Erling Smørgrav /* connect */ 208*8e3986eaSDag-Erling Smørgrav sd = fetchConnect(host, port); 2094ca1ab94SDag-Erling Smørgrav } 2104ca1ab94SDag-Erling Smørgrav 2114ca1ab94SDag-Erling Smørgrav /* if no proxy is configured or could be contacted, try direct */ 212*8e3986eaSDag-Erling Smørgrav if (sd < 0) { 213*8e3986eaSDag-Erling Smørgrav if ((sd = fetchConnect(URL->host, URL->port)) < 0) 2144ca1ab94SDag-Erling Smørgrav goto ouch; 2154ca1ab94SDag-Erling Smørgrav } 2164ca1ab94SDag-Erling Smørgrav 2174ca1ab94SDag-Erling Smørgrav /* reopen as stream */ 218*8e3986eaSDag-Erling Smørgrav if ((f = fdopen(sd, "r+")) == NULL) 2194ca1ab94SDag-Erling Smørgrav goto ouch; 2204ca1ab94SDag-Erling Smørgrav c->real_f = f; 2214ca1ab94SDag-Erling Smørgrav 2224ca1ab94SDag-Erling Smørgrav /* send request (proxies require absolute form, so use that) */ 2234ca1ab94SDag-Erling Smørgrav fprintf(f, "GET http://%s:%d/%s HTTP/1.1" ENDL, 2244ca1ab94SDag-Erling Smørgrav URL->host, URL->port, URL->doc); 2254ca1ab94SDag-Erling Smørgrav 2264ca1ab94SDag-Erling Smørgrav /* start sending headers away */ 2274ca1ab94SDag-Erling Smørgrav if (URL->user[0] || URL->pwd[0]) { 2284ca1ab94SDag-Erling Smørgrav fprintf(f, "Authorization: Basic "); 2294ca1ab94SDag-Erling Smørgrav fprint64(f, (const unsigned char *)URL->user); 2304ca1ab94SDag-Erling Smørgrav fputc(':', f); 2314ca1ab94SDag-Erling Smørgrav fprint64(f, (const unsigned char *)URL->pwd); 2324ca1ab94SDag-Erling Smørgrav fputs(ENDL, f); 2334ca1ab94SDag-Erling Smørgrav } 2344ca1ab94SDag-Erling Smørgrav fprintf(f, "Host: %s:%d" ENDL, URL->host, URL->port); 2354ca1ab94SDag-Erling Smørgrav fprintf(f, "User-Agent: %s " _LIBFETCH_VER ENDL, __progname); 2364ca1ab94SDag-Erling Smørgrav fprintf(f, "Connection: close" ENDL ENDL); 2374ca1ab94SDag-Erling Smørgrav 2384ca1ab94SDag-Erling Smørgrav /* get response */ 2394ca1ab94SDag-Erling Smørgrav if ((ln = fgetln(f, &len)) == NULL) 2404ca1ab94SDag-Erling Smørgrav goto fouch; 2414ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, "response: [\033[1m%*.*s\033[m]\n", 2424ca1ab94SDag-Erling Smørgrav (int)len-2, (int)len-2, ln)); 2434ca1ab94SDag-Erling Smørgrav 2444ca1ab94SDag-Erling Smørgrav /* we can't use strchr() and friends since ln isn't NUL-terminated */ 2454ca1ab94SDag-Erling Smørgrav p = ln; 2464ca1ab94SDag-Erling Smørgrav while ((p < ln + len) && !isspace(*p)) 2474ca1ab94SDag-Erling Smørgrav p++; 2484ca1ab94SDag-Erling Smørgrav while ((p < ln + len) && !isdigit(*p)) 2494ca1ab94SDag-Erling Smørgrav p++; 2504ca1ab94SDag-Erling Smørgrav if (!isdigit(*p)) 2514ca1ab94SDag-Erling Smørgrav goto fouch; 2524ca1ab94SDag-Erling Smørgrav err = atoi(p); 2534ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, "code: [\033[1m%d\033[m]\n", err)); 2544ca1ab94SDag-Erling Smørgrav 2554ca1ab94SDag-Erling Smørgrav /* add code to handle redirects later */ 256*8e3986eaSDag-Erling Smørgrav if (err != 200) { 257*8e3986eaSDag-Erling Smørgrav fetchLastErrCode = err; 258*8e3986eaSDag-Erling Smørgrav fetchLastErrText = _http_errstring(err); 2594ca1ab94SDag-Erling Smørgrav goto fouch; 260*8e3986eaSDag-Erling Smørgrav } 2614ca1ab94SDag-Erling Smørgrav 2624ca1ab94SDag-Erling Smørgrav /* browse through header */ 2634ca1ab94SDag-Erling Smørgrav while (1) { 2644ca1ab94SDag-Erling Smørgrav if ((ln = fgetln(f, &len)) == NULL) 2654ca1ab94SDag-Erling Smørgrav goto fouch; 2664ca1ab94SDag-Erling Smørgrav if ((ln[0] == '\r') || (ln[0] == '\n')) 2674ca1ab94SDag-Erling Smørgrav break; 2684ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, "header: [\033[1m%*.*s\033[m]\n", 2694ca1ab94SDag-Erling Smørgrav (int)len-2, (int)len-2, ln)); 2704ca1ab94SDag-Erling Smørgrav #define XFERENC "Transfer-Encoding:" 2714ca1ab94SDag-Erling Smørgrav if (strncasecmp(ln, XFERENC, sizeof(XFERENC)-1) == 0) { 2724ca1ab94SDag-Erling Smørgrav p = ln + sizeof(XFERENC) - 1; 2734ca1ab94SDag-Erling Smørgrav while ((p < ln + len) && isspace(*p)) 2744ca1ab94SDag-Erling Smørgrav p++; 2754ca1ab94SDag-Erling Smørgrav for (q = p; (q < ln + len) && !isspace(*q); q++) 2764ca1ab94SDag-Erling Smørgrav /* VOID */ ; 2774ca1ab94SDag-Erling Smørgrav *q = 0; 2784ca1ab94SDag-Erling Smørgrav if (strcasecmp(p, "chunked") == 0) 2794ca1ab94SDag-Erling Smørgrav enc = ENC_CHUNKED; 2804ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, "xferenc: [\033[1m%s\033[m]\n", p)); 2814ca1ab94SDag-Erling Smørgrav #undef XFERENC 2824ca1ab94SDag-Erling Smørgrav #define CONTTYPE "Content-Type:" 2834ca1ab94SDag-Erling Smørgrav } else if (strncasecmp(ln, CONTTYPE, sizeof(CONTTYPE)-1) == 0) { 2844ca1ab94SDag-Erling Smørgrav p = ln + sizeof(CONTTYPE) - 1; 2854ca1ab94SDag-Erling Smørgrav while ((p < ln + len) && isspace(*p)) 2864ca1ab94SDag-Erling Smørgrav p++; 2874ca1ab94SDag-Erling Smørgrav for (i = 0; p < ln + len; p++) 2884ca1ab94SDag-Erling Smørgrav if (i < HTTPCTYPELEN) 2894ca1ab94SDag-Erling Smørgrav c->content_type[i++] = *p; 2904ca1ab94SDag-Erling Smørgrav do c->content_type[i--] = 0; while (isspace(c->content_type[i])); 2914ca1ab94SDag-Erling Smørgrav DEBUG(fprintf(stderr, "conttype: [\033[1m%s\033[m]\n", 2924ca1ab94SDag-Erling Smørgrav c->content_type)); 2934ca1ab94SDag-Erling Smørgrav #undef CONTTYPE 2944ca1ab94SDag-Erling Smørgrav } 2954ca1ab94SDag-Erling Smørgrav } 2964ca1ab94SDag-Erling Smørgrav 2974ca1ab94SDag-Erling Smørgrav /* only body remains */ 2984ca1ab94SDag-Erling Smørgrav c->encoding = enc; 2994ca1ab94SDag-Erling Smørgrav cf = funopen(c, 3004ca1ab94SDag-Erling Smørgrav (int (*)(void *, char *, int))_http_readfn, 3014ca1ab94SDag-Erling Smørgrav (int (*)(void *, const char *, int))_http_writefn, 3024ca1ab94SDag-Erling Smørgrav (fpos_t (*)(void *, fpos_t, int))NULL, 3034ca1ab94SDag-Erling Smørgrav (int (*)(void *))_http_closefn); 3044ca1ab94SDag-Erling Smørgrav if (cf == NULL) 3054ca1ab94SDag-Erling Smørgrav goto fouch; 3064ca1ab94SDag-Erling Smørgrav return cf; 3074ca1ab94SDag-Erling Smørgrav 3084ca1ab94SDag-Erling Smørgrav ouch: 309*8e3986eaSDag-Erling Smørgrav if (sd >= 0) 310*8e3986eaSDag-Erling Smørgrav close(sd); 3114ca1ab94SDag-Erling Smørgrav free(c); 3124ca1ab94SDag-Erling Smørgrav return NULL; 3134ca1ab94SDag-Erling Smørgrav fouch: 3144ca1ab94SDag-Erling Smørgrav fclose(f); 3154ca1ab94SDag-Erling Smørgrav free(c); 3164ca1ab94SDag-Erling Smørgrav return NULL; 3174ca1ab94SDag-Erling Smørgrav } 3184ca1ab94SDag-Erling Smørgrav 3194ca1ab94SDag-Erling Smørgrav FILE * 3204ca1ab94SDag-Erling Smørgrav fetchPutHTTP(url_t *URL, char *flags) 3214ca1ab94SDag-Erling Smørgrav { 3224ca1ab94SDag-Erling Smørgrav warnx("fetchPutHTTP(): not implemented"); 3234ca1ab94SDag-Erling Smørgrav return NULL; 3244ca1ab94SDag-Erling Smørgrav } 325