/src/resiprocate/resip/stack/Contents.cxx
Line | Count | Source |
1 | | #include <vector> |
2 | | |
3 | | #if defined(HAVE_CONFIG_H) |
4 | | #include "config.h" |
5 | | #endif |
6 | | |
7 | | #include "resip/stack/Contents.hxx" |
8 | | #include "rutil/ParseBuffer.hxx" |
9 | | #include "rutil/Logger.hxx" |
10 | | #include "resip/stack/OctetContents.hxx" |
11 | | #include "rutil/MD5Stream.hxx" |
12 | | #include "rutil/WinLeakCheck.hxx" |
13 | | |
14 | | using namespace resip; |
15 | | using namespace std; |
16 | | |
17 | | #define RESIPROCATE_SUBSYSTEM Subsystem::CONTENTS |
18 | | |
19 | | H_ContentID resip::h_ContentID; |
20 | | H_ContentDescription resip::h_ContentDescription; |
21 | | |
22 | | Contents::Contents(const HeaderFieldValue& headerFieldValue, |
23 | | const Mime& contentType) |
24 | 64.6k | : LazyParser(headerFieldValue), |
25 | 64.6k | mType(contentType) |
26 | 64.6k | { |
27 | 64.6k | init(); |
28 | 64.6k | } |
29 | | |
30 | | Contents::Contents(const Mime& contentType) |
31 | 20 | : mType(contentType) |
32 | 20 | { |
33 | 20 | init(); |
34 | 20 | } |
35 | | |
36 | | Contents::Contents(const Contents& rhs) |
37 | 0 | : LazyParser(rhs) |
38 | 0 | { |
39 | 0 | init(rhs); |
40 | 0 | } |
41 | | |
42 | | Contents::Contents(const Contents& rhs,HeaderFieldValue::CopyPaddingEnum e) |
43 | 0 | : LazyParser(rhs,e) |
44 | 0 | { |
45 | 0 | init(rhs); |
46 | 0 | } |
47 | | |
48 | | Contents::Contents(const HeaderFieldValue& headerFieldValue, |
49 | | HeaderFieldValue::CopyPaddingEnum e, |
50 | | const Mime& contentsType) |
51 | 0 | : LazyParser(headerFieldValue,e), |
52 | 0 | mType(contentsType) |
53 | 0 | { |
54 | 0 | init(); |
55 | 0 | } |
56 | | |
57 | | |
58 | | Contents::~Contents() |
59 | 64.6k | { |
60 | 64.6k | freeMem(); |
61 | 64.6k | } |
62 | | |
63 | | static const Data errorContextData("Contents"); |
64 | | const Data& |
65 | | Contents::errorContext() const |
66 | 64.6k | { |
67 | 64.6k | return errorContextData; |
68 | 64.6k | } |
69 | | |
70 | | Contents& |
71 | | Contents::operator=(const Contents& rhs) |
72 | 0 | { |
73 | 0 | if (this != &rhs) |
74 | 0 | { |
75 | 0 | freeMem(); |
76 | 0 | LazyParser::operator=(rhs); |
77 | 0 | init(rhs); |
78 | 0 | } |
79 | |
|
80 | 0 | return *this; |
81 | 0 | } |
82 | | |
83 | | void |
84 | | Contents::init(const Contents& orig) |
85 | 0 | { |
86 | 0 | mBufferList.clear(); |
87 | 0 | mType = orig.mType; |
88 | 0 | if (orig.mDisposition) |
89 | 0 | { |
90 | 0 | mDisposition = new H_ContentDisposition::Type(*orig.mDisposition); |
91 | 0 | } |
92 | 0 | else |
93 | 0 | { |
94 | 0 | mDisposition = 0; |
95 | 0 | } |
96 | | |
97 | 0 | if (orig.mTransferEncoding) |
98 | 0 | { |
99 | 0 | mTransferEncoding = new H_ContentTransferEncoding::Type(*orig.mTransferEncoding); |
100 | 0 | } |
101 | 0 | else |
102 | 0 | { |
103 | 0 | mTransferEncoding = 0; |
104 | 0 | } |
105 | | |
106 | 0 | if (orig.mLanguages) |
107 | 0 | { |
108 | 0 | mLanguages = new H_ContentLanguages::Type(*orig.mLanguages); |
109 | 0 | } |
110 | 0 | else |
111 | 0 | { |
112 | 0 | mLanguages = 0; |
113 | 0 | } |
114 | | |
115 | 0 | if (orig.mId) |
116 | 0 | { |
117 | 0 | mId = new Token(*orig.mId); |
118 | 0 | } |
119 | 0 | else |
120 | 0 | { |
121 | 0 | mId = 0; |
122 | 0 | } |
123 | | |
124 | 0 | if (orig.mDescription) |
125 | 0 | { |
126 | 0 | mDescription = new StringCategory(*orig.mDescription); |
127 | 0 | } |
128 | 0 | else |
129 | 0 | { |
130 | 0 | mDescription = 0; |
131 | 0 | } |
132 | | |
133 | 0 | if(orig.mLength) |
134 | 0 | { |
135 | 0 | mLength = new StringCategory(*orig.mLength); |
136 | 0 | } |
137 | 0 | else |
138 | 0 | { |
139 | 0 | mLength = 0; |
140 | 0 | } |
141 | |
|
142 | 0 | mVersion = orig.mVersion; |
143 | 0 | mMinorVersion = orig.mMinorVersion; |
144 | |
|
145 | 0 | } |
146 | | |
147 | | Contents* |
148 | | Contents::createContents(const Mime& contentType, |
149 | | const Data& contents) |
150 | 0 | { |
151 | | // !ass! why are we asserting that the Data doesn't own the buffer? |
152 | | // .dlb. because this method is to be called only within a multipart |
153 | | // !ass! HFV is an overlay -- then setting c->mIsMine to true ?? dlb Q |
154 | | // .dlb. we are telling the content that it owns its HFV, not the data that it |
155 | | // .dlb. owns its memory |
156 | | // .bwc. So, we are _violating_ _encapsulation_, to make an assertion that the |
157 | | // Data is an intermediate instead of owning the buffer itself? What do we |
158 | | // care how this buffer is owned? All we require is that the buffer doesn't |
159 | | // get dealloced/modified while we're still around. The assertion might mean |
160 | | // that the Data will not do either of these things, but it affords no |
161 | | // protection from the actual owner doing so. We are no more protected with |
162 | | // the assertion, so I am removing it. |
163 | | // assert(!contents.mMine); |
164 | |
|
165 | 0 | HeaderFieldValue hfv(contents.data(), (unsigned int)contents.size()); |
166 | | |
167 | | // !bwc! This padding stuff is now the responsibility of the Contents class. |
168 | | // if(contentType.subType()=="sipfrag"||contentType.subType()=="external-body") |
169 | | // { |
170 | | // // .bwc. The parser for sipfrag requires padding at the end of the hfv. |
171 | | // HeaderFieldValue* temp = hfv; |
172 | | // hfv = new HeaderFieldValue(*temp,HeaderFieldValue::CopyPadding); |
173 | | // delete temp; |
174 | | // } |
175 | | |
176 | 0 | Contents* c; |
177 | 0 | if (ContentsFactoryBase::getFactoryMap().find(contentType) != ContentsFactoryBase::getFactoryMap().end()) |
178 | 0 | { |
179 | 0 | c = ContentsFactoryBase::getFactoryMap()[contentType]->create(hfv, contentType); |
180 | 0 | } |
181 | 0 | else |
182 | 0 | { |
183 | 0 | c = new OctetContents(hfv, contentType); |
184 | 0 | } |
185 | 0 | return c; |
186 | 0 | } |
187 | | |
188 | | bool |
189 | | Contents::exists(const HeaderBase& headerType) const |
190 | 0 | { |
191 | 0 | checkParsed(); |
192 | 0 | switch (headerType.getTypeNum()) |
193 | 0 | { |
194 | 0 | case Headers::ContentType : |
195 | 0 | { |
196 | 0 | return true; |
197 | 0 | } |
198 | 0 | case Headers::ContentDisposition : |
199 | 0 | { |
200 | 0 | return mDisposition != 0; |
201 | 0 | } |
202 | 0 | case Headers::ContentTransferEncoding : |
203 | 0 | { |
204 | 0 | return mTransferEncoding != 0; |
205 | 0 | } |
206 | 0 | case Headers::ContentLanguage : |
207 | 0 | { |
208 | 0 | return mLanguages != 0; |
209 | 0 | } |
210 | 0 | default : return false; |
211 | 0 | } |
212 | 0 | } |
213 | | |
214 | | bool |
215 | | Contents::exists(const MIME_Header& type) const |
216 | 0 | { |
217 | 0 | if (&type == &h_ContentID) |
218 | 0 | { |
219 | 0 | return mId != 0; |
220 | 0 | } |
221 | | |
222 | 0 | if (&type == &h_ContentDescription) |
223 | 0 | { |
224 | 0 | return mDescription != 0; |
225 | 0 | } |
226 | | |
227 | 0 | resip_assert(false); |
228 | 0 | return false; |
229 | 0 | } |
230 | | |
231 | | void |
232 | | Contents::remove(const HeaderBase& headerType) |
233 | 0 | { |
234 | 0 | switch (headerType.getTypeNum()) |
235 | 0 | { |
236 | 0 | case Headers::ContentDisposition : |
237 | 0 | { |
238 | 0 | delete mDisposition; |
239 | 0 | mDisposition = 0; |
240 | 0 | break; |
241 | 0 | } |
242 | 0 | case Headers::ContentLanguage : |
243 | 0 | { |
244 | 0 | delete mLanguages; |
245 | 0 | mLanguages = 0; |
246 | 0 | break; |
247 | 0 | } |
248 | 0 | case Headers::ContentTransferEncoding : |
249 | 0 | { |
250 | 0 | delete mTransferEncoding; |
251 | 0 | mTransferEncoding = 0; |
252 | 0 | break; |
253 | 0 | } |
254 | 0 | default : |
255 | 0 | ; |
256 | 0 | } |
257 | 0 | } |
258 | | |
259 | | void |
260 | | Contents::remove(const MIME_Header& type) |
261 | 0 | { |
262 | 0 | if (&type == &h_ContentID) |
263 | 0 | { |
264 | 0 | delete mId; |
265 | 0 | mId = 0; |
266 | 0 | return; |
267 | 0 | } |
268 | | |
269 | 0 | if (&type == &h_ContentDescription) |
270 | 0 | { |
271 | 0 | delete mDescription; |
272 | 0 | mDescription = 0; |
273 | 0 | return; |
274 | 0 | } |
275 | | |
276 | 0 | resip_assert(false); |
277 | 0 | } |
278 | | |
279 | | const H_ContentType::Type& |
280 | | Contents::header(const H_ContentType& headerType) const |
281 | 0 | { |
282 | 0 | return mType; |
283 | 0 | } |
284 | | |
285 | | H_ContentType::Type& |
286 | | Contents::header(const H_ContentType& headerType) |
287 | 0 | { |
288 | 0 | return mType; |
289 | 0 | } |
290 | | |
291 | | const H_ContentDisposition::Type& |
292 | | Contents::header(const H_ContentDisposition& headerType) const |
293 | 0 | { |
294 | 0 | checkParsed(); |
295 | 0 | if (mDisposition == 0) |
296 | 0 | { |
297 | 0 | ErrLog(<< "You called " |
298 | 0 | "Contents::header(const H_ContentDisposition& headerType) _const_ " |
299 | 0 | "without first calling exists(), and the header does not exist. Our" |
300 | 0 | " behavior in this scenario is to implicitly create the header(using const_cast!); " |
301 | 0 | "this is probably not what you want, but it is either this or " |
302 | 0 | "assert/throw an exception. Since this has been the behavior for " |
303 | 0 | "so long, we are not throwing here, _yet_. You need to fix your " |
304 | 0 | "code, before we _do_ start throwing. This is why const-correctness" |
305 | 0 | " should never be made a TODO item </rant>"); |
306 | 0 | Contents* ncthis = const_cast<Contents*>(this); |
307 | 0 | ncthis->mDisposition = new H_ContentDisposition::Type; |
308 | 0 | } |
309 | 0 | return *mDisposition; |
310 | 0 | } |
311 | | |
312 | | H_ContentDisposition::Type& |
313 | | Contents::header(const H_ContentDisposition& headerType) |
314 | 0 | { |
315 | 0 | checkParsed(); |
316 | 0 | if (mDisposition == 0) |
317 | 0 | { |
318 | 0 | mDisposition = new H_ContentDisposition::Type; |
319 | 0 | } |
320 | 0 | return *mDisposition; |
321 | 0 | } |
322 | | |
323 | | const H_ContentTransferEncoding::Type& |
324 | | Contents::header(const H_ContentTransferEncoding& headerType) const |
325 | 0 | { |
326 | 0 | checkParsed(); |
327 | 0 | if (mTransferEncoding == 0) |
328 | 0 | { |
329 | 0 | ErrLog(<< "You called " |
330 | 0 | "Contents::header(const H_ContentTransferEncoding& headerType) _const_ " |
331 | 0 | "without first calling exists(), and the header does not exist. Our" |
332 | 0 | " behavior in this scenario is to implicitly create the header(using const_cast!); " |
333 | 0 | "this is probably not what you want, but it is either this or " |
334 | 0 | "assert/throw an exception. Since this has been the behavior for " |
335 | 0 | "so long, we are not throwing here, _yet_. You need to fix your " |
336 | 0 | "code, before we _do_ start throwing. This is why const-correctness" |
337 | 0 | " should never be made a TODO item </rant>"); |
338 | 0 | Contents* ncthis = const_cast<Contents*>(this); |
339 | 0 | ncthis->mTransferEncoding = new H_ContentTransferEncoding::Type; |
340 | 0 | } |
341 | 0 | return *mTransferEncoding; |
342 | 0 | } |
343 | | |
344 | | H_ContentTransferEncoding::Type& |
345 | | Contents::header(const H_ContentTransferEncoding& headerType) |
346 | 0 | { |
347 | 0 | checkParsed(); |
348 | 0 | if (mTransferEncoding == 0) |
349 | 0 | { |
350 | 0 | mTransferEncoding = new H_ContentTransferEncoding::Type; |
351 | 0 | } |
352 | 0 | return *mTransferEncoding; |
353 | 0 | } |
354 | | |
355 | | const H_ContentLanguages::Type& |
356 | | Contents::header(const H_ContentLanguages& headerType) const |
357 | 0 | { |
358 | 0 | checkParsed(); |
359 | 0 | if (mLanguages == 0) |
360 | 0 | { |
361 | 0 | ErrLog(<< "You called " |
362 | 0 | "Contents::header(const H_ContentLanguages& headerType) _const_ " |
363 | 0 | "without first calling exists(), and the header does not exist. Our" |
364 | 0 | " behavior in this scenario is to implicitly create the header(using const_cast!); " |
365 | 0 | "this is probably not what you want, but it is either this or " |
366 | 0 | "assert/throw an exception. Since this has been the behavior for " |
367 | 0 | "so long, we are not throwing here, _yet_. You need to fix your " |
368 | 0 | "code, before we _do_ start throwing. This is why const-correctness" |
369 | 0 | " should never be made a TODO item </rant>"); |
370 | 0 | Contents* ncthis = const_cast<Contents*>(this); |
371 | 0 | ncthis->mLanguages = new H_ContentLanguages::Type; |
372 | 0 | } |
373 | 0 | return *mLanguages; |
374 | 0 | } |
375 | | |
376 | | H_ContentLanguages::Type& |
377 | | Contents::header(const H_ContentLanguages& headerType) |
378 | 0 | { |
379 | 0 | checkParsed(); |
380 | 0 | if (mLanguages == 0) |
381 | 0 | { |
382 | 0 | mLanguages = new H_ContentLanguages::Type; |
383 | 0 | } |
384 | 0 | return *mLanguages; |
385 | 0 | } |
386 | | |
387 | | const H_ContentDescription::Type& |
388 | | Contents::header(const H_ContentDescription& headerType) const |
389 | 0 | { |
390 | 0 | checkParsed(); |
391 | 0 | if (mDescription == 0) |
392 | 0 | { |
393 | 0 | ErrLog(<< "You called " |
394 | 0 | "Contents::header(const H_ContentDescription& headerType) _const_ " |
395 | 0 | "without first calling exists(), and the header does not exist. Our" |
396 | 0 | " behavior in this scenario is to implicitly create the header(using const_cast!); " |
397 | 0 | "this is probably not what you want, but it is either this or " |
398 | 0 | "assert/throw an exception. Since this has been the behavior for " |
399 | 0 | "so long, we are not throwing here, _yet_. You need to fix your " |
400 | 0 | "code, before we _do_ start throwing. This is why const-correctness" |
401 | 0 | " should never be made a TODO item </rant>"); |
402 | 0 | Contents* ncthis = const_cast<Contents*>(this); |
403 | 0 | ncthis->mDescription = new H_ContentDescription::Type; |
404 | 0 | } |
405 | 0 | return *mDescription; |
406 | 0 | } |
407 | | |
408 | | H_ContentDescription::Type& |
409 | | Contents::header(const H_ContentDescription& headerType) |
410 | 0 | { |
411 | 0 | checkParsed(); |
412 | 0 | if (mDescription == 0) |
413 | 0 | { |
414 | 0 | mDescription = new H_ContentDescription::Type; |
415 | 0 | } |
416 | 0 | return *mDescription; |
417 | 0 | } |
418 | | |
419 | | const H_ContentID::Type& |
420 | | Contents::header(const H_ContentID& headerType) const |
421 | 0 | { |
422 | 0 | checkParsed(); |
423 | 0 | if (mId == 0) |
424 | 0 | { |
425 | 0 | ErrLog(<< "You called " |
426 | 0 | "Contents::header(const H_ContentID& headerType) _const_ " |
427 | 0 | "without first calling exists(), and the header does not exist. Our" |
428 | 0 | " behavior in this scenario is to implicitly create the header(using const_cast!); " |
429 | 0 | "this is probably not what you want, but it is either this or " |
430 | 0 | "assert/throw an exception. Since this has been the behavior for " |
431 | 0 | "so long, we are not throwing here, _yet_. You need to fix your " |
432 | 0 | "code, before we _do_ start throwing. This is why const-correctness" |
433 | 0 | " should never be made a TODO item </rant>"); |
434 | 0 | Contents* ncthis = const_cast<Contents*>(this); |
435 | 0 | ncthis->mId = new H_ContentID::Type; |
436 | 0 | } |
437 | 0 | return *mId; |
438 | 0 | } |
439 | | |
440 | | H_ContentID::Type& |
441 | | Contents::header(const H_ContentID& headerType) |
442 | 0 | { |
443 | 0 | checkParsed(); |
444 | 0 | if (mId == 0) |
445 | 0 | { |
446 | 0 | mId = new H_ContentID::Type; |
447 | 0 | } |
448 | 0 | return *mId; |
449 | 0 | } |
450 | | |
451 | | // !dlb! headers except Content-Disposition may contain (comments) |
452 | | void |
453 | | Contents::preParseHeaders(ParseBuffer& pb) |
454 | 0 | { |
455 | 0 | const char* start = pb.position(); |
456 | 0 | Data all( start, (Data::size_type)(pb.end()-start)); |
457 | |
|
458 | 0 | Data headerName; |
459 | |
|
460 | 0 | try |
461 | 0 | { |
462 | | |
463 | 0 | while (!pb.eof()) |
464 | 0 | { |
465 | 0 | const char* anchor = pb.skipWhitespace(); |
466 | 0 | pb.skipToOneOf(Symbols::COLON, ParseBuffer::Whitespace); |
467 | 0 | pb.data(headerName, anchor); |
468 | |
|
469 | 0 | pb.skipWhitespace(); |
470 | 0 | pb.skipChar(Symbols::COLON[0]); |
471 | 0 | anchor = pb.skipWhitespace(); |
472 | 0 | pb.skipToTermCRLF(); |
473 | |
|
474 | 0 | Headers::Type type = Headers::getType(headerName.data(), headerName.size()); |
475 | 0 | ParseBuffer subPb(anchor, pb.position() - anchor); |
476 | |
|
477 | 0 | switch (type) |
478 | 0 | { |
479 | 0 | case Headers::ContentType : |
480 | 0 | { |
481 | | // already set |
482 | 0 | break; |
483 | 0 | } |
484 | 0 | case Headers::ContentDisposition : |
485 | 0 | { |
486 | 0 | mDisposition = new H_ContentDisposition::Type; |
487 | 0 | mDisposition->parse(subPb); |
488 | 0 | break; |
489 | 0 | } |
490 | 0 | case Headers::ContentTransferEncoding : |
491 | 0 | { |
492 | 0 | mTransferEncoding = new H_ContentTransferEncoding::Type; |
493 | 0 | mTransferEncoding->parse(subPb); |
494 | 0 | break; |
495 | 0 | } |
496 | | // !dlb! not sure this ever happens? |
497 | 0 | case Headers::ContentLanguage : |
498 | 0 | { |
499 | 0 | if (mLanguages == 0) |
500 | 0 | { |
501 | 0 | mLanguages = new H_ContentLanguages::Type; |
502 | 0 | } |
503 | |
|
504 | 0 | subPb.skipWhitespace(); |
505 | 0 | while (!subPb.eof() && *subPb.position() != Symbols::COMMA[0]) |
506 | 0 | { |
507 | 0 | H_ContentLanguages::Type::value_type tmp; |
508 | 0 | header(h_ContentLanguages).push_back(tmp); |
509 | 0 | header(h_ContentLanguages).back().parse(subPb); |
510 | 0 | subPb.skipLWS(); |
511 | 0 | } |
512 | 0 | break; // .kw. added -- this is needed, right? |
513 | 0 | } |
514 | 0 | default : |
515 | 0 | { |
516 | 0 | if (isEqualNoCase(headerName, "Content-Transfer-Encoding")) |
517 | 0 | { |
518 | 0 | mTransferEncoding = new StringCategory(); |
519 | 0 | mTransferEncoding->parse(subPb); |
520 | 0 | } |
521 | 0 | else if (isEqualNoCase(headerName, "Content-Description")) |
522 | 0 | { |
523 | 0 | mDescription = new StringCategory(); |
524 | 0 | mDescription->parse(subPb); |
525 | 0 | } |
526 | 0 | else if (isEqualNoCase(headerName, "Content-Id")) |
527 | 0 | { |
528 | 0 | mId = new Token(); |
529 | 0 | mId->parse(subPb); |
530 | 0 | } |
531 | | // Some people put this in ... |
532 | 0 | else if (isEqualNoCase(headerName, "Content-Length")) |
533 | 0 | { |
534 | 0 | mLength = new StringCategory(); |
535 | 0 | mLength->parse(subPb); |
536 | 0 | } |
537 | 0 | else if (isEqualNoCase(headerName, "MIME-Version")) |
538 | 0 | { |
539 | 0 | subPb.skipWhitespace(); |
540 | 0 | if (!subPb.eof() && *subPb.position() == Symbols::LPAREN[0]) |
541 | 0 | { |
542 | 0 | subPb.skipToEndQuote(Symbols::RPAREN[0]); |
543 | 0 | subPb.skipChar(Symbols::RPAREN[0]); |
544 | 0 | } |
545 | 0 | mVersion = subPb.integer(); |
546 | |
|
547 | 0 | if (!subPb.eof() && *subPb.position() == Symbols::LPAREN[0]) |
548 | 0 | { |
549 | 0 | subPb.skipToEndQuote(Symbols::RPAREN[0]); |
550 | 0 | subPb.skipChar(Symbols::RPAREN[0]); |
551 | 0 | } |
552 | 0 | subPb.skipChar(Symbols::PERIOD[0]); |
553 | | |
554 | 0 | if (!subPb.eof() && *subPb.position() == Symbols::LPAREN[0]) |
555 | 0 | { |
556 | 0 | subPb.skipToEndQuote(Symbols::RPAREN[0]); |
557 | 0 | subPb.skipChar(Symbols::RPAREN[0]); |
558 | 0 | } |
559 | | |
560 | 0 | mMinorVersion = subPb.integer(); |
561 | 0 | } |
562 | 0 | else |
563 | 0 | { |
564 | | // add to application headers someday |
565 | 0 | std::cerr << "Unknown MIME Content- header: " << headerName << std::endl; |
566 | 0 | ErrLog(<< "Unknown MIME Content- header: " << headerName); |
567 | 0 | resip_assert(false); |
568 | 0 | } |
569 | 0 | } |
570 | 0 | } |
571 | 0 | } |
572 | 0 | } |
573 | 0 | catch (ParseException & e ) |
574 | 0 | { |
575 | 0 | ErrLog( << "Some problem parsing contents: " << e ); |
576 | 0 | throw e; |
577 | 0 | } |
578 | 0 | } |
579 | | |
580 | | EncodeStream& |
581 | | Contents::encodeHeaders(EncodeStream& str) const |
582 | 0 | { |
583 | 0 | if (mVersion != 1 || mMinorVersion != 0) |
584 | 0 | { |
585 | 0 | str << "MIME-Version" << Symbols::COLON[0] << Symbols::SPACE[0] |
586 | 0 | << mVersion << Symbols::PERIOD[0] << mMinorVersion |
587 | 0 | << Symbols::CRLF; |
588 | 0 | } |
589 | |
|
590 | 0 | str << "Content-Type" << Symbols::COLON[0] << Symbols::SPACE[0] |
591 | 0 | << mType |
592 | 0 | << Symbols::CRLF; |
593 | |
|
594 | 0 | if (exists(h_ContentDisposition)) |
595 | 0 | { |
596 | 0 | str << "Content-Disposition" << Symbols::COLON[0] << Symbols::SPACE[0]; |
597 | |
|
598 | 0 | header(h_ContentDisposition).encode(str); |
599 | 0 | str << Symbols::CRLF; |
600 | 0 | } |
601 | |
|
602 | 0 | if (exists(h_ContentLanguages)) |
603 | 0 | { |
604 | 0 | str << "Content-Languages" << Symbols::COLON[0] << Symbols::SPACE[0]; |
605 | |
|
606 | 0 | size_t count = 0; |
607 | 0 | size_t size = header(h_ContentLanguages).size(); |
608 | |
|
609 | 0 | for (H_ContentLanguages::Type::const_iterator |
610 | 0 | i = header(h_ContentLanguages).begin(); |
611 | 0 | i != header(h_ContentLanguages).end(); ++i) |
612 | 0 | { |
613 | 0 | i->encode(str); |
614 | |
|
615 | 0 | if (++count < size) |
616 | 0 | str << Symbols::COMMA << Symbols::SPACE; |
617 | 0 | } |
618 | 0 | str << Symbols::CRLF; |
619 | 0 | } |
620 | |
|
621 | 0 | if (mTransferEncoding) |
622 | 0 | { |
623 | 0 | str << "Content-Transfer-Encoding" << Symbols::COLON[0] << Symbols::SPACE[0] |
624 | 0 | << *mTransferEncoding |
625 | 0 | << Symbols::CRLF; |
626 | 0 | } |
627 | |
|
628 | 0 | if (mId) |
629 | 0 | { |
630 | 0 | str << "Content-Id" << Symbols::COLON[0] << Symbols::SPACE[0] |
631 | 0 | << *mId |
632 | 0 | << Symbols::CRLF; |
633 | 0 | } |
634 | |
|
635 | 0 | if (mDescription) |
636 | 0 | { |
637 | 0 | str << "Content-Description" << Symbols::COLON[0] << Symbols::SPACE[0] |
638 | 0 | << *mDescription |
639 | 0 | << Symbols::CRLF; |
640 | 0 | } |
641 | |
|
642 | 0 | if (mLength) |
643 | 0 | { |
644 | 0 | str << "Content-Length" << Symbols::COLON[0] << Symbols::SPACE[0] |
645 | 0 | << *mLength |
646 | 0 | << Symbols::CRLF; |
647 | 0 | } |
648 | | |
649 | 0 | str << Symbols::CRLF; |
650 | 0 | return str; |
651 | 0 | } |
652 | | |
653 | | Data |
654 | | Contents::getBodyData() const |
655 | 0 | { |
656 | 0 | checkParsed(); |
657 | 0 | return Data::from(*this); |
658 | 0 | } |
659 | | |
660 | | void |
661 | | Contents::addBuffer(char* buf) |
662 | 0 | { |
663 | 0 | mBufferList.push_back(buf); |
664 | 0 | } |
665 | | |
666 | | bool |
667 | | resip::operator==(const Contents& lhs, const Contents& rhs) |
668 | 0 | { |
669 | 0 | MD5Stream lhsStream; |
670 | 0 | lhsStream << lhs; |
671 | 0 | MD5Stream rhsStream; |
672 | 0 | rhsStream << rhs; |
673 | 0 | return lhsStream.getHex() == rhsStream.getHex(); |
674 | 0 | } |
675 | | |
676 | | bool |
677 | | resip::operator!=(const Contents& lhs, const Contents& rhs) |
678 | 0 | { |
679 | 0 | return !operator==(lhs,rhs); |
680 | 0 | } |
681 | | |
682 | | /* ==================================================================== |
683 | | * The Vovida Software License, Version 1.0 |
684 | | * |
685 | | * Copyright (c) 2000-2005 |
686 | | * |
687 | | * Redistribution and use in source and binary forms, with or without |
688 | | * modification, are permitted provided that the following conditions |
689 | | * are met: |
690 | | * |
691 | | * 1. Redistributions of source code must retain the above copyright |
692 | | * notice, this list of conditions and the following disclaimer. |
693 | | * |
694 | | * 2. Redistributions in binary form must reproduce the above copyright |
695 | | * notice, this list of conditions and the following disclaimer in |
696 | | * the documentation and/or other materials provided with the |
697 | | * distribution. |
698 | | * |
699 | | * 3. The names "VOCAL", "Vovida Open Communication Application Library", |
700 | | * and "Vovida Open Communication Application Library (VOCAL)" must |
701 | | * not be used to endorse or promote products derived from this |
702 | | * software without prior written permission. For written |
703 | | * permission, please contact vocal@vovida.org. |
704 | | * |
705 | | * 4. Products derived from this software may not be called "VOCAL", nor |
706 | | * may "VOCAL" appear in their name, without prior written |
707 | | * permission of Vovida Networks, Inc. |
708 | | * |
709 | | * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED |
710 | | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
711 | | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND |
712 | | * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA |
713 | | * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES |
714 | | * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, |
715 | | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
716 | | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
717 | | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
718 | | * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
719 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE |
720 | | * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
721 | | * DAMAGE. |
722 | | * |
723 | | * ==================================================================== |
724 | | * |
725 | | * This software consists of voluntary contributions made by Vovida |
726 | | * Networks, Inc. and many individuals on behalf of Vovida Networks, |
727 | | * Inc. For more information on Vovida Networks, Inc., please see |
728 | | * <http://www.vovida.org/>. |
729 | | * |
730 | | */ |