Annotation of libwww/Library/src/HTTPReq.c, revision 2.57
2.1 frystyk 1: /* HTTPReq.c
2.23 frystyk 2: ** HTTP REQUEST GENERATION
2.1 frystyk 3: **
2.32 frystyk 4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.57 ! frystyk 6: ** @(#) $Id: HTTPReq.c,v 2.56 1998/11/19 15:06:30 frystyk Exp $
2.32 frystyk 7: **
2.1 frystyk 8: ** This module implements the output stream for HTTP used for sending
9: ** requests with or without a entity body.
10: **
11: ** History:
12: ** Jan 95 HFN Written from scratch
13: */
14:
15: /* Library Includes */
2.52 frystyk 16: #include "wwwsys.h"
2.28 frystyk 17: #include "WWWUtil.h"
2.32 frystyk 18: #include "WWWCore.h"
19:
2.23 frystyk 20: #include "HTTPGen.h"
2.21 frystyk 21: #include "HTTPUtil.h"
2.1 frystyk 22: #include "HTTPReq.h" /* Implements */
23:
2.24 frystyk 24: #define PUTC(c) (*me->target->isa->put_character)(me->target, c)
25: #define PUTS(s) (*me->target->isa->put_string)(me->target, s)
2.1 frystyk 26: #define PUTBLOCK(b, l) (*me->target->isa->put_block)(me->target, b, l)
27:
28: struct _HTStream {
2.29 frystyk 29: const HTStreamClass * isa;
2.1 frystyk 30: HTStream * target;
31: HTRequest * request;
2.18 frystyk 32: SOCKET sockfd;
2.11 frystyk 33: int version;
2.38 frystyk 34: int state;
35: char * url;
2.1 frystyk 36: BOOL transparent;
37: };
38:
39: /* ------------------------------------------------------------------------- */
40: /* HTTP Output Request Stream */
41: /* ------------------------------------------------------------------------- */
42:
2.11 frystyk 43: /* HTTP09Request
44: ** -------------
45: ** Makes a HTTP/0.9 request
2.1 frystyk 46: */
2.38 frystyk 47: PRIVATE int HTTP09Request (HTStream * me, HTRequest * request)
2.11 frystyk 48: {
2.34 frystyk 49: HTParentAnchor * anchor = HTRequest_anchor(request);
50: char * addr = HTAnchor_physical(anchor);
2.38 frystyk 51: if (!me->url) me->url = HTParse(addr, "", PARSE_PATH|PARSE_PUNCTUATION);
52: if (me->state == 0) {
2.47 frystyk 53: int status = PUTS("GET ");
54: if (status != HT_OK) return status;
2.38 frystyk 55: me->state++;
56: }
57: if (me->state == 1) {
58: int status = PUTS(me->url);
59: if (status != HT_OK) return status;
60: me->state++;
61: }
2.24 frystyk 62: PUTC(CR);
63: PUTC(LF);
2.53 frystyk 64: if (PROT_TRACE)HTTrace("HTTP........ Generating HTTP/0.9 Request\n");
2.38 frystyk 65: return HT_OK;
2.11 frystyk 66: }
67:
68: /* HTTPMakeRequest
69: ** ---------------
70: ** Makes a HTTP/1.0-1.1 request header.
71: */
2.38 frystyk 72: PRIVATE int HTTPMakeRequest (HTStream * me, HTRequest * request)
2.1 frystyk 73: {
2.39 frystyk 74: HTMethod method = HTRequest_method(request);
75: HTRqHd request_mask = HTRequest_rqHd(request);
76: HTParentAnchor * anchor = HTRequest_anchor(request);
2.43 frystyk 77: char * etag = HTAnchor_etag(anchor);
2.24 frystyk 78: char crlf[3];
79: char qstr[10];
80: *crlf = CR; *(crlf+1) = LF; *(crlf+2) = '\0';
2.1 frystyk 81:
2.41 frystyk 82: /* Generate the HTTP/1.x RequestLine */
2.38 frystyk 83: if (me->state == 0) {
2.34 frystyk 84: if (method != METHOD_INVALID) {
85: PUTS(HTMethod_name(method));
86: PUTC(' ');
87: } else
88: PUTS("GET ");
2.38 frystyk 89: me->state++;
2.34 frystyk 90: }
2.1 frystyk 91:
2.39 frystyk 92: /*
2.45 frystyk 93: ** Generate the Request URI. If we are using full request URI then it's
94: ** easy. Otherwise we must filter out the path part of the URI.
95: ** In case it's a OPTIONS request then if there is no pathinfo then use
96: ** a * instead. If we use a method different from GET or HEAD then use
97: ** the content-location if available.
2.39 frystyk 98: */
2.45 frystyk 99: if (me->state == 1) {
100: char * abs_location = NULL;
2.38 frystyk 101: char * addr = HTAnchor_physical(anchor);
2.45 frystyk 102:
103: /*
104: ** If we are using a method different from HEAD and GET then use
105: ** the Content-Location if available, else the Request-URI.
106: */
107: if (!HTMethod_isSafe(method)) {
108: char * location = HTAnchor_location(anchor);
109: if (location) {
110: if (HTURL_isAbsolute(location))
111: addr = location;
112: else {
113: /*
114: ** We have a content-location but it is relative and
115: ** must expand it either to the content-base or to
116: ** the Request-URI itself.
117: */
118: char * base = HTAnchor_base(anchor);
119: abs_location = HTParse(location, base, PARSE_ALL);
120: addr = abs_location;
121: }
122: }
123: }
124:
125: /*
126: ** If we are using a proxy or newer versions of HTTP then we can
127: ** send the full URL. Otherwise we only send the path.
128: */
129: if (HTRequest_fullURI(request))
130: StrAllocCopy(me->url, addr);
131: else {
132: me->url = HTParse(addr, "", PARSE_PATH | PARSE_PUNCTUATION);
2.39 frystyk 133: if (method == METHOD_OPTIONS) {
134: /*
135: ** We don't preserve the final slash or lack of same through
136: ** out the code. This is mainly for optimization reasons
2.44 frystyk 137: ** but it gives a problem OPTIONS. We can either send a "*"
138: ** or a "/" but not both. For now we send a "*".
2.39 frystyk 139: */
2.45 frystyk 140: if (!strcmp(me->url, "/")) *me->url = '*';
2.39 frystyk 141: }
2.1 frystyk 142: }
2.45 frystyk 143: HT_FREE(abs_location);
144: me->state++;
145: }
146:
147: /*
148: ** Now send the URL that we have put together
149: */
150: if (me->state == 2) {
151: int status = HT_OK;
152: if ((status = PUTS(me->url)) != HT_OK) return status;
2.38 frystyk 153: me->state++;
2.48 frystyk 154:
155: #if 0
156: fprintf(stderr, "Requesting '%s'\n", me->url);
157: #endif
158:
2.1 frystyk 159: }
2.25 frystyk 160: PUTC(' ');
2.41 frystyk 161:
162: /*
163: ** Send out the version number. If we know it is a HTTP/1.0 server we
164: ** are talking to then use HTTP/1.0, else use HTTP/1.1 as default version
165: ** number
166: */
167: if (me->version == HTTP_10)
168: PUTS(HTTP_VERSION_10);
169: else
170: PUTS(HTTP_VERSION);
2.24 frystyk 171: PUTBLOCK(crlf, 2);
2.1 frystyk 172:
2.4 frystyk 173: /* Request Headers */
2.34 frystyk 174: if (request_mask & HT_C_ACCEPT_TYPE) {
2.37 frystyk 175: /*
176: ** If caller has specified a specific output format then use this.
177: ** Otherwise use all the registered converters to generate the
178: ** accept header
179: */
180: if (HTRequest_outputFormat(request) == WWW_PRESENT) {
181: int list;
182: HTList *cur;
183: BOOL first=YES;
184: for (list=0; list<2; list++) {
185: if ((!list && ((cur = HTFormat_conversion()) != NULL)) ||
186: (list && ((cur = HTRequest_conversion(request))!=NULL))) {
187: HTPresentation * pres;
188: while ((pres=(HTPresentation *) HTList_nextObject(cur))) {
189: if (pres->rep_out==WWW_PRESENT && pres->quality<=1.0) {
190: if (first) {
191: PUTS("Accept: ");
192: first=NO;
193: } else
194: PUTC(',');
195: PUTS(HTAtom_name(pres->rep));
2.46 frystyk 196: if (pres->quality < 1.0 && pres->quality >= 0.0) {
2.37 frystyk 197: sprintf(qstr, ";q=%1.1f", pres->quality);
198: PUTS(qstr);
199: }
2.1 frystyk 200: }
201: }
202: }
203: }
2.37 frystyk 204: if (!first) PUTBLOCK(crlf, 2);
205: } else {
206: PUTS("Accept: ");
207: PUTS(HTAtom_name(HTRequest_outputFormat(request)));
208: PUTBLOCK(crlf, 2);
209: }
2.1 frystyk 210: }
2.34 frystyk 211: if (request_mask & HT_C_ACCEPT_CHAR) {
2.4 frystyk 212: int list;
213: HTList *cur;
2.24 frystyk 214: BOOL first=YES;
2.4 frystyk 215: for (list=0; list<2; list++) {
2.14 frystyk 216: if ((!list && ((cur = HTFormat_charset()) != NULL)) ||
217: (list && ((cur = HTRequest_charset(request)) != NULL))) {
2.4 frystyk 218: HTAcceptNode *pres;
219: while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
2.5 frystyk 220: if (first) {
2.24 frystyk 221: PUTS("Accept-Charset: ");
2.5 frystyk 222: first=NO;
2.24 frystyk 223: } else
224: PUTC(',');
225: PUTS(HTAtom_name(pres->atom));
2.46 frystyk 226: if (pres->quality < 1.0 && pres->quality >= 0.0) {
227: sprintf(qstr, ";q=%1.1f", pres->quality);
228: PUTS(qstr);
229: }
2.4 frystyk 230: }
231: }
232: }
2.31 frystyk 233: if (!first) PUTBLOCK(crlf, 2);
2.4 frystyk 234: }
2.34 frystyk 235: if (request_mask & HT_C_ACCEPT_ENC) {
2.4 frystyk 236: int list;
237: HTList *cur;
2.24 frystyk 238: BOOL first=YES;
2.4 frystyk 239: for (list=0; list<2; list++) {
2.33 frystyk 240: if ((!list && ((cur = HTFormat_contentCoding()) != NULL)) ||
2.14 frystyk 241: (list && ((cur = HTRequest_encoding(request)) != NULL))) {
2.33 frystyk 242: HTCoding * pres;
243: while ((pres = (HTCoding *) HTList_nextObject(cur))) {
2.46 frystyk 244: double quality = HTCoding_quality(pres);
2.5 frystyk 245: if (first) {
2.24 frystyk 246: PUTS("Accept-Encoding: ");
2.32 frystyk 247: first = NO;
2.24 frystyk 248: } else
249: PUTC(',');
2.33 frystyk 250: PUTS(HTCoding_name(pres));
2.46 frystyk 251: if (quality < 1.0 && quality >= 0.0) {
252: sprintf(qstr, ";q=%1.1f", quality);
253: PUTS(qstr);
254: }
255: }
256: }
257: }
258: if (!first) PUTBLOCK(crlf, 2);
259: }
260: if (request_mask & HT_C_ACCEPT_TE) {
261: int list;
262: HTList *cur;
263: BOOL first=YES;
264: for (list=0; list<2; list++) {
265: if ((!list && ((cur = HTFormat_transferCoding()) != NULL)) ||
266: (list && ((cur = HTRequest_transfer(request)) != NULL))) {
267: HTCoding * pres;
268: while ((pres = (HTCoding *) HTList_nextObject(cur))) {
269: double quality = HTCoding_quality(pres);
2.55 frystyk 270: const char * coding = HTCoding_name(pres);
2.46 frystyk 271: if (first) {
272: PUTS("TE: ");
273: first = NO;
274: } else
275: PUTC(',');
2.55 frystyk 276:
277: /* Special check for "chunked" which is translated to "trailers" */
278: if (!strcasecomp(coding, "chunked"))
279: PUTS("trailers");
280: else
281: PUTS(coding);
2.46 frystyk 282: if (quality < 1.0 && quality >= 0.0) {
283: sprintf(qstr, ";q=%1.1f", quality);
284: PUTS(qstr);
285: }
2.4 frystyk 286: }
287: }
288: }
2.31 frystyk 289: if (!first) PUTBLOCK(crlf, 2);
2.4 frystyk 290: }
2.34 frystyk 291: if (request_mask & HT_C_ACCEPT_LAN) {
2.4 frystyk 292: int list;
293: HTList *cur;
2.24 frystyk 294: BOOL first=YES;
2.4 frystyk 295: for (list=0; list<2; list++) {
2.14 frystyk 296: if ((!list && ((cur = HTFormat_language()) != NULL)) ||
297: (list && ((cur = HTRequest_language(request)) != NULL))) {
2.4 frystyk 298: HTAcceptNode *pres;
299: while ((pres = (HTAcceptNode *) HTList_nextObject(cur))) {
2.5 frystyk 300: if (first) {
2.24 frystyk 301: PUTS("Accept-Language: ");
2.5 frystyk 302: first=NO;
2.24 frystyk 303: } else
304: PUTC(',');
305: PUTS(HTAtom_name(pres->atom));
2.46 frystyk 306: if (pres->quality < 1.0 && pres->quality >= 0.0) {
2.24 frystyk 307: sprintf(qstr, ";q=%1.1f", pres->quality);
308: PUTS(qstr);
2.5 frystyk 309: }
2.4 frystyk 310: }
311: }
312: }
2.31 frystyk 313: if (!first) PUTBLOCK(crlf, 2);
2.4 frystyk 314: }
2.36 frystyk 315: if (request_mask & HT_C_AUTH) {
2.34 frystyk 316: HTAssocList * cur = HTRequest_credentials(request);
317: if (cur) { /* Access authentication */
318: HTAssoc * pres;
319: while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
320: PUTS(HTAssoc_name(pres));
321: PUTS(": ");
322: PUTS(HTAssoc_value(pres));
323: PUTBLOCK(crlf, 2);
324: }
2.28 frystyk 325: }
2.1 frystyk 326: }
2.46 frystyk 327: if (request_mask & HT_C_EXPECT) {
328: HTAssocList * cur = HTRequest_expect(request);
329: if (cur) {
330: BOOL first=YES;
331: HTAssoc * pres;
332: while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
333: char * value = HTAssoc_value(pres);
334: if (first) {
335: PUTS("Expect: ");
336: first = NO;
337: } else
338: PUTC(',');
339:
340: /* Output the name */
341: PUTS(HTAssoc_name(pres));
342:
343: /* Only output the value if not empty string */
344: if (*value) {
345: PUTS("=");
346: PUTS(value);
347: }
348: }
349: PUTBLOCK(crlf, 2);
350: }
351: }
2.34 frystyk 352: if (request_mask & HT_C_FROM) {
353: HTUserProfile * up = HTRequest_userProfile(request);
354: const char * mailaddress = HTUserProfile_email(up);
2.1 frystyk 355: if (mailaddress) {
2.24 frystyk 356: PUTS("From: ");
357: PUTS(mailaddress);
358: PUTBLOCK(crlf, 2);
2.1 frystyk 359: }
360: }
2.34 frystyk 361: if (request_mask & HT_C_HOST) {
2.13 frystyk 362: char *orig = HTAnchor_address((HTAnchor *) anchor);
2.12 frystyk 363: char *host = HTParse(orig, "", PARSE_HOST);
2.34 frystyk 364: #if 0
365: /* Keep the port number for HTTP/1.1 compliance */
2.12 frystyk 366: char *ptr = strchr(host, ':'); /* Chop off port number */
367: if (ptr) *ptr = '\0';
2.34 frystyk 368: #endif
2.24 frystyk 369: PUTS("Host: ");
370: PUTS(host);
371: PUTBLOCK(crlf, 2);
2.26 frystyk 372: HT_FREE(orig);
373: HT_FREE(host);
2.39 frystyk 374: }
2.42 frystyk 375:
376: /*
377: ** In the "If-*" series of headers, the ones related to etags have higher
378: ** priority than the date relates ones. That is, if we have a etag then
2.45 frystyk 379: ** use that, otherwise use the date. First we check for range, match, and
380: ** unmodified-since.
2.42 frystyk 381: */
2.45 frystyk 382: if (request_mask & HT_C_IF_RANGE && etag) {
383: PUTS("If-Range: \"");
384: PUTS(etag);
385: PUTC('"');
386: PUTBLOCK(crlf, 2);
387: if (PROT_TRACE) HTTrace("HTTP........ If-Range using etag `%s\'\n", etag);
2.57 ! frystyk 388: } else if (request_mask & HT_C_IF_MATCH_ANY) {
2.56 frystyk 389: PUTS("If-Match: *");
390: PUTBLOCK(crlf, 2);
391: if (PROT_TRACE) HTTrace("HTTP........ If-Match using `*\'\n");
2.45 frystyk 392: } else if (request_mask & HT_C_IF_MATCH && etag) {
2.43 frystyk 393: PUTS("If-Match: \"");
394: PUTS(etag);
395: PUTC('"');
396: PUTBLOCK(crlf, 2);
397: if (PROT_TRACE) HTTrace("HTTP........ If-Match using etag `%s\'\n", etag);
398: } else if (request_mask & HT_C_IF_UNMOD_SINCE) {
2.42 frystyk 399: time_t lm = HTAnchor_lastModified(anchor);
400: if (lm > 0) {
2.43 frystyk 401: PUTS("If-Unmodified-Since: ");
2.42 frystyk 402: PUTS(HTDateTimeStr(&lm, NO));
403: PUTBLOCK(crlf, 2);
2.43 frystyk 404: if (PROT_TRACE) HTTrace("HTTP........ If-Unmodified-Since\n");
2.42 frystyk 405: }
406: }
2.45 frystyk 407:
408: /*
409: ** If-None-Match and If-Modified-Since are equivalent except that the
410: ** first uses etags and the second uses dates. Etags have precedence over
411: ** dates.
412: */
2.57 ! frystyk 413: if (request_mask & HT_C_IF_NONE_MATCH_ANY) {
2.56 frystyk 414: PUTS("If-None-Match: *");
415: PUTBLOCK(crlf, 2);
416: if (PROT_TRACE) HTTrace("HTTP........ If-None-Match using `*\'\n");
417: } else if (request_mask & HT_C_IF_NONE_MATCH && etag) {
2.43 frystyk 418: PUTS("If-None-Match: \"");
419: PUTS(etag);
420: PUTC('"');
421: PUTBLOCK(crlf, 2);
2.46 frystyk 422: if (PROT_TRACE) HTTrace("HTTP........ If-None-Match `%s\'\n", etag);
423: }
424: if (request_mask & HT_C_IMS) {
2.42 frystyk 425: time_t lm = HTAnchor_lastModified(anchor);
426: if (lm > 0) {
2.43 frystyk 427: PUTS("If-Modified-Since: ");
2.42 frystyk 428: PUTS(HTDateTimeStr(&lm, NO));
429: PUTBLOCK(crlf, 2);
2.43 frystyk 430: if (PROT_TRACE) HTTrace("HTTP........ If-Modified-Since\n");
2.42 frystyk 431: }
432: }
433:
2.45 frystyk 434: /*
435: ** Max forwards is mainly for TRACE where we want to be able to stop the
436: ** TRACE at a specific location un the message path.
437: */
2.39 frystyk 438: if (request_mask & HT_C_MAX_FORWARDS) {
439: int hops = HTRequest_maxForwards(request);
440: if (hops >= 0) {
441: sprintf(qstr, "%d", hops);
442: PUTS("Max-Forwards: ");
443: PUTS(qstr);
444: PUTBLOCK(crlf, 2);
445: }
2.42 frystyk 446: }
2.45 frystyk 447:
448: /*
449: ** Range requests. For now, we only take the first entry registered for
450: ** this request. This means that you can only send a single "unit" and
451: ** then a set of range within this unit. This is in accordance with
452: ** HTTP/1.1. Multiple units will go on multiple lines.
453: */
2.42 frystyk 454: if (request_mask & HT_C_RANGE) {
2.45 frystyk 455: HTAssocList * cur = HTRequest_range(request);
456: if (cur) { /* Range requests */
457: HTAssoc * pres;
458: while ((pres = (HTAssoc *) HTAssocList_nextObject(cur))) {
459: PUTS("Range: ");
460: PUTS(HTAssoc_name(pres)); /* Unit */
461: PUTS("=");
462: PUTS(HTAssoc_value(pres)); /* Ranges within this unit */
463: PUTBLOCK(crlf, 2);
464: }
465: }
2.1 frystyk 466: }
2.34 frystyk 467: if (request_mask & HT_C_REFERER) {
468: HTParentAnchor * parent_anchor = HTRequest_parent(request);
469: if (parent_anchor) {
470: char * act = HTAnchor_address((HTAnchor *) anchor);
471: char * parent = HTAnchor_address((HTAnchor *) parent_anchor);
2.50 frystyk 472: #if 1
473: char * relative = HTRelative(parent, act);
474: #else
2.34 frystyk 475: char * relative = HTParse(parent, act,
476: PARSE_ACCESS|PARSE_HOST|PARSE_PATH|PARSE_PUNCTUATION);
2.50 frystyk 477: #endif
2.34 frystyk 478: if (relative && *relative) {
479: PUTS("Referer: ");
2.50 frystyk 480: PUTS(relative);
2.34 frystyk 481: PUTBLOCK(crlf, 2);
482: }
483: HT_FREE(act);
484: HT_FREE(parent);
485: HT_FREE(relative);
2.1 frystyk 486: }
487: }
2.34 frystyk 488: if (request_mask & HT_C_USER_AGENT) {
2.24 frystyk 489: PUTS("User-Agent: ");
490: PUTS(HTLib_appName());
491: PUTC('/');
492: PUTS(HTLib_appVersion());
493: PUTC(' ');
494: PUTS(HTLib_name());
495: PUTC('/');
496: PUTS(HTLib_version());
497: PUTBLOCK(crlf, 2);
2.1 frystyk 498: }
2.53 frystyk 499: if (PROT_TRACE) HTTrace("HTTP........ Generating HTTP/1.x Request Headers\n");
2.38 frystyk 500: return HT_OK;
2.1 frystyk 501: }
502:
2.29 frystyk 503: PRIVATE int HTTPRequest_put_block (HTStream * me, const char * b, int l)
2.1 frystyk 504: {
2.7 frystyk 505: if (!me->target) {
2.1 frystyk 506: return HT_WOULD_BLOCK;
2.7 frystyk 507: } else if (me->transparent)
2.11 frystyk 508: return b ? PUTBLOCK(b, l) : HT_OK;
2.1 frystyk 509: else {
2.38 frystyk 510: int status = HT_OK;
511: if (me->version == HTTP_09) {
512: status = HTTP09Request(me, me->request);
513: if (status != HT_OK) return status;
514: } else {
515: status = HTTPMakeRequest(me, me->request);
516: if (status != HT_OK) return status;
2.1 frystyk 517: me->transparent = YES;
2.11 frystyk 518: return b ? PUTBLOCK(b, l) : HT_OK;
2.1 frystyk 519: }
520: return status;
521: }
522: }
523:
2.16 frystyk 524: PRIVATE int HTTPRequest_put_character (HTStream * me, char c)
2.1 frystyk 525: {
2.11 frystyk 526: return HTTPRequest_put_block(me, &c, 1);
2.1 frystyk 527: }
528:
2.29 frystyk 529: PRIVATE int HTTPRequest_put_string (HTStream * me, const char * s)
2.1 frystyk 530: {
2.11 frystyk 531: return HTTPRequest_put_block(me, s, strlen(s));
2.1 frystyk 532: }
533:
534: /*
535: ** Flushes data but doesn't free stream object
536: */
2.16 frystyk 537: PRIVATE int HTTPRequest_flush (HTStream * me)
2.1 frystyk 538: {
2.13 frystyk 539: int status = HTTPRequest_put_block(me, NULL, 0);
540: return status==HT_OK ? (*me->target->isa->flush)(me->target) : status;
2.1 frystyk 541: }
542:
543: /*
544: ** Flushes data and frees stream object
545: */
2.16 frystyk 546: PRIVATE int HTTPRequest_free (HTStream * me)
2.1 frystyk 547: {
2.11 frystyk 548: int status = HTTPRequest_flush(me);
549: if (status != HT_WOULD_BLOCK) {
550: if ((status = (*me->target->isa->_free)(me->target)) == HT_WOULD_BLOCK)
551: return HT_WOULD_BLOCK;
2.38 frystyk 552: HT_FREE(me->url);
2.26 frystyk 553: HT_FREE(me);
2.1 frystyk 554: }
2.7 frystyk 555: return status;
2.1 frystyk 556: }
557:
2.16 frystyk 558: PRIVATE int HTTPRequest_abort (HTStream * me, HTList * e)
2.1 frystyk 559: {
2.27 eric 560: if (PROT_TRACE) HTTrace("HTTPRequest. ABORTING...\n");
2.51 kahan 561: /* JK: Added protection against NULL pointers */
2.49 frystyk 562: if (me) {
2.51 kahan 563: if (me->target && me->target->isa)
564: (*me->target->isa->abort)(me->target, e);
565: if (me->url)
566: HT_FREE(me->url);
2.49 frystyk 567: HT_FREE(me);
568: }
2.1 frystyk 569: return HT_ERROR;
570: }
571:
572: /* HTTPRequest Stream
573: ** -----------------
574: */
2.29 frystyk 575: PRIVATE const HTStreamClass HTTPRequestClass =
2.1 frystyk 576: {
577: "HTTPRequest",
578: HTTPRequest_flush,
579: HTTPRequest_free,
580: HTTPRequest_abort,
581: HTTPRequest_put_character,
582: HTTPRequest_put_string,
583: HTTPRequest_put_block
584: };
585:
2.23 frystyk 586: PUBLIC HTStream * HTTPRequest_new (HTRequest * request, HTStream * target,
2.45 frystyk 587: BOOL endHeader, int version)
2.1 frystyk 588: {
2.26 frystyk 589: HTStream * me;
590: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
591: HT_OUTOFMEM("HTTPRequest_new");
2.1 frystyk 592: me->isa = &HTTPRequestClass;
593: me->target = target;
594: me->request = request;
2.45 frystyk 595: me->version = version;
2.1 frystyk 596: me->transparent = NO;
2.46 frystyk 597:
598: /*
599: ** If sending a body in the request then we want a 100 code!
600: */
601: if (HTMethod_hasEntity(HTRequest_method(request)))
602: HTRequest_addExpect(request, "100-continue", "");
603:
2.23 frystyk 604:
605: /* Return general HTTP header stream */
2.45 frystyk 606: return HTTPGen_new(request, me, endHeader, version);
2.1 frystyk 607: }
Webmaster