1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_dtrans.hxx"
26
27 //------------------------------------------------------------------------
28 // includes
29 //------------------------------------------------------------------------
30 #include "mcnttype.hxx"
31
32 //------------------------------------------------------------------------
33 // namespace directives
34 //------------------------------------------------------------------------
35
36 using namespace com::sun::star::uno;
37 using namespace com::sun::star::lang;
38 using namespace com::sun::star::container;
39 using namespace rtl;
40 using namespace std;
41 using namespace osl;
42
43 //------------------------------------------------------------------------
44 // constants
45 //------------------------------------------------------------------------
46
47 const OUString TSPECIALS = OUString::createFromAscii( "()<>@,;:\\\"/[]?=" );
48 const OUString TOKEN = OUString::createFromAscii( "!#$%&'*+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~." );
49 const OUString SPACE = OUString::createFromAscii( " " );
50 const OUString SEMICOLON = OUString::createFromAscii( ";" );
51
52 //------------------------------------------------------------------------
53 // ctor
54 //------------------------------------------------------------------------
55
CMimeContentType(const OUString & aCntType)56 CMimeContentType::CMimeContentType( const OUString& aCntType )
57 {
58 init( aCntType );
59 }
60
61 //------------------------------------------------------------------------
62 //
63 //------------------------------------------------------------------------
64
getMediaType()65 OUString SAL_CALL CMimeContentType::getMediaType( ) throw(RuntimeException)
66 {
67 return m_MediaType;
68 }
69
70 //------------------------------------------------------------------------
71 //
72 //------------------------------------------------------------------------
73
getMediaSubtype()74 OUString SAL_CALL CMimeContentType::getMediaSubtype( ) throw(RuntimeException)
75 {
76 return m_MediaSubtype;
77 }
78
79 //------------------------------------------------------------------------
80 //
81 //------------------------------------------------------------------------
82
getFullMediaType()83 OUString SAL_CALL CMimeContentType::getFullMediaType( ) throw(RuntimeException)
84 {
85 return m_MediaType + OUString::createFromAscii( "/" ) + m_MediaSubtype;
86 }
87
88 //------------------------------------------------------------------------
89 //
90 //------------------------------------------------------------------------
91
getParameters()92 Sequence< OUString > SAL_CALL CMimeContentType::getParameters( ) throw(RuntimeException)
93 {
94 MutexGuard aGuard( m_aMutex );
95
96 Sequence< OUString > seqParams;
97
98 map< OUString, OUString >::iterator iter;
99 map< OUString, OUString >::iterator iter_end = m_ParameterMap.end( );
100
101 for ( iter = m_ParameterMap.begin( ); iter != iter_end; ++iter )
102 {
103 seqParams.realloc( seqParams.getLength( ) + 1 );
104 seqParams[seqParams.getLength( ) - 1] = iter->first;
105 }
106
107 return seqParams;
108 }
109
110 //------------------------------------------------------------------------
111 //
112 //------------------------------------------------------------------------
113
hasParameter(const OUString & aName)114 sal_Bool SAL_CALL CMimeContentType::hasParameter( const OUString& aName ) throw(RuntimeException)
115 {
116 MutexGuard aGuard( m_aMutex );
117 return ( m_ParameterMap.end( ) != m_ParameterMap.find( aName ) );
118 }
119
120 //------------------------------------------------------------------------
121 //
122 //------------------------------------------------------------------------
123
getParameterValue(const OUString & aName)124 OUString SAL_CALL CMimeContentType::getParameterValue( const OUString& aName ) throw(NoSuchElementException, RuntimeException)
125 {
126 MutexGuard aGuard( m_aMutex );
127
128 if ( !hasParameter( aName ) )
129 throw NoSuchElementException( );
130
131 return m_ParameterMap.find( aName )->second;
132 }
133
134 //------------------------------------------------------------------------
135 //
136 //------------------------------------------------------------------------
137
init(const OUString & aCntType)138 void SAL_CALL CMimeContentType::init( const OUString& aCntType ) throw( IllegalArgumentException )
139 {
140 if ( !aCntType.getLength( ) )
141 throw IllegalArgumentException( );
142
143 m_nPos = 0;
144 m_ContentType = aCntType;
145 getSym( );
146 type();
147 }
148
149 //------------------------------------------------------------------------
150 //
151 //------------------------------------------------------------------------
152
getSym(void)153 void SAL_CALL CMimeContentType::getSym( void )
154 {
155 if ( m_nPos < m_ContentType.getLength( ) )
156 {
157 m_nxtSym = OUString( &m_ContentType[m_nPos], 1 );
158 ++m_nPos;
159 return;
160 }
161
162 m_nxtSym = OUString( );
163 }
164
165 //------------------------------------------------------------------------
166 //
167 //------------------------------------------------------------------------
168
acceptSym(const OUString & pSymTlb)169 void SAL_CALL CMimeContentType::acceptSym( const OUString& pSymTlb )
170 {
171 if ( pSymTlb.indexOf( m_nxtSym ) < 0 )
172 throw IllegalArgumentException( );
173
174 getSym();
175 }
176
177 //------------------------------------------------------------------------
178 //
179 //------------------------------------------------------------------------
180
skipSpaces(void)181 void SAL_CALL CMimeContentType::skipSpaces( void )
182 {
183 while ( SPACE == m_nxtSym )
184 getSym( );
185 }
186
187 //------------------------------------------------------------------------
188 //
189 //------------------------------------------------------------------------
190
type(void)191 void SAL_CALL CMimeContentType::type( void )
192 {
193 skipSpaces( );
194
195 // check FIRST( type )
196 if ( !isInRange( m_nxtSym, TOKEN ) )
197 throw IllegalArgumentException( );
198
199 // parse
200 while( m_nxtSym.getLength( ) )
201 {
202 if ( isInRange( m_nxtSym, TOKEN ) )
203 m_MediaType += m_nxtSym;
204 else if ( isInRange( m_nxtSym, OUString::createFromAscii( "/ " ) ) )
205 break;
206 else
207 throw IllegalArgumentException( );
208 getSym( );
209 }
210
211 // check FOLLOW( type )
212 skipSpaces( );
213 acceptSym( OUString::createFromAscii( "/" ) );
214
215 subtype( );
216 }
217
218 //------------------------------------------------------------------------
219 //
220 //------------------------------------------------------------------------
221
subtype(void)222 void SAL_CALL CMimeContentType::subtype( void )
223 {
224 skipSpaces( );
225
226 // check FIRST( subtype )
227 if ( !isInRange( m_nxtSym, TOKEN ) )
228 throw IllegalArgumentException( );
229
230 while( m_nxtSym.getLength( ) )
231 {
232 if ( isInRange( m_nxtSym, TOKEN ) )
233 m_MediaSubtype += m_nxtSym;
234 else if ( isInRange( m_nxtSym, OUString::createFromAscii( "; " ) ) )
235 break;
236 else
237 throw IllegalArgumentException( );
238 getSym( );
239 }
240
241 // parse the rest
242 skipSpaces( );
243 trailer();
244 }
245
246 //------------------------------------------------------------------------
247 //
248 //------------------------------------------------------------------------
249
trailer(void)250 void SAL_CALL CMimeContentType::trailer( void )
251 {
252 while( m_nxtSym.getLength( ) )
253 {
254 if ( m_nxtSym == OUString::createFromAscii( "(" ) )
255 {
256 getSym( );
257 comment( );
258 acceptSym( OUString::createFromAscii( ")" ) );
259 }
260 else if ( m_nxtSym == OUString::createFromAscii( ";" ) )
261 {
262 // get the parameter name
263 getSym( );
264 skipSpaces( );
265
266 if ( !isInRange( m_nxtSym, TOKEN ) )
267 throw IllegalArgumentException( );
268
269 OUString pname = pName( );
270
271 skipSpaces();
272 acceptSym( OUString::createFromAscii( "=" ) );
273
274 // get the parameter value
275 skipSpaces( );
276
277 OUString pvalue = pValue( );
278
279 // insert into map
280 if ( !m_ParameterMap.insert( pair < const OUString, OUString > ( pname, pvalue ) ).second )
281 throw IllegalArgumentException( );
282 }
283 else
284 throw IllegalArgumentException( );
285
286 skipSpaces( );
287 }
288 }
289
290 //------------------------------------------------------------------------
291 //
292 //------------------------------------------------------------------------
293
pName()294 OUString SAL_CALL CMimeContentType::pName( )
295 {
296 OUString pname;
297
298 while( m_nxtSym.getLength( ) )
299 {
300 if ( isInRange( m_nxtSym, TOKEN ) )
301 pname += m_nxtSym;
302 else if ( isInRange( m_nxtSym, OUString::createFromAscii( "= " ) ) )
303 break;
304 else
305 throw IllegalArgumentException( );
306 getSym( );
307 }
308
309 return pname;
310 }
311
312 //------------------------------------------------------------------------
313 //
314 //------------------------------------------------------------------------
315
pValue()316 OUString SAL_CALL CMimeContentType::pValue( )
317 {
318 OUString pvalue;
319
320 // quoted pvalue
321 if ( m_nxtSym == OUString::createFromAscii( "\"" ) )
322 {
323 getSym( );
324 pvalue = quotedPValue( );
325
326 if ( OUString( &pvalue[pvalue.getLength() - 1], 1 ) != OUString::createFromAscii( "\"" ) )
327 throw IllegalArgumentException( );
328
329 // remove the last quote-sign
330 const OUString qpvalue( pvalue.getStr(), pvalue.getLength( ) - 1 );
331 pvalue = qpvalue;
332
333 if ( !pvalue.getLength( ) )
334 throw IllegalArgumentException( );
335 }
336 else if ( isInRange( m_nxtSym, TOKEN ) ) // unquoted pvalue
337 {
338 pvalue = nonquotedPValue( );
339 }
340 else
341 throw IllegalArgumentException( );
342
343 return pvalue;
344 }
345
346 //------------------------------------------------------------------------
347 // the following combinations within a quoted value are not allowed:
348 // '";' (quote sign followed by semicolon) and '" ' (quote sign followed
349 // by space)
350 //------------------------------------------------------------------------
351
quotedPValue()352 OUString SAL_CALL CMimeContentType::quotedPValue( )
353 {
354 OUString pvalue;
355 sal_Bool bAfterQuoteSign = sal_False;
356
357 while ( m_nxtSym.getLength( ) )
358 {
359 if ( bAfterQuoteSign && ((m_nxtSym == SPACE)||(m_nxtSym == SEMICOLON) ) )
360 break;
361 else if ( isInRange( m_nxtSym, TOKEN + TSPECIALS + SPACE ) )
362 {
363 pvalue += m_nxtSym;
364 if ( m_nxtSym == OUString::createFromAscii( "\"" ) )
365 bAfterQuoteSign = sal_True;
366 else
367 bAfterQuoteSign = sal_False;
368 }
369 else
370 throw IllegalArgumentException( );
371 getSym( );
372 }
373
374 return pvalue;
375 }
376
377 //------------------------------------------------------------------------
378 //
379 //------------------------------------------------------------------------
380
nonquotedPValue()381 OUString SAL_CALL CMimeContentType::nonquotedPValue( )
382 {
383 OUString pvalue;
384
385 while ( m_nxtSym.getLength( ) )
386 {
387 if ( isInRange( m_nxtSym, TOKEN ) )
388 pvalue += m_nxtSym;
389 else if ( isInRange( m_nxtSym, OUString::createFromAscii( "; " ) ) )
390 break;
391 else
392 throw IllegalArgumentException( );
393 getSym( );
394 }
395
396 return pvalue;
397 }
398
399 //------------------------------------------------------------------------
400 //
401 //------------------------------------------------------------------------
402
comment(void)403 void SAL_CALL CMimeContentType::comment( void )
404 {
405 while ( m_nxtSym.getLength( ) )
406 {
407 if ( isInRange( m_nxtSym, TOKEN + SPACE ) )
408 getSym( );
409 else if ( m_nxtSym == OUString::createFromAscii( ")" ) )
410 break;
411 else
412 throw IllegalArgumentException( );
413 }
414 }
415
416 //------------------------------------------------------------------------
417 //
418 //------------------------------------------------------------------------
419
isInRange(const rtl::OUString & aChr,const rtl::OUString & aRange)420 sal_Bool SAL_CALL CMimeContentType::isInRange( const rtl::OUString& aChr, const rtl::OUString& aRange )
421 {
422 return ( aRange.indexOf( aChr ) > -1 );
423 }
424