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