~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbms/src/cslib/CSHTTPStream.cc

  • Committer: Stewart Smith
  • Date: 2010-11-03 03:27:09 UTC
  • mto: (1902.1.1 build) (1910.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 1903.
  • Revision ID: stewart@flamingspork.com-20101103032709-oyvfrc6eb8fzj0mr
fix docs warning: docs/unlock.rst:2: (WARNING/2) Title underline too short.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
 
2
 *
 
3
 * PrimeBase Media Stream for MySQL
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or modify
 
6
 * it under the terms of the GNU General Public License as published by
 
7
 * the Free Software Foundation; either version 2 of the License, or
 
8
 * (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
18
 *
 
19
 * Original author: Paul McCullagh (H&G2JCtL)
 
20
 * Continued development: Barry Leslie
 
21
 *
 
22
 * 2007-06-10
 
23
 *
 
24
 * A basic syncronized object.
 
25
 *
 
26
 */
 
27
#include "CSConfig.h"
 
28
 
 
29
#include <stdlib.h>
 
30
#include <string.h>
 
31
#include <inttypes.h>
 
32
 
 
33
#include "CSGlobal.h"
 
34
#include "CSHTTPStream.h"
 
35
#include "CSLog.h"
 
36
 
 
37
#ifdef DEBUG
 
38
//#define PRINT_HEADER
 
39
#endif
 
40
 
 
41
/*
 
42
 * ---------------------------------------------------------------
 
43
 * HTTP HEADERS
 
44
 */
 
45
 
 
46
CSHeader::~CSHeader()
 
47
{
 
48
        if (iName) {
 
49
                iName->release();
 
50
                iName = NULL;
 
51
        }
 
52
        if (iValue) {
 
53
                iValue->release();
 
54
                iValue = NULL;
 
55
        }
 
56
}
 
57
 
 
58
void CSHeader::setName(const char *name)
 
59
{
 
60
        iName = CSString::newString(name);
 
61
}
 
62
 
 
63
void CSHeader::setName(const char *name, uint32_t len)
 
64
{
 
65
        iName = CSString::newString(name, len);
 
66
}
 
67
 
 
68
void CSHeader::setName(CSString *name)
 
69
{
 
70
        iName = name;
 
71
}
 
72
 
 
73
void CSHeader::setValue(const char *value)
 
74
{
 
75
        iValue = CSString::newString(value);
 
76
}
 
77
 
 
78
void CSHeader::setValue(const char *value, uint32_t len)
 
79
{
 
80
        iValue = CSString::newString(value, len);
 
81
}
 
82
 
 
83
void CSHeader::setValue(CSString *value)
 
84
{
 
85
        iValue = value;
 
86
}
 
87
 
 
88
void CSHeader::write(CSOutputStream *out, bool trace)
 
89
{
 
90
        if (trace)
 
91
                printf("%s: %s\n", iName->getCString(), iValue->getCString());
 
92
 
 
93
        out->print(iName);
 
94
        out->print(": ");
 
95
        if (iValue)
 
96
                out->print(iValue);
 
97
        out->print("\r\n");
 
98
}
 
99
 
 
100
void CSHTTPHeaders::clearHeaders()
 
101
{
 
102
        iKeepAlive = false;
 
103
        iExpect100Continue = false;
 
104
        iUnknownEpectHeader = false;
 
105
        if (iHeaders) {
 
106
                iHeaders->release();
 
107
                iHeaders = NULL;
 
108
        }
 
109
}
 
110
CSVector *CSHTTPHeaders::takeHeaders()
 
111
{
 
112
        CSVector *headers = iHeaders;
 
113
        iHeaders = NULL;
 
114
        return headers;
 
115
}
 
116
 
 
117
void CSHTTPHeaders::setHeaders(CSVector *headers)
 
118
{
 
119
        if (iHeaders) 
 
120
                iHeaders->release();
 
121
        iHeaders = headers;
 
122
}
 
123
 
 
124
void CSHTTPHeaders::addHeader(CSHeader *h)
 
125
{
 
126
        if (!iHeaders)
 
127
                new_(iHeaders, CSVector(5));
 
128
 
 
129
        if (strcasecmp(h->getNameCString(), "Connection") == 0 && strcasecmp(h->getValueCString(), "Keep-Alive") == 0)
 
130
                iKeepAlive = true;
 
131
                
 
132
        if (strcasecmp(h->getNameCString(), "Expect") == 0) {
 
133
                if (strcasecmp(h->getValueCString(), "100-continue") == 0)
 
134
                        iExpect100Continue = true;
 
135
                else
 
136
                        iUnknownEpectHeader = true;
 
137
        }
 
138
                
 
139
        iHeaders->add(h);
 
140
}
 
141
 
 
142
void CSHTTPHeaders::addHeaders(CSHTTPHeaders *headers)
 
143
{
 
144
        CSHeader *h;
 
145
        uint32_t i =0;
 
146
        while ((h = headers->getHeader(i++))) {
 
147
                addHeader(h);
 
148
        }
 
149
}
 
150
 
 
151
void CSHTTPHeaders::addHeader(const char *name, const char *value)
 
152
{
 
153
        CSHeader *h;
 
154
 
 
155
        enter_();
 
156
        if (!iHeaders)
 
157
                new_(iHeaders, CSVector(5));
 
158
 
 
159
        new_(h, CSHeader());
 
160
        push_(h);
 
161
        h->setName(name);
 
162
        h->setValue(value);
 
163
        pop_(h);
 
164
 
 
165
        addHeader(h);
 
166
        exit_();
 
167
}
 
168
 
 
169
void CSHTTPHeaders::addHeader(const char *name, uint32_t nlen, const char *value, uint32_t vlen)
 
170
{
 
171
        CSHeader *h;
 
172
 
 
173
        enter_();
 
174
        if (!iHeaders)
 
175
                new_(iHeaders, CSVector(5));
 
176
 
 
177
        new_(h, CSHeader());
 
178
        push_(h);
 
179
        h->setName(name, nlen);
 
180
        h->setValue(value, vlen);
 
181
        pop_(h);
 
182
        addHeader(h);
 
183
        exit_();
 
184
}
 
185
 
 
186
void CSHTTPHeaders::addHeader(CSString *name, CSString *value)
 
187
{
 
188
        CSHeader *h;
 
189
 
 
190
        enter_();
 
191
        push_(name);
 
192
        push_(value);
 
193
        if (!iHeaders)
 
194
                new_(iHeaders, CSVector(5));
 
195
 
 
196
        new_(h, CSHeader());
 
197
        pop_(value);
 
198
        pop_(name);
 
199
        h->setName(name);
 
200
        h->setValue(value);
 
201
        addHeader(h);
 
202
        exit_();
 
203
}
 
204
 
 
205
void CSHTTPHeaders::addHeader(const char *name, CSString *value)
 
206
{
 
207
        CSHeader *h;
 
208
        CSString *n;
 
209
 
 
210
        enter_();
 
211
        push_(value);
 
212
        n = CSString::newString(name);
 
213
        push_(n);
 
214
        if (!iHeaders)
 
215
                new_(iHeaders, CSVector(5));
 
216
        new_(h, CSHeader());
 
217
        pop_(n);
 
218
        pop_(value);
 
219
        h->setName(n);
 
220
        h->setValue(value);
 
221
        addHeader(h);
 
222
        exit_();
 
223
}
 
224
 
 
225
void CSHTTPHeaders::addHeader(const char *name, uint64_t value)
 
226
{
 
227
        char buffer[30];
 
228
 
 
229
        snprintf(buffer, 30, "%"PRIu64, value);
 
230
        addHeader(name, buffer);
 
231
}
 
232
 
 
233
void CSHTTPHeaders::removeHeader(CSString *name)
 
234
{
 
235
        enter_();
 
236
        push_(name);
 
237
        if (iHeaders) {
 
238
                CSHeader *h;
 
239
 
 
240
                for (uint32_t i=0; i<iHeaders->size(); ) {
 
241
                        h = (CSHeader *) iHeaders->get(i);
 
242
                        if (h->getName()->compare(name) == 0) {
 
243
                                iHeaders->remove(i);
 
244
                        } else 
 
245
                                i++;
 
246
                }
 
247
        }
 
248
        release_(name);
 
249
        
 
250
        exit_();
 
251
}
 
252
 
 
253
void CSHTTPHeaders::removeHeader(const char *name)
 
254
{
 
255
        removeHeader(CSString::newString(name));
 
256
}
 
257
 
 
258
CSString *CSHTTPHeaders::getHeaderValue(const char *name)
 
259
{
 
260
        CSString *v;
 
261
 
 
262
        v = NULL;
 
263
        if (iHeaders) {
 
264
                CSHeader *h;
 
265
 
 
266
                for (uint32_t i=0; i<iHeaders->size(); i++) {
 
267
                        h = (CSHeader *) iHeaders->get(i);
 
268
                        if (h->getName()->compare(name) == 0) {
 
269
                                v = h->getValue();
 
270
                                v->retain();
 
271
                                break;
 
272
                        }
 
273
                }
 
274
        }
 
275
        return v;
 
276
}
 
277
 
 
278
const char *CSHTTPHeaders::getHeaderCStringValue(const char *name)
 
279
{
 
280
        if (iHeaders) {
 
281
                CSHeader *h;
 
282
 
 
283
                for (uint32_t i=0; i<iHeaders->size(); i++) {
 
284
                        h = (CSHeader *) iHeaders->get(i);
 
285
                        if (h->getName()->compare(name) == 0) {
 
286
                                return h->getValue()->getCString();
 
287
                        }
 
288
                }
 
289
        }
 
290
        return NULL;
 
291
}
 
292
 
 
293
void CSHTTPHeaders::writeHeader(CSOutputStream *out, bool trace)
 
294
{
 
295
        if (iHeaders) {
 
296
                CSHeader *h;
 
297
 
 
298
                for (uint32_t i=0; i<iHeaders->size(); i++) {
 
299
                        h = (CSHeader *) iHeaders->get(i);
 
300
                        h->write(out, trace);
 
301
                }
 
302
        }
 
303
}
 
304
 
 
305
bool CSHTTPHeaders::keepAlive()
 
306
{
 
307
        return iKeepAlive;
 
308
}
 
309
 
 
310
bool CSHTTPHeaders::expect100Continue()
 
311
{
 
312
        return iExpect100Continue;
 
313
}
 
314
 
 
315
bool CSHTTPHeaders::unknownEpectHeader()
 
316
{
 
317
        return iUnknownEpectHeader;
 
318
}
 
319
 
 
320
/*
 
321
 * ---------------------------------------------------------------
 
322
 * HTTP INPUT STREAMS
 
323
 */
 
324
 
 
325
CSHTTPInputStream::CSHTTPInputStream(CSInputStream* in):
 
326
CSHTTPHeaders(),
 
327
iInput(NULL),
 
328
iMethod(NULL),
 
329
iRequestURI(NULL),
 
330
iHTTPVersion(NULL),
 
331
iStatusPhrase(NULL)
 
332
{
 
333
        iInput = in;
 
334
}
 
335
 
 
336
CSHTTPInputStream::~CSHTTPInputStream()
 
337
{
 
338
        freeHead();
 
339
        if (iInput)
 
340
                iInput->release();
 
341
}
 
342
 
 
343
void CSHTTPInputStream::readHead(bool trace)
 
344
{
 
345
        CSStringBuffer  *sb = NULL;
 
346
        bool                    first_line = true;
 
347
        uint32_t                        start, end;
 
348
 
 
349
        enter_();
 
350
        freeHead();
 
351
        for (;;) {
 
352
                sb = iInput->readLine();
 
353
                if (!sb)
 
354
                        break;
 
355
                if (trace) {
 
356
                        if (first_line)
 
357
                                CSL.log(self, CSLog::Protocol, "HTTP Request - Header:\n");
 
358
                        printf("%s\n", sb->getCString());
 
359
                }
 
360
                if (sb->length() == 0) {
 
361
                        sb->release();
 
362
                        break;
 
363
                }
 
364
                push_(sb);
 
365
                
 
366
                if (first_line) {
 
367
                        CSString *str;
 
368
                        start = sb->ignore(0, ' ');
 
369
                        end = sb->find(start, ' ');
 
370
                        str = sb->substr(start, end - start);
 
371
                        if (str->startsWith("HTTP")) { // Reply header
 
372
                                iMethod = NULL;
 
373
                                iRequestURI = NULL;
 
374
                                iHTTPVersion = str;
 
375
                                start = sb->ignore(end, ' ');
 
376
                                end = sb->find(start, ' ');
 
377
                                if (start > end)
 
378
                                        CSException::throwException(CS_CONTEXT, CS_ERR_BAD_HTTP_HEADER, "Bad HTTP header");
 
379
 
 
380
                                str = sb->substr(start, end - start);
 
381
                                iStatus = atol(str->getCString());
 
382
                                str->release();
 
383
                                start = sb->ignore(end, ' ');
 
384
                                end = sb->find(start, '\r');
 
385
                                if (start > end)
 
386
                                        CSException::throwException(CS_CONTEXT, CS_ERR_BAD_HTTP_HEADER, "Bad HTTP header");
 
387
                                iStatusPhrase = sb->substr(start, end - start);
 
388
                        } else {
 
389
                                iStatus = 0;
 
390
                                iStatusPhrase = NULL;
 
391
                                iMethod = str;
 
392
                        start = sb->ignore(end, ' ');
 
393
                        end = sb->find(start, ' ');
 
394
                        if (start > end)
 
395
                                CSException::throwException(CS_CONTEXT, CS_ERR_BAD_HTTP_HEADER, "Bad HTTP header");
 
396
                        iRequestURI = sb->substr(start, end - start);
 
397
                        start = sb->ignore(end, ' ');
 
398
                        end = sb->find(start, ' ');
 
399
                        if (start > end)
 
400
                                CSException::throwException(CS_CONTEXT, CS_ERR_BAD_HTTP_HEADER, "Bad HTTP header");
 
401
                        iHTTPVersion = sb->substr(start, end - start);
 
402
                        }                               
 
403
                        first_line = false;
 
404
                }
 
405
                else {
 
406
                        uint32_t nstart, nend;
 
407
                        uint32_t vstart, vend;
 
408
 
 
409
                        nstart = sb->ignore(0, ' ');
 
410
                        nend = sb->find(nstart, ':');
 
411
 
 
412
                        vstart = sb->ignore(nend+1, ' ');
 
413
                        vend = sb->find(vstart, '\r');
 
414
 
 
415
                        nend = sb->trim(nend, ' ');
 
416
                        vend = sb->trim(vend, ' ');
 
417
                        
 
418
                        if (vstart > vend)
 
419
                                CSException::throwException(CS_CONTEXT, CS_ERR_BAD_HTTP_HEADER, "Bad HTTP header");
 
420
                        addHeader(sb->getBuffer(nstart), nend-nstart, sb->getBuffer(vstart), vend-vstart);
 
421
                }
 
422
 
 
423
                release_(sb);
 
424
        }
 
425
        exit_();
 
426
}
 
427
 
 
428
void CSHTTPInputStream::readBody()
 
429
{
 
430
        uint64_t        body_size;
 
431
        size_t  tfer, len;
 
432
 
 
433
        if (getContentLength(&body_size)) {
 
434
                iBody.setLength((size_t) body_size);
 
435
                len = 0;
 
436
                while (len < body_size) {
 
437
                        tfer =  read(iBody.getBuffer(len), (size_t)(body_size - len));
 
438
                        if (!tfer)
 
439
                                CSException::throwException(CS_CONTEXT, CS_ERR_BODY_INCOMPLETE, "POST data incomplete");
 
440
                        len += tfer;
 
441
                }
 
442
        }
 
443
        else {
 
444
                CSStringBuffer *sb = NULL;
 
445
 
 
446
                /* Read until we have an empty line. */
 
447
                for (;;) {
 
448
                        sb = readLine();
 
449
                        if (!sb)
 
450
                                break;
 
451
                        if (sb->length() == 0) {
 
452
                                sb->release();
 
453
                                break;
 
454
                        }
 
455
                        iBody.append(sb->getBuffer(0), sb->length());
 
456
                        iBody.append((char) '\n');
 
457
                        sb->release();
 
458
                }
 
459
        }
 
460
}
 
461
 
 
462
bool CSHTTPInputStream::getRange(uint64_t *size, uint64_t *offset)
 
463
{
 
464
        CSString        *val;
 
465
        bool haveRange = false;
 
466
 
 
467
        if ((val = getHeaderValue("Range"))) {
 
468
                uint64_t                first_byte = 0, last_byte = 0;
 
469
                const char      *range = val->getCString();
 
470
                
 
471
                if (range && (val->compare("bytes=", 6) == 0)) {
 
472
                        if ((sscanf(range + 6, "%"PRIu64"-%"PRIu64"", &first_byte, &last_byte) == 2) && (last_byte >= first_byte)) {
 
473
                                *offset = (uint64_t) first_byte;
 
474
                                *size =last_byte - first_byte + 1;
 
475
                                haveRange = true;
 
476
                        }       
 
477
                }
 
478
                val->release();
 
479
                                
 
480
        }
 
481
        return haveRange;
 
482
}
 
483
 
 
484
bool CSHTTPInputStream::getContentLength(uint64_t *length)
 
485
{
 
486
        CSString        *val;
 
487
        uint64_t                size = 0;
 
488
 
 
489
        if ((val = getHeaderValue("Content-Length"))) {
 
490
                const char      *len = val->getCString();
 
491
 
 
492
                if (len)  
 
493
                        sscanf(len, "%"PRIu64"", &size);                
 
494
                val->release();
 
495
                *length = size;
 
496
                return true;
 
497
        }
 
498
        return false;
 
499
}
 
500
 
 
501
const char *CSHTTPInputStream::getMethod()
 
502
{
 
503
        if (!iMethod)
 
504
                return NULL;
 
505
        return iMethod->getCString();
 
506
}
 
507
 
 
508
void CSHTTPInputStream::close()
 
509
{
 
510
        enter_();
 
511
        iInput->close();
 
512
        exit_();
 
513
}
 
514
 
 
515
size_t CSHTTPInputStream::read(char *b, size_t len)
 
516
{
 
517
        enter_();
 
518
        return_(iInput->read(b, len));
 
519
}
 
520
 
 
521
int CSHTTPInputStream::read()
 
522
{
 
523
        enter_();
 
524
        return_(iInput->read());
 
525
}
 
526
 
 
527
int CSHTTPInputStream::peek()
 
528
{
 
529
        enter_();
 
530
        return_(iInput->peek());
 
531
}
 
532
 
 
533
void CSHTTPInputStream::freeHead()
 
534
{
 
535
        enter_();
 
536
        clearHeaders();
 
537
        if (iMethod) {
 
538
                iMethod->release();
 
539
                iMethod = NULL;
 
540
        }
 
541
        if (iRequestURI) {
 
542
                iRequestURI->release();
 
543
                iRequestURI = NULL;
 
544
        }
 
545
        if (iHTTPVersion) {
 
546
                iHTTPVersion->release();
 
547
                iHTTPVersion = NULL;
 
548
        }
 
549
        if (iStatusPhrase) {
 
550
                iStatusPhrase->release();
 
551
                iStatusPhrase = NULL;
 
552
        }
 
553
        iStatus = 0;
 
554
        exit_();
 
555
}
 
556
 
 
557
CSHTTPInputStream *CSHTTPInputStream::newStream(CSInputStream* i)
 
558
{
 
559
        CSHTTPInputStream *s;
 
560
 
 
561
        if (!(s = new CSHTTPInputStream(i))) {
 
562
                i->release();
 
563
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
 
564
        }
 
565
        return s;
 
566
}
 
567
 
 
568
/*
 
569
 * ---------------------------------------------------------------
 
570
 * HTTP OUTPUT STREAMS
 
571
 */
 
572
 
 
573
CSHTTPOutputStream::CSHTTPOutputStream(CSOutputStream* out):
 
574
CSHTTPHeaders(),
 
575
iOutput(NULL),
 
576
iStatus(0),
 
577
iContentLength(0),
 
578
iRangeSize(0),
 
579
iRangeOffset(0),
 
580
iTotalLength(0)
 
581
{
 
582
        iOutput = out;
 
583
        iBody.setGrowSize(120);
 
584
}
 
585
 
 
586
CSHTTPOutputStream::~CSHTTPOutputStream()
 
587
{
 
588
        clearHeaders();
 
589
        clearBody();
 
590
        if (iOutput)
 
591
                iOutput->release();
 
592
}
 
593
 
 
594
void CSHTTPOutputStream::print(const char *str, bool trace)
 
595
{
 
596
        if (trace)
 
597
                printf("%s", str);
 
598
        iOutput->print(str);
 
599
}
 
600
 
 
601
 
 
602
void CSHTTPOutputStream::print(int32_t value, bool trace)
 
603
{
 
604
        if (trace)
 
605
                printf("%d", value);
 
606
        iOutput->print(value);
 
607
}
 
608
 
 
609
void CSHTTPOutputStream::print(uint64_t value, bool trace)
 
610
{
 
611
        if (trace)
 
612
                printf("%"PRIu64, value);
 
613
        iOutput->print(value);
 
614
}
 
615
 
 
616
void CSHTTPOutputStream::writeHeaders(bool trace)
 
617
{
 
618
        writeHeader(this, trace);
 
619
        clearHeaders();
 
620
}
 
621
 
 
622
void CSHTTPOutputStream::writeHead(bool trace)
 
623
{
 
624
        enter_();
 
625
        if (trace)
 
626
                CSL.log(self, CSLog::Protocol, "HTTP Reply - Header:\n");
 
627
        print("HTTP/1.1 ", trace);
 
628
        print(iStatus, trace);
 
629
        print(" ", trace);
 
630
        print(getReasonPhrase(iStatus), trace);
 
631
        print("\r\n", trace);
 
632
        writeHeader(iOutput, trace);
 
633
        print("Content-Length: ", trace);
 
634
        print(iContentLength, trace);
 
635
        print("\r\n", trace);
 
636
        if (iRangeSize && (iStatus == 200)) {
 
637
                print("Content-Range: bytes ", trace);
 
638
                print(iRangeOffset, trace);
 
639
                print("-", trace);
 
640
                print(iRangeOffset + iRangeSize -1, trace);
 
641
                print("/", trace);
 
642
                print(iTotalLength, trace);
 
643
                print("\r\n", trace);
 
644
        }
 
645
        print("\r\n", trace);
 
646
        exit_();
 
647
 
 
648
}
 
649
 
 
650
void CSHTTPOutputStream::clearBody()
 
651
{
 
652
        iRangeSize = 0;
 
653
        iRangeOffset = 0;
 
654
        iTotalLength = 0;
 
655
        iContentLength = 0;
 
656
        iBody.clear();
 
657
}
 
658
 
 
659
void CSHTTPOutputStream::writeBody()
 
660
{
 
661
        iOutput->write(iBody.getBuffer(0), iBody.length());
 
662
}
 
663
 
 
664
void CSHTTPOutputStream::appendBody(const char *str)
 
665
{
 
666
        iBody.append(str);
 
667
        iContentLength = iBody.length();
 
668
}
 
669
 
 
670
void CSHTTPOutputStream::appendBody(int32_t value)
 
671
{
 
672
        iBody.append(value);
 
673
        iContentLength = iBody.length();
 
674
}
 
675
 
 
676
void CSHTTPOutputStream::appendBody(uint32_t value)
 
677
{
 
678
        iBody.append(value);
 
679
        iContentLength = iBody.length();
 
680
}
 
681
 
 
682
void CSHTTPOutputStream::appendBody(uint64_t value)
 
683
{
 
684
        iBody.append(value);
 
685
        iContentLength = iBody.length();
 
686
}
 
687
 
 
688
const char *CSHTTPOutputStream::getBodyData()
 
689
{
 
690
        return iBody.getCString(); 
 
691
}
 
692
 
 
693
size_t CSHTTPOutputStream::getBodyLength()
 
694
{
 
695
        return iBody.length();
 
696
}
 
697
 
 
698
void CSHTTPOutputStream::setBody(CSStringBufferImpl *buf)
 
699
{
 
700
        iBody.take(buf);
 
701
        iContentLength = iBody.length(); 
 
702
}
 
703
 
 
704
void CSHTTPOutputStream::close()
 
705
{
 
706
        enter_();
 
707
        iOutput->close();
 
708
        exit_();
 
709
}
 
710
 
 
711
void CSHTTPOutputStream::write(const char *b, size_t len)
 
712
{
 
713
        enter_();
 
714
        iOutput->write(b, len);
 
715
        exit_();
 
716
}
 
717
 
 
718
void CSHTTPOutputStream::flush()
 
719
{
 
720
        enter_();
 
721
        iOutput->flush();
 
722
        exit_();
 
723
}
 
724
 
 
725
void CSHTTPOutputStream::write(char b)
 
726
{
 
727
        enter_();
 
728
        iOutput->write(b);
 
729
        exit_();
 
730
}
 
731
 
 
732
const char *CSHTTPOutputStream::getReasonPhrase(int code)
 
733
{
 
734
        const char *message = "Unknown Code";
 
735
 
 
736
        switch (code) {
 
737
                case 100: message = "Continue"; break;
 
738
                case 101: message = "Switching Protocols"; break;
 
739
                case 200: message = "OK"; break;
 
740
                case 201: message = "Created"; break;
 
741
                case 202: message = "Accepted"; break;
 
742
                case 203: message = "Non-Authoritative Information"; break;
 
743
                case 204: message = "No Content"; break;
 
744
                case 205: message = "Reset Content"; break;
 
745
                case 206: message = "Partial Content"; break;
 
746
                case 300: message = "Multiple Choices"; break;
 
747
                case 301: message = "Moved Permanently"; break;
 
748
                case 302: message = "Found"; break;
 
749
                case 303: message = "See Other"; break;
 
750
                case 304: message = "Not Modified"; break;
 
751
                case 305: message = "Use Proxy"; break;
 
752
                case 307: message = "Temporary Redirect"; break;
 
753
                case 400: message = "Bad Request"; break;
 
754
                case 401: message = "Unauthorized"; break;
 
755
                case 402: message = "Payment Required"; break;
 
756
                case 403: message = "Forbidden"; break;
 
757
                case 404: message = "Not Found"; break;
 
758
                case 405: message = "Method Not Allowed"; break;
 
759
                case 406: message = "Not Acceptable"; break;
 
760
                case 407: message = "Proxy Authentication Required"; break;
 
761
                case 408: message = "Request Time-out"; break;
 
762
                case 409: message = "Conflict"; break;
 
763
                case 410: message = "Gone"; break;
 
764
                case 411: message = "Length Required"; break;
 
765
                case 412: message = "Precondition Failed"; break;
 
766
                case 413: message = "Request Entity Too Large"; break;
 
767
                case 414: message = "Request-URI Too Large"; break;
 
768
                case 415: message = "Unsupported Media Type"; break;
 
769
                case 416: message = "Requested range not satisfiable"; break;
 
770
                case 417: message = "Expectation Failed"; break;
 
771
                case 500: message = "Internal Server Error"; break;
 
772
                case 501: message = "Not Implemented"; break;
 
773
                case 502: message = "Bad Gateway"; break;
 
774
                case 503: message = "Service Unavailable"; break;
 
775
                case 504: message = "Gateway Time-out"; break;
 
776
                case 505: message = "HTTP Version not supported"; break;
 
777
        }
 
778
        return message;
 
779
}
 
780
 
 
781
CSHTTPOutputStream *CSHTTPOutputStream::newStream(CSOutputStream* i)
 
782
{
 
783
        CSHTTPOutputStream *s;
 
784
 
 
785
        if (!(s = new CSHTTPOutputStream(i))) {
 
786
                i->release();
 
787
                CSException::throwOSError(CS_CONTEXT, ENOMEM);
 
788
        }
 
789
        return s;
 
790
}
 
791
 
 
792