/[resiprocate]/branches/b-identity-0505/Contents.cxx
ViewVC logotype

Contents of /branches/b-identity-0505/Contents.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4598 - (show annotations) (download)
Wed May 11 22:53:07 2005 UTC (14 years, 6 months ago) by derek
File size: 15275 byte(s)
set svn:eol-style to LF
1 #if defined(HAVE_CONFIG_H)
2 #include "resiprocate/config.hxx"
3 #endif
4
5 #include "resiprocate/Contents.hxx"
6 #include "resiprocate/os/ParseBuffer.hxx"
7 #include "resiprocate/os/Logger.hxx"
8 #include "resiprocate/GenericContents.hxx"
9 #include "resiprocate/os/WinLeakCheck.hxx"
10
11 using namespace resip;
12
13 #define RESIPROCATE_SUBSYSTEM Subsystem::CONTENTS
14
15 H_ContentID resip::h_ContentID;
16 H_ContentDescription resip::h_ContentDescription;
17
18 HashMap<Mime, ContentsFactoryBase*>* Contents::FactoryMap = 0;
19
20 Contents::Contents(HeaderFieldValue* headerFieldValue,
21 const Mime& contentType)
22 : LazyParser(headerFieldValue),
23 mType(contentType),
24 mDisposition(0),
25 mTransferEncoding(0),
26 mLanguages(0),
27 mId(0),
28 mDescription(0),
29 mLength(0),
30 mVersion(1),
31 mMinorVersion(0)
32 {}
33
34 Contents::Contents(const Mime& contentType)
35 : mType(contentType),
36 mDisposition(0),
37 mTransferEncoding(0),
38 mLanguages(0),
39 mId(0),
40 mDescription(0),
41 mLength(0),
42 mVersion(1),
43 mMinorVersion(0)
44 {}
45
46 Contents::Contents(const Contents& rhs)
47 : LazyParser(rhs),
48 mType(rhs.mType),
49 mDisposition(0),
50 mTransferEncoding(0),
51 mLanguages(0),
52 mId(0),
53 mDescription(0),
54 mLength(0),
55 mVersion(1),
56 mMinorVersion(0)
57 {
58 *this = rhs;
59 }
60
61 Contents::~Contents()
62 {
63 clear();
64 }
65
66 void
67 Contents::clear()
68 {
69 delete mDisposition;
70 delete mTransferEncoding;
71 delete mLanguages;
72 delete mId;
73 delete mDescription;
74
75 mDisposition = 0;
76 mTransferEncoding = 0;
77 mLanguages = 0;
78 mId = 0;
79 mDescription = 0;
80 mLength = 0;
81 }
82
83 const Data&
84 Contents::errorContext() const
85 {
86 static const Data context("Contents");
87 return context;
88 }
89
90 Contents&
91 Contents::operator=(const Contents& rhs)
92 {
93 if (this != &rhs)
94 {
95 LazyParser::operator=(rhs);
96 mType = rhs.mType;
97 if (rhs.mDisposition)
98 {
99 if (mDisposition) delete mDisposition;
100 mDisposition = new H_ContentDisposition::Type(*rhs.mDisposition);
101 }
102 if (rhs.mTransferEncoding)
103 {
104 if (mTransferEncoding) delete mTransferEncoding;
105 mTransferEncoding = new H_ContentTransferEncoding::Type(*rhs.mTransferEncoding);
106 }
107 if (rhs.mLanguages)
108 {
109 if (mLanguages) delete mLanguages;
110 mLanguages = new H_ContentLanguages::Type(*rhs.mLanguages);
111 }
112 if (rhs.mId)
113 {
114 if (mId) delete mId;
115 mId = new Token(*rhs.mId);
116 }
117 if (rhs.mDescription)
118 {
119 if (mDescription) delete mDescription;
120 mDescription = new StringCategory(*rhs.mDescription);
121 }
122
123 mVersion = rhs.mVersion;
124 mMinorVersion = rhs.mMinorVersion;
125 }
126
127 return *this;
128 }
129
130 HashMap<Mime, ContentsFactoryBase*>&
131 Contents::getFactoryMap()
132 {
133 if (Contents::FactoryMap == 0)
134 {
135 Contents::FactoryMap = new HashMap<Mime, ContentsFactoryBase*>();
136 }
137 return *Contents::FactoryMap;
138 }
139
140 Contents*
141 Contents::getContents(const Mime& m)
142 {
143 if (Contents::getFactoryMap().find(m) != Contents::getFactoryMap().end())
144 {
145 return Contents::getFactoryMap()[m]->convert(getContents());
146 }
147 else
148 {
149 // return a generic contents and hope for the best
150 return new GenericContents(mHeaderField, m);
151 }
152 }
153
154 Contents*
155 Contents::createContents(const Mime& contentType,
156 const Data& contents)
157 {
158 // !ass! why are we asserting that the Data doesn't own the buffer?
159 // .dlb. because this method is to be called only within a multipart
160 // !ass! HFV is an overlay -- then setting c->mIsMine to true ?? dlb Q
161 // .dlb. we are telling the content that it owns its HFV, not the data that it
162 // .dlb. owns its memory
163
164 assert(!contents.mMine);
165 HeaderFieldValue *hfv = new HeaderFieldValue(contents.data(), contents.size());
166
167 Contents* c;
168 if (Contents::getFactoryMap().find(contentType) != Contents::getFactoryMap().end())
169 {
170 c = Contents::getFactoryMap()[contentType]->create(hfv, contentType);
171 }
172 else
173 {
174 c = new GenericContents(hfv, contentType);
175 }
176 c->mIsMine = true;
177 return c;
178 }
179
180 bool
181 Contents::exists(const HeaderBase& headerType) const
182 {
183 checkParsed();
184 switch (headerType.getTypeNum())
185 {
186 case Headers::ContentType :
187 {
188 return true;
189 }
190 case Headers::ContentDisposition :
191 {
192 return mDisposition != 0;
193 }
194 case Headers::ContentTransferEncoding :
195 {
196 return mTransferEncoding != 0;
197 }
198 case Headers::ContentLanguage :
199 {
200 return mLanguages != 0;
201 }
202 default : return false;
203 }
204 }
205
206 bool
207 Contents::exists(const MIME_Header& type) const
208 {
209 if (&type == &h_ContentID)
210 {
211 return mId != 0;
212 }
213
214 if (&type == &h_ContentDescription)
215 {
216 return mDescription != 0;
217 }
218
219 assert(false);
220 return false;
221 }
222
223 void
224 Contents::remove(const HeaderBase& headerType)
225 {
226 switch (headerType.getTypeNum())
227 {
228 case Headers::ContentDisposition :
229 {
230 delete mDisposition;
231 mDisposition = 0;
232 break;
233 }
234 case Headers::ContentLanguage :
235 {
236 delete mLanguages;
237 mLanguages = 0;
238 break;
239 }
240 case Headers::ContentTransferEncoding :
241 {
242 delete mTransferEncoding;
243 mTransferEncoding = 0;
244 break;
245 }
246 default :
247 ;
248 }
249 }
250
251 void
252 Contents::remove(const MIME_Header& type)
253 {
254 if (&type == &h_ContentID)
255 {
256 delete mId;
257 mId = 0;
258 return;
259 }
260
261 if (&type == &h_ContentDescription)
262 {
263 delete mDescription;
264 mDescription = 0;
265 return;
266 }
267
268 assert(false);
269 }
270
271 H_ContentType::Type&
272 Contents::header(const H_ContentType& headerType) const
273 {
274 return mType;
275 }
276
277 H_ContentDisposition::Type&
278 Contents::header(const H_ContentDisposition& headerType) const
279 {
280 checkParsed();
281 if (mDisposition == 0)
282 {
283 mDisposition = new H_ContentDisposition::Type;
284 }
285 return *mDisposition;
286 }
287
288 H_ContentTransferEncoding::Type&
289 Contents::header(const H_ContentTransferEncoding& headerType) const
290 {
291 checkParsed();
292 if (mTransferEncoding == 0)
293 {
294 mTransferEncoding = new H_ContentTransferEncoding::Type;
295 }
296 return *mTransferEncoding;
297 }
298
299 H_ContentLanguages::Type&
300 Contents::header(const H_ContentLanguages& headerType) const
301 {
302 checkParsed();
303 if (mLanguages == 0)
304 {
305 mLanguages = new H_ContentLanguages::Type;
306 }
307 return *mLanguages;
308 }
309
310 H_ContentDescription::Type&
311 Contents::header(const H_ContentDescription& headerType) const
312 {
313 checkParsed();
314 if (mDescription == 0)
315 {
316 mDescription = new H_ContentDescription::Type;
317 }
318 return *mDescription;
319 }
320
321 H_ContentID::Type&
322 Contents::header(const H_ContentID& headerType) const
323 {
324 checkParsed();
325 if (mId == 0)
326 {
327 mId = new H_ContentID::Type;
328 }
329 return *mId;
330 }
331
332 // !dlb! headers except Content-Disposition may contain (comments)
333 void
334 Contents::preParseHeaders(ParseBuffer& pb)
335 {
336 const char* start = pb.position();
337 Data all( start, pb.end()-start);
338
339 Data headerName;
340
341 try
342 {
343
344 while (!pb.eof())
345 {
346 const char* anchor = pb.skipWhitespace();
347 pb.skipToOneOf(Symbols::COLON, ParseBuffer::Whitespace);
348 pb.data(headerName, anchor);
349
350 pb.skipWhitespace();
351 pb.skipChar(Symbols::COLON[0]);
352 anchor = pb.skipWhitespace();
353 pb.skipToTermCRLF();
354
355 Headers::Type type = Headers::getType(headerName.data(), headerName.size());
356 ParseBuffer subPb(anchor, pb.position() - anchor);
357
358 switch (type)
359 {
360 case Headers::ContentType :
361 {
362 // already set
363 break;
364 }
365 case Headers::ContentDisposition :
366 {
367 mDisposition = new H_ContentDisposition::Type;
368 mDisposition->parse(subPb);
369 break;
370 }
371 case Headers::ContentTransferEncoding :
372 {
373 mTransferEncoding = new H_ContentTransferEncoding::Type;
374 mTransferEncoding->parse(subPb);
375 break;
376 }
377 // !dlb! not sure this ever happens?
378 case Headers::ContentLanguage :
379 {
380 if (mLanguages == 0)
381 {
382 mLanguages = new H_ContentLanguages::Type;
383 }
384
385 subPb.skipWhitespace();
386 while (!subPb.eof() && *subPb.position() != Symbols::COMMA[0])
387 {
388 H_ContentLanguages::Type::value_type tmp;
389 header(h_ContentLanguages).push_back(tmp);
390 header(h_ContentLanguages).back().parse(subPb);
391 subPb.skipLWS();
392 }
393 }
394 default :
395 {
396 if (isEqualNoCase(headerName, "Content-Transfer-Encoding"))
397 {
398 mTransferEncoding = new StringCategory();
399 mTransferEncoding->parse(subPb);
400 }
401 else if (isEqualNoCase(headerName, "Content-Description"))
402 {
403 mDescription = new StringCategory();
404 mDescription->parse(subPb);
405 }
406 else if (isEqualNoCase(headerName, "Content-Id"))
407 {
408 mId = new Token();
409 mId->parse(subPb);
410 }
411 // Some people put this in ...
412 else if (isEqualNoCase(headerName, "Content-Length"))
413 {
414 mLength = new StringCategory();
415 mLength->parse(subPb);
416 }
417 else if (isEqualNoCase(headerName, "MIME-Version"))
418 {
419 subPb.skipWhitespace();
420 if (!subPb.eof() && *subPb.position() == Symbols::LPAREN[0])
421 {
422 subPb.skipToEndQuote(Symbols::RPAREN[0]);
423 subPb.skipChar(Symbols::RPAREN[0]);
424 }
425 mVersion = subPb.integer();
426
427 if (!subPb.eof() && *subPb.position() == Symbols::LPAREN[0])
428 {
429 subPb.skipToEndQuote(Symbols::RPAREN[0]);
430 subPb.skipChar(Symbols::RPAREN[0]);
431 }
432 subPb.skipChar(Symbols::PERIOD[0]);
433
434 if (!subPb.eof() && *subPb.position() == Symbols::LPAREN[0])
435 {
436 subPb.skipToEndQuote(Symbols::RPAREN[0]);
437 subPb.skipChar(Symbols::RPAREN[0]);
438 }
439
440 mMinorVersion = subPb.integer();
441 }
442 else
443 {
444 // add to application headers someday
445 std::cerr << "Unknown MIME Content- header: " << headerName << std::endl;
446 ErrLog(<< "Unknown MIME Content- header: " << headerName);
447 assert(false);
448 }
449 }
450 }
451 }
452 }
453 catch (ParseBuffer::Exception & /* e */)
454 {
455 ErrLog( << "Some problem parsing contents" );
456 #if 0 // TODO CJ REMOVE this if 0 and make this throw
457 throw;
458 #endif
459 }
460 }
461
462 std::ostream&
463 Contents::encodeHeaders(std::ostream& str) const
464 {
465 if (mVersion != 1 || mMinorVersion != 0)
466 {
467 str << "MIME-Version" << Symbols::COLON[0] << Symbols::SPACE[0]
468 << mVersion << Symbols::PERIOD[0] << mMinorVersion
469 << Symbols::CRLF;
470 }
471
472 str << "Content-Type" << Symbols::COLON[0] << Symbols::SPACE[0]
473 << mType
474 << Symbols::CRLF;
475
476 if (exists(h_ContentDisposition))
477 {
478 str << "Content-Disposition" << Symbols::COLON[0] << Symbols::SPACE[0];
479
480 header(h_ContentDisposition).encode(str);
481 str << Symbols::CRLF;
482 }
483
484 if (exists(h_ContentLanguages))
485 {
486 str << "Content-Languages" << Symbols::COLON[0] << Symbols::SPACE[0];
487
488 int count = 0;
489 int size = header(h_ContentLanguages).size();
490
491 for (H_ContentLanguages::Type::iterator
492 i = header(h_ContentLanguages).begin();
493 i != header(h_ContentLanguages).end(); ++i)
494 {
495 i->encode(str);
496
497 if (++count < size)
498 str << Symbols::COMMA << Symbols::SPACE;
499 }
500 str << Symbols::CRLF;
501 }
502
503 if (mTransferEncoding)
504 {
505 str << "Content-Transfer-Encoding" << Symbols::COLON[0] << Symbols::SPACE[0]
506 << *mTransferEncoding
507 << Symbols::CRLF;
508 }
509
510 if (mId)
511 {
512 str << "Content-Id" << Symbols::COLON[0] << Symbols::SPACE[0]
513 << *mId
514 << Symbols::CRLF;
515 }
516
517 if (mDescription)
518 {
519 str << "Content-Description" << Symbols::COLON[0] << Symbols::SPACE[0]
520 << *mDescription
521 << Symbols::CRLF;
522 }
523
524 if (mLength)
525 {
526 str << "Content-Length" << Symbols::COLON[0] << Symbols::SPACE[0]
527 << *mLength
528 << Symbols::CRLF;
529 }
530
531 str << Symbols::CRLF;
532 return str;
533 }
534
535 Data
536 Contents::getBodyData() const
537 {
538 ErrLog( << "Need to implement getBodyData function for " << getType() );
539 assert(0);
540 return Data::Empty;
541 }
542
543
544 /* ====================================================================
545 * The Vovida Software License, Version 1.0
546 *
547 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
548 *
549 * Redistribution and use in source and binary forms, with or without
550 * modification, are permitted provided that the following conditions
551 * are met:
552 *
553 * 1. Redistributions of source code must retain the above copyright
554 * notice, this list of conditions and the following disclaimer.
555 *
556 * 2. Redistributions in binary form must reproduce the above copyright
557 * notice, this list of conditions and the following disclaimer in
558 * the documentation and/or other materials provided with the
559 * distribution.
560 *
561 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
562 * and "Vovida Open Communication Application Library (VOCAL)" must
563 * not be used to endorse or promote products derived from this
564 * software without prior written permission. For written
565 * permission, please contact vocal@vovida.org.
566 *
567 * 4. Products derived from this software may not be called "VOCAL", nor
568 * may "VOCAL" appear in their name, without prior written
569 * permission of Vovida Networks, Inc.
570 *
571 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
572 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
573 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
574 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
575 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
576 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
577 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
578 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
579 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
580 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
581 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
582 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
583 * DAMAGE.
584 *
585 * ====================================================================
586 *
587 * This software consists of voluntary contributions made by Vovida
588 * Networks, Inc. and many individuals on behalf of Vovida Networks,
589 * Inc. For more information on Vovida Networks, Inc., please see
590 * <http://www.vovida.org/>.
591 *
592 */

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27