Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <string.h>
31 : : #include <ne_xml.h>
32 : : #include <osl/diagnose.h>
33 : : #include <rtl/ustrbuf.hxx>
34 : : #include "UCBDeadPropertyValue.hxx"
35 : :
36 : : using namespace webdav_ucp;
37 : : using namespace com::sun::star;
38 : :
39 : : //////////////////////////////////////////////////////////////////////////
40 : :
41 : : struct UCBDeadPropertyValueParseContext
42 : : {
43 : : rtl::OUString * pType;
44 : : rtl::OUString * pValue;
45 : :
46 : 0 : UCBDeadPropertyValueParseContext() : pType( 0 ), pValue( 0 ) {}
47 [ # # ][ # # ]: 0 : ~UCBDeadPropertyValueParseContext() { delete pType; delete pValue; }
48 : : };
49 : :
50 : : // static
51 : 2 : const rtl::OUString UCBDeadPropertyValue::aTypeString("string");
52 : 2 : const rtl::OUString UCBDeadPropertyValue::aTypeLong("long");
53 : 2 : const rtl::OUString UCBDeadPropertyValue::aTypeShort("short");
54 : 2 : const rtl::OUString UCBDeadPropertyValue::aTypeBoolean("boolean");
55 : 2 : const rtl::OUString UCBDeadPropertyValue::aTypeChar("char");
56 : 2 : const rtl::OUString UCBDeadPropertyValue::aTypeByte("byte");
57 : 2 : const rtl::OUString UCBDeadPropertyValue::aTypeHyper("hyper");
58 : 2 : const rtl::OUString UCBDeadPropertyValue::aTypeFloat("float");
59 : 2 : const rtl::OUString UCBDeadPropertyValue::aTypeDouble("double");
60 : :
61 : : // static
62 : 2 : const rtl::OUString UCBDeadPropertyValue::aXMLPre("<ucbprop><type>");
63 : 2 : const rtl::OUString UCBDeadPropertyValue::aXMLMid("</type><value>");
64 : 2 : const rtl::OUString UCBDeadPropertyValue::aXMLEnd("</value></ucbprop>");
65 : :
66 : : #define STATE_TOP (1)
67 : :
68 : : #define STATE_UCBPROP (STATE_TOP)
69 : : #define STATE_TYPE (STATE_TOP + 1)
70 : : #define STATE_VALUE (STATE_TOP + 2)
71 : :
72 : : //////////////////////////////////////////////////////////////////////////
73 : 0 : extern "C" int UCBDeadPropertyValue_startelement_callback(
74 : : void *,
75 : : int parent,
76 : : const char * /*nspace*/,
77 : : const char *name,
78 : : const char ** )
79 : : {
80 [ # # ]: 0 : if ( name != 0 )
81 : : {
82 [ # # # ]: 0 : switch ( parent )
83 : : {
84 : : case NE_XML_STATEROOT:
85 [ # # ]: 0 : if ( strcmp( name, "ucbprop" ) == 0 )
86 : 0 : return STATE_UCBPROP;
87 : 0 : break;
88 : :
89 : : case STATE_UCBPROP:
90 [ # # ]: 0 : if ( strcmp( name, "type" ) == 0 )
91 : 0 : return STATE_TYPE;
92 [ # # ]: 0 : else if ( strcmp( name, "value" ) == 0 )
93 : 0 : return STATE_VALUE;
94 : 0 : break;
95 : : }
96 : : }
97 : 0 : return NE_XML_DECLINE;
98 : : }
99 : :
100 : : //////////////////////////////////////////////////////////////////////////
101 : 0 : extern "C" int UCBDeadPropertyValue_chardata_callback(
102 : : void *userdata,
103 : : int state,
104 : : const char *buf,
105 : : size_t len )
106 : : {
107 : : UCBDeadPropertyValueParseContext * pCtx
108 : 0 : = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
109 : :
110 [ # # # ]: 0 : switch ( state )
111 : : {
112 : : case STATE_TYPE:
113 : : OSL_ENSURE( !pCtx->pType,
114 : : "UCBDeadPropertyValue_endelement_callback - "
115 : : "Type already set!" );
116 : : pCtx->pType
117 [ # # ]: 0 : = new rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
118 : 0 : break;
119 : :
120 : : case STATE_VALUE:
121 : : OSL_ENSURE( !pCtx->pValue,
122 : : "UCBDeadPropertyValue_endelement_callback - "
123 : : "Value already set!" );
124 : : pCtx->pValue
125 [ # # ]: 0 : = new rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
126 : 0 : break;
127 : : }
128 : 0 : return 0; // zero to continue, non-zero to abort parsing
129 : : }
130 : :
131 : : //////////////////////////////////////////////////////////////////////////
132 : 0 : extern "C" int UCBDeadPropertyValue_endelement_callback(
133 : : void *userdata,
134 : : int state,
135 : : const char *,
136 : : const char * )
137 : : {
138 : : UCBDeadPropertyValueParseContext * pCtx
139 : 0 : = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
140 : :
141 [ # # # # ]: 0 : switch ( state )
142 : : {
143 : : case STATE_TYPE:
144 [ # # ]: 0 : if ( !pCtx->pType )
145 : 0 : return 1; // abort
146 : 0 : break;
147 : :
148 : : case STATE_VALUE:
149 [ # # ]: 0 : if ( !pCtx->pValue )
150 : 0 : return 1; // abort
151 : 0 : break;
152 : :
153 : : case STATE_UCBPROP:
154 [ # # ][ # # ]: 0 : if ( !pCtx->pType || ! pCtx->pValue )
155 : 0 : return 1; // abort
156 : 0 : break;
157 : : }
158 : 0 : return 0; // zero to continue, non-zero to abort parsing
159 : : }
160 : :
161 : : //////////////////////////////////////////////////////////////////////////
162 : 0 : static rtl::OUString encodeValue( const rtl::OUString & rValue )
163 : : {
164 : : // Note: I do not use the usual & + < + > encoding, because
165 : : // I want to prevent any XML parser from trying to 'understand'
166 : : // the value. This caused problems:
167 : : //
168 : : // Example:
169 : : // - Unencoded property value: x<z
170 : : // PROPPATCH:
171 : : // - Encoded property value: x<z
172 : : // - UCBDeadPropertyValue::toXML result:
173 : : // <ucbprop><type>string</type><value>x<z</value></ucbprop>
174 : : // PROPFIND:
175 : : // - parser replaces < by > ==> error (not well formed)
176 : :
177 : 0 : rtl::OUStringBuffer aResult;
178 : 0 : const sal_Unicode * pValue = rValue.getStr();
179 : :
180 : 0 : sal_Int32 nCount = rValue.getLength();
181 [ # # ]: 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
182 : : {
183 : 0 : const sal_Unicode c = pValue[ n ];
184 : :
185 [ # # ]: 0 : if ( '%' == c )
186 [ # # ]: 0 : aResult.appendAscii( "%per;" );
187 [ # # ]: 0 : else if ( '<' == c )
188 [ # # ]: 0 : aResult.appendAscii( "%lt;" );
189 [ # # ]: 0 : else if ( '>' == c )
190 [ # # ]: 0 : aResult.appendAscii( "%gt;" );
191 : : else
192 [ # # ]: 0 : aResult.append( c );
193 : : }
194 [ # # ]: 0 : return aResult.makeStringAndClear();
195 : : }
196 : :
197 : : //////////////////////////////////////////////////////////////////////////
198 : 0 : static rtl::OUString decodeValue( const rtl::OUString & rValue )
199 : : {
200 : 0 : rtl::OUStringBuffer aResult;
201 : 0 : const sal_Unicode * pValue = rValue.getStr();
202 : :
203 : 0 : sal_Int32 nPos = 0;
204 : 0 : sal_Int32 nEnd = rValue.getLength();
205 : :
206 [ # # ]: 0 : while ( nPos < nEnd )
207 : : {
208 : 0 : sal_Unicode c = pValue[ nPos ];
209 : :
210 [ # # ]: 0 : if ( '%' == c )
211 : : {
212 : 0 : nPos++;
213 : :
214 [ # # ]: 0 : if ( nPos == nEnd )
215 : : {
216 : : OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
217 : 0 : return rtl::OUString();
218 : : }
219 : :
220 : 0 : c = pValue[ nPos ];
221 : :
222 [ # # ]: 0 : if ( 'p' == c )
223 : : {
224 : : // %per;
225 : :
226 [ # # ]: 0 : if ( nPos > nEnd - 4 )
227 : : {
228 : : OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
229 : 0 : return rtl::OUString();
230 : : }
231 : :
232 [ # # ][ # # ]: 0 : if ( ( 'e' == pValue[ nPos + 1 ] )
[ # # ]
233 : : &&
234 : 0 : ( 'r' == pValue[ nPos + 2 ] )
235 : : &&
236 : 0 : ( ';' == pValue[ nPos + 3 ] ) )
237 : : {
238 [ # # ]: 0 : aResult.append( sal_Unicode( '%' ) );
239 : 0 : nPos += 3;
240 : : }
241 : : else
242 : : {
243 : : OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
244 : 0 : return rtl::OUString();
245 : : }
246 : : }
247 [ # # ]: 0 : else if ( 'l' == c )
248 : : {
249 : : // %lt;
250 : :
251 [ # # ]: 0 : if ( nPos > nEnd - 3 )
252 : : {
253 : : OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
254 : 0 : return rtl::OUString();
255 : : }
256 : :
257 [ # # ][ # # ]: 0 : if ( ( 't' == pValue[ nPos + 1 ] )
258 : : &&
259 : 0 : ( ';' == pValue[ nPos + 2 ] ) )
260 : : {
261 [ # # ]: 0 : aResult.append( sal_Unicode( '<' ) );
262 : 0 : nPos += 2;
263 : : }
264 : : else
265 : : {
266 : : OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
267 : 0 : return rtl::OUString();
268 : : }
269 : : }
270 [ # # ]: 0 : else if ( 'g' == c )
271 : : {
272 : : // %gt;
273 : :
274 [ # # ]: 0 : if ( nPos > nEnd - 3 )
275 : : {
276 : : OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
277 : 0 : return rtl::OUString();
278 : : }
279 : :
280 [ # # ][ # # ]: 0 : if ( ( 't' == pValue[ nPos + 1 ] )
281 : : &&
282 : 0 : ( ';' == pValue[ nPos + 2 ] ) )
283 : : {
284 [ # # ]: 0 : aResult.append( sal_Unicode( '>' ) );
285 : 0 : nPos += 2;
286 : : }
287 : : else
288 : : {
289 : : OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
290 : 0 : return rtl::OUString();
291 : : }
292 : : }
293 : : else
294 : : {
295 : : OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
296 : 0 : return rtl::OUString();
297 : : }
298 : : }
299 : : else
300 [ # # ]: 0 : aResult.append( c );
301 : :
302 : 0 : nPos++;
303 : : }
304 : :
305 [ # # ]: 0 : return aResult.makeStringAndClear();
306 : : }
307 : :
308 : : //////////////////////////////////////////////////////////////////////////
309 : : // static
310 : 0 : bool UCBDeadPropertyValue::supportsType( const uno::Type & rType )
311 : : {
312 [ # # # # : 0 : if ( ( rType != getCppuType( static_cast< const rtl::OUString * >( 0 ) ) )
# # # # #
# # # # #
# # # # ]
[ # # ]
313 : : &&
314 : 0 : ( rType != getCppuType( static_cast< const sal_Int32 * >( 0 ) ) )
315 : : &&
316 : 0 : ( rType != getCppuType( static_cast< const sal_Int16 * >( 0 ) ) )
317 : : &&
318 : 0 : ( rType != getCppuBooleanType() )
319 : : &&
320 : 0 : ( rType != getCppuCharType() )
321 : : &&
322 : 0 : ( rType != getCppuType( static_cast< const sal_Int8 * >( 0 ) ) )
323 : : &&
324 : 0 : ( rType != getCppuType( static_cast< const sal_Int64 * >( 0 ) ) )
325 : : &&
326 : 0 : ( rType != getCppuType( static_cast< const float * >( 0 ) ) )
327 : : &&
328 : 0 : ( rType != getCppuType( static_cast< const double * >( 0 ) ) ) )
329 : : {
330 : 0 : return false;
331 : : }
332 : :
333 : 0 : return true;
334 : : }
335 : :
336 : : //////////////////////////////////////////////////////////////////////////
337 : : // static
338 : 0 : bool UCBDeadPropertyValue::createFromXML( const rtl::OString & rInData,
339 : : uno::Any & rOutData )
340 : : {
341 : 0 : bool success = false;
342 : :
343 : 0 : ne_xml_parser * parser = ne_xml_create();
344 [ # # ]: 0 : if ( parser )
345 : : {
346 : 0 : UCBDeadPropertyValueParseContext aCtx;
347 : : ne_xml_push_handler( parser,
348 : : UCBDeadPropertyValue_startelement_callback,
349 : : UCBDeadPropertyValue_chardata_callback,
350 : : UCBDeadPropertyValue_endelement_callback,
351 [ # # ]: 0 : &aCtx );
352 : :
353 [ # # ]: 0 : ne_xml_parse( parser, rInData.getStr(), rInData.getLength() );
354 : :
355 [ # # ]: 0 : success = !ne_xml_failed( parser );
356 : :
357 [ # # ]: 0 : ne_xml_destroy( parser );
358 : :
359 [ # # ]: 0 : if ( success )
360 : : {
361 [ # # ][ # # ]: 0 : if ( aCtx.pType && aCtx.pValue )
362 : : {
363 : : // Decode aCtx.pValue! It may contain XML reserved chars.
364 [ # # ]: 0 : rtl::OUString aStringValue = decodeValue( *aCtx.pValue );
365 [ # # ]: 0 : if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeString ) )
366 : : {
367 [ # # ]: 0 : rOutData <<= aStringValue;
368 : : }
369 [ # # ]: 0 : else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeLong ) )
370 : : {
371 [ # # ]: 0 : rOutData <<= aStringValue.toInt32();
372 : : }
373 [ # # ]: 0 : else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeShort ) )
374 : : {
375 [ # # ]: 0 : rOutData <<= sal_Int16( aStringValue.toInt32() );
376 : : }
377 [ # # ]: 0 : else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeBoolean ) )
378 : : {
379 [ # # ]: 0 : if ( aStringValue.equalsIgnoreAsciiCase(
380 : 0 : rtl::OUString("true") ) )
381 [ # # ]: 0 : rOutData <<= sal_Bool( sal_True );
382 : : else
383 [ # # ]: 0 : rOutData <<= sal_Bool( sal_False );
384 : : }
385 [ # # ]: 0 : else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeChar ) )
386 : : {
387 [ # # ]: 0 : rOutData <<= aStringValue.toChar();
388 : : }
389 [ # # ]: 0 : else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeByte ) )
390 : : {
391 [ # # ]: 0 : rOutData <<= sal_Int8( aStringValue.toChar() );
392 : : }
393 [ # # ]: 0 : else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeHyper ) )
394 : : {
395 [ # # ]: 0 : rOutData <<= aStringValue.toInt64();
396 : : }
397 [ # # ]: 0 : else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeFloat ) )
398 : : {
399 [ # # ]: 0 : rOutData <<= aStringValue.toFloat();
400 : : }
401 [ # # ]: 0 : else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeDouble ) )
402 : : {
403 [ # # ]: 0 : rOutData <<= aStringValue.toDouble();
404 : : }
405 : : else
406 : : {
407 : : OSL_FAIL( "UCBDeadPropertyValue::createFromXML - "
408 : : "Unsupported property type!" );
409 : 0 : success = false;
410 : 0 : }
411 : : }
412 : : else
413 : 0 : success = false;
414 : 0 : }
415 : : }
416 : :
417 : 0 : return success;
418 : : }
419 : :
420 : : //////////////////////////////////////////////////////////////////////////
421 : : // static
422 : 0 : bool UCBDeadPropertyValue::toXML( const uno::Any & rInData,
423 : : rtl::OUString & rOutData )
424 : : {
425 : : // <ucbprop><type>the_type</type><value>the_value</value></ucbprop>
426 : :
427 : : // Check property type. Extract type and value as string.
428 : :
429 : 0 : const uno::Type& rType = rInData.getValueType();
430 : 0 : rtl::OUString aStringValue;
431 : 0 : rtl::OUString aStringType;
432 : :
433 [ # # ][ # # ]: 0 : if ( rType == getCppuType( static_cast< const rtl::OUString * >( 0 ) ) )
434 : : {
435 : : // string
436 : 0 : rInData >>= aStringValue;
437 : 0 : aStringType = aTypeString;
438 : : }
439 [ # # ][ # # ]: 0 : else if ( rType == getCppuType( static_cast< const sal_Int32 * >( 0 ) ) )
440 : : {
441 : : // long
442 : 0 : sal_Int32 nValue = 0;
443 : 0 : rInData >>= nValue;
444 : 0 : aStringValue = rtl::OUString::valueOf( nValue );
445 : 0 : aStringType = aTypeLong;
446 : : }
447 [ # # ][ # # ]: 0 : else if ( rType == getCppuType( static_cast< const sal_Int16 * >( 0 ) ) )
448 : : {
449 : : // short
450 : 0 : sal_Int32 nValue = 0;
451 : 0 : rInData >>= nValue;
452 : 0 : aStringValue = rtl::OUString::valueOf( nValue );
453 : 0 : aStringType = aTypeShort;
454 : : }
455 [ # # ][ # # ]: 0 : else if ( rType == getCppuBooleanType() )
456 : : {
457 : : // boolean
458 : 0 : sal_Bool bValue = false;
459 : 0 : rInData >>= bValue;
460 : 0 : aStringValue = rtl::OUString::valueOf( bValue );
461 : 0 : aStringType = aTypeBoolean;
462 : : }
463 [ # # ][ # # ]: 0 : else if ( rType == getCppuCharType() )
464 : : {
465 : : // char
466 : 0 : sal_Unicode cValue = 0;
467 : 0 : rInData >>= cValue;
468 : 0 : aStringValue = rtl::OUString::valueOf( cValue );
469 : 0 : aStringType = aTypeChar;
470 : : }
471 [ # # ][ # # ]: 0 : else if ( rType == getCppuType( static_cast< const sal_Int8 * >( 0 ) ) )
472 : : {
473 : : // byte
474 : 0 : sal_Int8 nValue = 0;
475 : 0 : rInData >>= nValue;
476 : 0 : aStringValue = rtl::OUString::valueOf( sal_Unicode( nValue ) );
477 : 0 : aStringType = aTypeByte;
478 : : }
479 [ # # ][ # # ]: 0 : else if ( rType == getCppuType( static_cast< const sal_Int64 * >( 0 ) ) )
480 : : {
481 : : // hyper
482 : 0 : sal_Int64 nValue = 0;
483 : 0 : rInData >>= nValue;
484 : 0 : aStringValue = rtl::OUString::valueOf( nValue );
485 : 0 : aStringType = aTypeHyper;
486 : : }
487 [ # # ][ # # ]: 0 : else if ( rType == getCppuType( static_cast< const float * >( 0 ) ) )
488 : : {
489 : : // float
490 : 0 : float nValue = 0;
491 : 0 : rInData >>= nValue;
492 : 0 : aStringValue = rtl::OUString::valueOf( nValue );
493 : 0 : aStringType = aTypeFloat;
494 : : }
495 [ # # ][ # # ]: 0 : else if ( rType == getCppuType( static_cast< const double * >( 0 ) ) )
496 : : {
497 : : // double
498 : 0 : double nValue = 0;
499 : 0 : rInData >>= nValue;
500 : 0 : aStringValue = rtl::OUString::valueOf( nValue );
501 : 0 : aStringType = aTypeDouble;
502 : : }
503 : : else
504 : : {
505 : : OSL_FAIL( "UCBDeadPropertyValue::toXML - "
506 : : "Unsupported property type!" );
507 : 0 : return false;
508 : : }
509 : :
510 : : // Encode value! It must not contain XML reserved chars!
511 [ # # ]: 0 : aStringValue = encodeValue( aStringValue );
512 : :
513 : 0 : rOutData = aXMLPre;
514 : 0 : rOutData += aStringType;
515 : 0 : rOutData += aXMLMid;
516 : 0 : rOutData += aStringValue;
517 : 0 : rOutData += aXMLEnd;
518 : :
519 : 0 : return true;
520 [ + - ][ + - ]: 6 : }
521 : :
522 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|