|
reSIProcate/stack
9694
|
00001 #if defined(HAVE_CONFIG_H) 00002 #include "config.h" 00003 #endif 00004 00005 #include "resip/stack/MultipartMixedContents.hxx" 00006 #include "resip/stack/SipMessage.hxx" 00007 #include "rutil/Logger.hxx" 00008 #include "rutil/Random.hxx" 00009 #include "rutil/BaseException.hxx" 00010 #include "rutil/ParseBuffer.hxx" 00011 #include "rutil/WinLeakCheck.hxx" 00012 00013 using namespace resip; 00014 using namespace std; 00015 00016 #define RESIPROCATE_SUBSYSTEM Subsystem::CONTENTS 00017 00018 bool 00019 MultipartMixedContents::init() 00020 { 00021 static ContentsFactory<MultipartMixedContents> factory; 00022 (void)factory; 00023 return true; 00024 } 00025 00026 MultipartMixedContents::MultipartMixedContents() 00027 : Contents(getStaticType()), 00028 mContents() 00029 { 00030 setBoundary(); 00031 } 00032 00033 MultipartMixedContents::MultipartMixedContents(const Mime& contentsType) 00034 : Contents(contentsType), 00035 mContents() 00036 { 00037 if (!mType.exists(p_boundary)) 00038 { 00039 setBoundary(); 00040 } 00041 } 00042 00043 MultipartMixedContents::MultipartMixedContents(const HeaderFieldValue& hfv, const Mime& contentsType) 00044 : Contents(hfv, contentsType), 00045 mContents() 00046 { 00047 if (!mType.exists(p_boundary)) 00048 { 00049 setBoundary(); 00050 } 00051 } 00052 00053 MultipartMixedContents::MultipartMixedContents(const MultipartMixedContents& rhs) 00054 : Contents(rhs), 00055 mContents() 00056 { 00057 vector<Contents*>::const_iterator j; 00058 00059 // .bwc. Don't trigger a parse of the original by calling parts() 00060 const vector<Contents*>& list = rhs.mContents; 00061 00062 for ( j = list.begin(); 00063 j != list.end(); ++j) 00064 { 00065 assert( *j ); 00066 mContents.push_back( (*j)->clone() ); 00067 } 00068 } 00069 00070 void 00071 MultipartMixedContents::setBoundary() 00072 { 00073 Data boundaryToken = Random::getRandomHex(8); 00074 mType.param(p_boundary) = boundaryToken; 00075 } 00076 00077 void 00078 MultipartMixedContents::setBoundary(const Data& boundary) 00079 { 00080 mType.param(p_boundary) = boundary; 00081 } 00082 00083 void 00084 MultipartMixedContents::clear() 00085 { 00086 for (vector<Contents*>::iterator i = mContents.begin(); 00087 i != mContents.end(); ++i) 00088 { 00089 delete *i; 00090 } 00091 } 00092 00093 MultipartMixedContents::~MultipartMixedContents() 00094 { 00095 clear(); 00096 } 00097 00098 MultipartMixedContents& 00099 MultipartMixedContents::operator=(const MultipartMixedContents& rhs) 00100 { 00101 if (this != &rhs) 00102 { 00103 Contents::operator=(rhs); 00104 clear(); 00105 00106 for (vector<Contents*>::iterator i = mContents.begin(); 00107 i != mContents.end(); ++i) 00108 { 00109 mContents.push_back( (*i)->clone() ); 00110 } 00111 } 00112 return *this; 00113 } 00114 00115 Contents* 00116 MultipartMixedContents::clone() const 00117 { 00118 return new MultipartMixedContents(*this); 00119 } 00120 00121 const Mime& 00122 MultipartMixedContents::getStaticType() 00123 { 00124 static Mime type("multipart","mixed"); 00125 return type; 00126 } 00127 00128 EncodeStream& 00129 MultipartMixedContents::encodeParsed(EncodeStream& str) const 00130 { 00131 const Data& boundaryToken = mType.param(p_boundary); 00132 Data boundary(boundaryToken.size() + 2, Data::Preallocate); 00133 boundary = Symbols::DASHDASH; 00134 boundary += boundaryToken; 00135 boundary.replace("\"", ""); // remove quotes 00136 00137 assert( mContents.size() > 0 ); 00138 00139 bool first = true; 00140 for (vector<Contents*>::const_iterator i = mContents.begin(); 00141 i != mContents.end(); ++i) 00142 { 00143 if (!first) 00144 { 00145 str << Symbols::CRLF; 00146 } 00147 else 00148 { 00149 first = false; 00150 } 00151 str << boundary << Symbols::CRLF; 00152 (*i)->encodeHeaders(str); 00153 (*i)->encode(str); 00154 } 00155 00156 str << Symbols::CRLF << boundary << Symbols::DASHDASH; 00157 return str; 00158 } 00159 00160 // The boundary delimiter MUST occur at the beginning of a line, i.e., following 00161 // a CRLF, and the initial CRLF is considered to be attached to the boundary 00162 // delimiter line rather than part of the preceding part. 00163 void 00164 MultipartMixedContents::parse(ParseBuffer& pb) 00165 { 00166 const Data& boundaryToken = mType.param(p_boundary); 00167 00168 Data boundary(boundaryToken.size() + 4, Data::Preallocate); 00169 boundary += Symbols::CRLF; 00170 boundary += Symbols::DASHDASH; 00171 boundary += boundaryToken; 00172 00173 Data boundaryNoCRLF(boundaryToken.size() + 2, Data::Preallocate); 00174 boundaryNoCRLF += Symbols::DASHDASH; 00175 boundaryNoCRLF += boundaryToken; 00176 00177 pb.skipToChars(boundaryNoCRLF); 00178 pb.skipN((int)boundaryNoCRLF.size()); 00179 pb.assertNotEof(); 00180 00181 do 00182 { 00183 // skip over boundary 00184 00185 if( pb.eof() || *pb.position() != Symbols::CR[0] ) 00186 { 00187 throw Exception("Invalid line ending, missing CR",__FILE__,__LINE__); 00188 } 00189 pb.skipChar(); 00190 if( pb.eof() || *pb.position() != Symbols::LF[0] ) 00191 { 00192 throw Exception("Invalid line ending, missing LF",__FILE__,__LINE__); 00193 } 00194 pb.skipChar(); 00195 00196 pb.assertNotEof(); 00197 00198 const char* headerStart = pb.position(); 00199 00200 // pull out contents type only 00201 pb.skipToChars("Content-Type"); 00202 if (pb.eof()) 00203 { 00204 pb.reset(headerStart); 00205 pb.skipToChars("CONTENT-TYPE"); 00206 } 00207 pb.assertNotEof(); 00208 00209 pb.skipToChar(Symbols::COLON[0]); 00210 pb.skipChar(); 00211 pb.assertNotEof(); 00212 00213 pb.skipWhitespace(); 00214 const char* typeStart = pb.position(); 00215 pb.assertNotEof(); 00216 00217 // determine contents-type header buffer 00218 pb.skipToTermCRLF(); 00219 pb.assertNotEof(); 00220 00221 ParseBuffer subPb(typeStart, pb.position() - typeStart); 00222 Mime contentType; 00223 contentType.parse(subPb); 00224 00225 pb.assertNotEof(); 00226 00227 // determine body start 00228 pb.reset(typeStart); 00229 const char* bodyStart = pb.skipToChars(Symbols::CRLFCRLF); 00230 pb.assertNotEof(); 00231 bodyStart += 4; 00232 00233 // determine contents body buffer 00234 pb.skipToChars(boundary); 00235 pb.assertNotEof(); 00236 Data tmp; 00237 pb.data(tmp, bodyStart); 00238 // create contents against body 00239 mContents.push_back(createContents(contentType, tmp)); 00240 // pre-parse headers 00241 ParseBuffer headersPb(headerStart, bodyStart-4-headerStart); 00242 mContents.back()->preParseHeaders(headersPb); 00243 00244 pb.skipN((int)boundary.size()); 00245 00246 const char* loc = pb.position(); 00247 pb.skipChar(); 00248 pb.skipChar(); 00249 Data next; 00250 pb.data(next, loc); 00251 00252 if ( next == Symbols::DASHDASH ) 00253 { 00254 break; 00255 } 00256 pb.reset( loc ); 00257 } 00258 while ( !pb.eof() ); 00259 00260 } 00261 00262 /* ==================================================================== 00263 * The Vovida Software License, Version 1.0 00264 * 00265 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved. 00266 * 00267 * Redistribution and use in source and binary forms, with or without 00268 * modification, are permitted provided that the following conditions 00269 * are met: 00270 * 00271 * 1. Redistributions of source code must retain the above copyright 00272 * notice, this list of conditions and the following disclaimer. 00273 * 00274 * 2. Redistributions in binary form must reproduce the above copyright 00275 * notice, this list of conditions and the following disclaimer in 00276 * the documentation and/or other materials provided with the 00277 * distribution. 00278 * 00279 * 3. The names "VOCAL", "Vovida Open Communication Application Library", 00280 * and "Vovida Open Communication Application Library (VOCAL)" must 00281 * not be used to endorse or promote products derived from this 00282 * software without prior written permission. For written 00283 * permission, please contact vocal@vovida.org. 00284 * 00285 * 4. Products derived from this software may not be called "VOCAL", nor 00286 * may "VOCAL" appear in their name, without prior written 00287 * permission of Vovida Networks, Inc. 00288 * 00289 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED 00290 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 00291 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 00292 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA 00293 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES 00294 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL, 00295 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00296 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00297 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 00298 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 00299 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 00300 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 00301 * DAMAGE. 00302 * 00303 * ==================================================================== 00304 * 00305 * This software consists of voluntary contributions made by Vovida 00306 * Networks, Inc. and many individuals on behalf of Vovida Networks, 00307 * Inc. For more information on Vovida Networks, Inc., please see 00308 * <http://www.vovida.org/>. 00309 * 00310 */
1.7.5.1