~drizzle-trunk/drizzle/development

1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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>
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
30
#include <string.h>
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
31
#include <inttypes.h>
32
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
33
#include "CSGlobal.h"
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
34
#include "CSHTTPStream.h"
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
35
#include "CSLog.h"
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
63
void CSHeader::setName(const char *name, uint32_t len)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
78
void CSHeader::setValue(const char *value, uint32_t len)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
79
{
80
	iValue = CSString::newString(value, len);
81
}
82
83
void CSHeader::setValue(CSString *value)
84
{
85
	iValue = value;
86
}
87
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
88
void CSHeader::write(CSOutputStream *out, bool trace)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
89
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
90
	if (trace)
91
		printf("%s: %s\n", iName->getCString(), iValue->getCString());
92
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
93
	out->print(iName);
94
	out->print(": ");
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
95
	if (iValue)
96
		out->print(iValue);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
145
	uint32_t i =0;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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());
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
160
	push_(h);
161
	h->setName(name);
162
	h->setValue(value);
163
	pop_(h);
164
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
165
	addHeader(h);
166
	exit_();
167
}
168
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
169
void CSHTTPHeaders::addHeader(const char *name, uint32_t nlen, const char *value, uint32_t vlen)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
170
{
171
	CSHeader *h;
172
173
	enter_();
174
	if (!iHeaders)
175
		new_(iHeaders, CSVector(5));
176
177
	new_(h, CSHeader());
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
178
	push_(h);
179
	h->setName(name, nlen);
180
	h->setValue(value, vlen);
181
	pop_(h);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
233
void CSHTTPHeaders::removeHeader(CSString *name)
234
{
235
	enter_();
236
	push_(name);
237
	if (iHeaders) {
238
		CSHeader *h;
239
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
240
		for (uint32_t i=0; i<iHeaders->size(); ) {
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
266
		for (uint32_t i=0; i<iHeaders->size(); i++) {
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
267
			h = (CSHeader *) iHeaders->get(i);
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
268
			if (h->getName()->compare(name) == 0) {
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
269
				v = h->getValue();
270
				v->retain();
271
				break;
272
			}
273
		}
274
	}
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
343
void CSHTTPInputStream::readHead(bool trace)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
344
{
345
	CSStringBuffer	*sb = NULL;
346
	bool			first_line = true;
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
347
	uint32_t			start, end;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
348
349
	enter_();
350
	freeHead();
351
	for (;;) {
352
		sb = iInput->readLine();
353
		if (!sb)
354
			break;
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
355
		if (trace) {
356
			if (first_line)
357
				CSL.log(self, CSLog::Protocol, "HTTP Request - Header:\n");
358
			printf("%s\n", sb->getCString());
359
		}
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
360
		if (sb->length() == 0) {
361
			sb->release();
362
			break;
363
		}
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
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, ' ');
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
376
				end = sb->find(start, ' ');
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
377
				if (start > end)
378
					CSException::throwException(CS_CONTEXT, CS_ERR_BAD_HTTP_HEADER, "Bad HTTP header");
379
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
380
				str = sb->substr(start, end - start);
1548.2.19 by Barry.Leslie at PrimeBase
Fixes for longjmp clobber problem, (Hopefully)
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);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
424
	}
425
	exit_();
426
}
427
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
484
bool CSHTTPInputStream::getContentLength(uint64_t *length)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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();
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
495
		*length = size;
496
		return true;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
497
	}
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
498
	return false;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
619
	clearHeaders();
620
}
621
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
622
void CSHTTPOutputStream::writeHead(bool trace)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
623
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
636
	if (iRangeSize && (iStatus == 200)) {
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
644
	}
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
645
	print("\r\n", trace);
646
	exit_();
647
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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(); 
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
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