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