2 Syren -- a lightweight downloader for Linux/BSD/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 3 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 headers list
29 #include "syren_hdrs.h"
32 static void SyHdrClearItem (TSyKVListItem
*key
) {
37 if (cc
) { SyKVListFree(cc
); key
->udata
= NULL
; }
41 static char *SyHdrCookieGetName (const char *cval
) {
44 if (!cval
) return NULL
;
45 while (*s
&& (unsigned char)(*s
) > ' ' && (unsigned char)(*s
) != '=') s
++;
46 if (s
== cval
) return NULL
;
47 return SyStrNew(cval
, s
-cval
);
51 static TSyKVListItem
*SyHdrFindCookieField (const TSyHdrs
*hdr
) {
54 if (!hdr
|| !hdr
->fields
|| hdr
->type
== SY_HDR_INVALID
) return NULL
;
55 item
= hdr
->fields
->first
; while (item
&& !item
->udata
) item
= item
->next
;
60 TSyHdrs
*SyHdrNew (void) {
61 TSyHdrs
*hdr
= calloc(1, sizeof(TSyHdrs
));
63 if (!hdr
) return NULL
;
64 hdr
->fields
= SyKVListNew();
65 if (!hdr
->fields
) { free(hdr
); return NULL
; }
66 hdr
->code
= -1; hdr
->type
= SY_HDR_INVALID
;
71 void SyHdrFree (TSyHdrs
*hdr
) {
73 SyHdrClear(hdr
, SY_HDR_INVALID
); SyKVListFree(hdr
->fields
);
78 void SyHdrClear (TSyHdrs
*hdr
, TSyHdrType type
) {
82 key
= hdr
->fields
->first
;
83 while (key
) { SyHdrClearItem(key
); key
= key
->next
; }
84 SyKVListClear(hdr
->fields
);
86 if (hdr
->firstLine
) { free(hdr
->firstLine
); hdr
->firstLine
= NULL
; }
87 hdr
->code
= -1; hdr
->type
= type
;
91 static TSyKVListItem
*SyHdrAddField (TSyHdrs
*hdr
, const char *kname
, const char *value
, int *newKey
) {
94 if (!hdr
|| !hdr
->fields
|| hdr
->type
== SY_HDR_INVALID
) return NULL
;
95 if (newKey
) *newKey
= 0;
96 if (!strcasecmp(kname
, "Set-Cookie") || !strcasecmp(kname
, "Set-Cookie2") ||
97 !strcasecmp(kname
, "Cookie") || !strcasecmp(kname
, "Cookie2")) {
98 item
= SyKVListSet(hdr
->fields
, kname
, NULL
, newKey
); if (!item
) return NULL
;
99 if (!item
->udata
) item
->udata
= SyKVListNew();
100 if (!item
->udata
) { SyKVListDelete(hdr
->fields
, kname
); return NULL
; }
101 ((TSyKVList
*)(item
->udata
))->casesens
= 1;
102 } else item
= SyKVListSet(hdr
->fields
, kname
, value
, newKey
); if (!item
) return NULL
;
107 TSyResult
SyHdrDeleteField (TSyHdrs
*hdr
, const char *name
) {
110 if (!hdr
|| !hdr
->fields
|| hdr
->type
== SY_HDR_INVALID
|| !name
|| !name
[0]) return SY_ERROR
;
111 item
= SyKVListFind(hdr
->fields
, name
); if (!item
) return SY_ERROR
;
112 SyHdrClearItem(item
);
113 return SyKVListDelete(hdr
->fields
, name
);
117 char *SyHdrGetFieldValue (const TSyHdrs
*hdr
, const char *name
) {
120 if (!hdr
|| !hdr
->fields
|| hdr
->type
== SY_HDR_INVALID
|| !name
|| !name
[0]) return NULL
;
121 item
= SyKVListFind(hdr
->fields
, name
); if (!item
) return NULL
;
122 if (item
->udata
) return NULL
; /* see cookie functions */
123 return SyStrDup(item
->value
);
127 /* set field; correctly processes "Set-Cookie" and "Cookie" */
128 TSyResult
SyHdrSetFieldValue (TSyHdrs
*hdr
, const char *name
, const char *value
) {
133 if (!hdr
|| !hdr
->fields
|| hdr
->type
== SY_HDR_INVALID
|| !name
|| !name
[0] || !value
) return SY_ERROR
;
134 while (*value
&& (unsigned char)(*value
) <= ' ') value
++; /*if (!value[0]) return SY_ERROR;*/
135 item
= SyHdrAddField(hdr
, name
, value
, &newKey
); if (!item
) return SY_ERROR
;
137 s
= SyHdrCookieGetName(value
);
138 if (!s
) { if (newKey
) SyHdrDeleteField(hdr
, name
); return SY_ERROR
; }
140 item
= SyKVListSet(cc
, s
, value
, NULL
);
142 if (!item
) { if (newKey
) SyHdrDeleteField(hdr
, name
); return SY_ERROR
; }
148 TSyKVList
*SyHdrFindCookieList (const TSyHdrs
*hdr
) {
149 TSyKVListItem
*item
= SyHdrFindCookieField(hdr
);
151 if (item
) return (TSyKVList
*)item
->udata
;
156 void SyHdrDeleteCookie (TSyHdrs
*hdr
, const char *name
) {
157 SyKVListDelete(SyHdrFindCookieList(hdr
), name
);
161 /* value must be full value (with 'path', 'domain', etc) */
162 TSyResult
SyHdrSetCookie (TSyHdrs
*hdr
, const char *value
) {
163 TSyKVListItem
*item
= SyHdrFindCookieField(hdr
);
164 return SyHdrSetFieldValue(hdr
,
165 item
?item
->key
:(hdr
->type
==SY_HDR_REQUEST
?"Cookie":"Set-Cookie"),
170 /* add line, parse it, set "code" if necessary */
171 TSyResult
SyHdrAddLine (TSyHdrs
*hdr
, const char *line
) {
175 TSyResult res
= SY_OK
;
177 if (!hdr
|| !hdr
->fields
|| hdr
->type
== SY_HDR_INVALID
|| !line
) return SY_ERROR
;
178 if (!line
[0]) return SY_OK
; /* ignore empty lines */
179 if (hdr
->firstLine
) {
180 /* "name: value" pair or multiline */
181 if ((unsigned char)(*line
) <= ' ') {
182 /* multiline header continues */
183 item
= hdr
->fields
->last
; if (!item
) return SY_ERROR
; /* nothing to continue */
187 item
= cc
->last
; if (!item
) return SY_ERROR
; /* nothing to continue */
189 s
= SySPrintf("%s%s", item
->value
?item
->value
:"", line
); if (!s
) return SY_ERROR
;
190 if (item
->value
) free(item
->value
);
193 /* "name: value" pair */
194 s
= strchr(line
, ':');
195 if (!s
) return SY_ERROR
;
196 n
= SyStrNew(line
, s
-line
); if (!n
) return SY_ERROR
;
197 SyStrTrim(n
); if (!n
[0]) { free(n
); return SY_ERROR
; }
198 s
++; s
= SyStrNew(s
, -1); if (!s
) { free(n
); return SY_ERROR
; }
199 SyStrTrim(s
); if (!s
[0]) { free(s
); free(n
); return SY_OK
; }
200 res
= SyHdrSetFieldValue(hdr
, n
, s
);
205 s
= SyStrNew(line
, -1); if (!s
) return SY_ERROR
;
207 if (hdr
->type
== SY_HDR_REPLY
) {
208 /* parse reply code; bad code is error! */
209 /* hack for brain-damaged 'bandit' server */
211 s
= strstr(s
, "HTTP/"); if (!s
) break;
213 if (isdigit(*s
) && s
[1] == '.' && isdigit(s
[2])) { s
+= 3; break; }
215 if (!s
) return SY_ERROR
;
216 while (*s
&& (unsigned char)(*s
) > ' ') s
++;
217 while (*s
&& (unsigned char)(*s
) <= ' ') s
++;
218 if (!isdigit(*s
) || !isdigit(s
[1]) || !isdigit(s
[2])) return SY_ERROR
;
219 if ((unsigned char)(s
[3]) > ' ') return SY_ERROR
;
220 hdr
->code
= (*s
-'0')*100+(s
[1]-'0')*10+(s
[2]-'0');