bugfixes; build system changed again %-)
[syren.git] / src / syren_http.c
blob0bb040013479c21e39edb801ecc86bb929b937dd
1 /*
2 Syren -- a lightweight downloader for Linux/BSD/Win/MacOSX
3 inspired by Axel Copyright 2001-2002 Wilmer van der Gaast
4 version 0.0.6 (atomic alien)
5 coded by Ketmar // Avalon Group
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License with
18 the Debian GNU/Linux distribution in file /usr/doc/copyright/GPL;
19 if not, write to the Free Software Foundation, Inc., 59 Temple Place,
20 Suite 330, Boston, MA 02111-1307 USA
23 Syren http utilities
25 #ifndef _SYREN_HTTP_C
26 #define _SYREN_HTTP_C
28 #include "syren_http.h"
31 /* return ptr to next line */
32 static char *SyHTTPFixLine (char *curstr) {
33 char *nl = curstr, *res;
35 while (*nl && *nl != '\n') nl++;
36 res = nl+(*nl?1:0);
37 *nl = '\0';
38 if (nl > curstr && *(nl-1) == '\r') *(nl-1) = '\0';
40 return res;
44 TSyResult SyHTTPReadHeaders (TSyHdrs *hdrs, TSySocket *fd, const TSyPrintStr *pfn) {
45 char *hdrbuf, *curstr, *nextstr;
46 TSyResult res;
48 SyMessage(pfn, SY_MSG_NOTICE, "reading reply headers");
49 if (!hdrs) return SY_ERROR;
50 SyHdrClear(hdrs, SY_HDR_REPLY);
51 if (fd < 0) return SY_ERROR;
52 hdrbuf = SyTCPReceiveHdrs(fd, 65536);
53 if (!hdrbuf) {
54 SyMessage(pfn, SY_MSG_ERROR, "error receiving reply headers");
55 return SY_ERROR;
57 curstr = hdrbuf;
58 while (*curstr) {
59 nextstr = SyHTTPFixLine(curstr);
60 if (!nextstr[0]) break;
61 SyMessage(pfn, SY_MSG_NOTICE, " %s", curstr);
62 res = SyHdrAddLine(hdrs, curstr);
63 if (res != SY_OK) {
64 SyMessage(pfn, SY_MSG_ERROR, "can't parse reply header string");
65 return SY_ERROR;
67 curstr = nextstr;
69 if (hdrs->code < 0) {
70 SyMessage(pfn, SY_MSG_ERROR, "empty reply headers");
71 return SY_ERROR;
73 SyMessage(pfn, SY_MSG_NOTICE, " reply headers received; code: %i", hdrs->code);
74 return SY_OK;
78 /* -1: none or error */
79 int64_t SyHTTPGetSize (const TSyHdrs *hdrs) {
80 int64_t res;
81 char *buf = SyHdrGetFieldValue(hdrs, "content-length");
82 res = SyStr2Long(buf); free(buf);
83 return res;
87 static TSyResult SyHTTPAddAuth (TSyHdrs *hdrs, const char *astr, const TSyURL *url) {
88 TSyResult res;
89 const char *user, *pass;
90 char *tmp, *s;
92 user = url->user; pass = url->pass;
93 if ((user && *user) || (pass && *pass)) {
94 tmp = SyBuildAuthStr(user, pass); if (!tmp) return SY_ERROR;
95 s = SySPrintf(astr, tmp);
96 free(tmp); if (!s) return SY_ERROR;
97 res = SyHdrAddLine(hdrs, s); free(s);
98 if (res != SY_OK) return SY_ERROR;
101 return SY_OK;
105 TSyResult SyHTTPBuildQuery (TSyHdrs *hdrs, const char *method, const TSyURL *url, const TSyURL *proxy) {
106 char port[32], *tmp, *s;
107 const char *mt;
108 TSyResult res;
109 if (!hdrs) return SY_ERROR;
111 SyHdrClear(hdrs, SY_HDR_REQUEST);
112 if (!url) return SY_ERROR;
113 /* query string */
114 if (url->port != 80) sprintf(port, ":%i", url->port); else *port = '\0';
115 mt = (method && *method)?method:"GET";
116 if (proxy) {
117 /*if (*url->user || *url->pass)
118 s = SySPrintf("%s %s://%s:%s@%s%s", mt, url->protostr, url->user, url->pass, url->host, port);
119 else*/
120 s = SySPrintf("%s %s://%s%s", mt, url->protostr, url->host, port);
121 } else s = SySPrintf("%s ", mt);
122 if (!s) return SY_ERROR;
123 tmp = SySPrintf("%s%s%s%s%s HTTP/1.0", s, url->dir, url->file, url->query, url->anchor);
124 free(s); if (!tmp) return SY_ERROR;
125 res = SyHdrAddLine(hdrs, tmp); free(tmp);
126 if (res != SY_OK) return SY_ERROR;
127 /* auth */
128 if (proxy) {
129 if (SyHTTPAddAuth(hdrs, "Proxy-Authorization: Basic %s", proxy) != SY_OK) return SY_ERROR;
131 if (SyHTTPAddAuth(hdrs, "Authorization: Basic %s", url) != SY_OK) return SY_ERROR;
132 /* host */
133 if (url->port != 80) s = SySPrintf("Host: %s:%i", url->host, url->port); /* don't add 443 for HTTPS? */
134 else s = SySPrintf("Host: %s", url->host);
135 if (!s) return SY_ERROR;
136 res = SyHdrAddLine(hdrs, s); free(s);
137 return res;
141 TSyResult SyHTTPAddRange (TSyHdrs *hdrs, int from, int to) {
142 TSyResult res;
143 char *s;
144 if (!hdrs) return SY_ERROR;
145 if (from <= 0) {
146 if (to < 0) return SY_OK;
147 from = 0;
149 if (to >= 0 && to < from) return SY_ERROR;
150 if (to >= 0) {
151 if (from > 0) s = SySPrintf("Range: bytes=%i-%i", from, to);
152 else s = SySPrintf("Range: bytes=-%i", to);
153 } else {
154 if (from > 0) s = SySPrintf("Range: bytes=%i-", from); else return SY_OK;
156 res = SyHdrAddLine(hdrs, s); free(s);
157 return res;
161 /* FIXME: hide password! */
162 TSyResult SyHTTPSendQuery (TSySocket *fd, const TSyHdrs *hdrs, const TSyPrintStr *pfn) {
163 TSyKVListItem *item, *ci;
164 TSyKVList *cc;
166 if (!hdrs || !hdrs->fields || hdrs->type == SY_HDR_INVALID) return SY_ERROR;
167 if (!hdrs->firstLine) { SyMessage(pfn, SY_MSG_ERROR, "incomplete header"); return SY_ERROR; }
168 if (SyTCPSendLine(pfn, 1, fd, "%s", hdrs->firstLine) != SY_OK) return SY_ERROR;
169 /* auth */
170 item = hdrs->fields->first;
171 while (item) {
172 cc = item->udata;
173 if (cc && cc->count) {
174 ci = cc->first;
175 while (ci) {
176 if (SyTCPSendLine(pfn, 1, fd, "%s: %s", item->key, ci->value) != SY_OK) return SY_ERROR;
177 ci = ci->next;
179 } else {
180 if (SyTCPSendLine(pfn, 1, fd, "%s: %s", item->key, item->value) != SY_OK) return SY_ERROR;
182 item = item->next;
184 return SyTCPSendLine(pfn, 0, fd, "");
188 #endif