Update ooo320-m1
[ooovba.git] / ucb / source / ucp / webdav / UCBDeadPropertyValue.cxx
blob012bd85c92a7d72c143abe04ff5cc3bc6a893466
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: UCBDeadPropertyValue.cxx,v $
10 * $Revision: 1.19 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
34 #include <string.h>
35 #include <ne_xml.h>
36 #include <osl/diagnose.h>
37 #include <rtl/ustrbuf.hxx>
38 #include "UCBDeadPropertyValue.hxx"
40 using namespace webdav_ucp;
41 using namespace com::sun::star;
43 //////////////////////////////////////////////////////////////////////////
45 struct UCBDeadPropertyValueParseContext
47 rtl::OUString * pType;
48 rtl::OUString * pValue;
50 UCBDeadPropertyValueParseContext() : pType( 0 ), pValue( 0 ) {}
51 ~UCBDeadPropertyValueParseContext() { delete pType; delete pValue; }
54 // static
55 const rtl::OUString UCBDeadPropertyValue::aTypeString
56 = rtl::OUString::createFromAscii( "string" );
57 const rtl::OUString UCBDeadPropertyValue::aTypeLong
58 = rtl::OUString::createFromAscii( "long" );
59 const rtl::OUString UCBDeadPropertyValue::aTypeShort
60 = rtl::OUString::createFromAscii( "short" );
61 const rtl::OUString UCBDeadPropertyValue::aTypeBoolean
62 = rtl::OUString::createFromAscii( "boolean" );
63 const rtl::OUString UCBDeadPropertyValue::aTypeChar
64 = rtl::OUString::createFromAscii( "char" );
65 const rtl::OUString UCBDeadPropertyValue::aTypeByte
66 = rtl::OUString::createFromAscii( "byte" );
67 const rtl::OUString UCBDeadPropertyValue::aTypeHyper
68 = rtl::OUString::createFromAscii( "hyper" );
69 const rtl::OUString UCBDeadPropertyValue::aTypeFloat
70 = rtl::OUString::createFromAscii( "float" );
71 const rtl::OUString UCBDeadPropertyValue::aTypeDouble
72 = rtl::OUString::createFromAscii( "double" );
74 // static
75 const rtl::OUString UCBDeadPropertyValue::aXMLPre
76 = rtl::OUString::createFromAscii( "<ucbprop><type>" );
77 const rtl::OUString UCBDeadPropertyValue::aXMLMid
78 = rtl::OUString::createFromAscii( "</type><value>" );
79 const rtl::OUString UCBDeadPropertyValue::aXMLEnd
80 = rtl::OUString::createFromAscii( "</value></ucbprop>" );
82 #define STATE_TOP (1)
84 #define STATE_UCBPROP (STATE_TOP)
85 #define STATE_TYPE (STATE_TOP + 1)
86 #define STATE_VALUE (STATE_TOP + 2)
88 //////////////////////////////////////////////////////////////////////////
89 extern "C" int UCBDeadPropertyValue_startelement_callback(
90 void *,
91 int parent,
92 const char *nspace,
93 const char *name,
94 const char ** )
96 if ( ( name != 0 ) &&
97 ( ( nspace == 0 ) || ( strcmp( nspace, "" ) == 0 ) ) )
99 switch ( parent )
101 case NE_XML_STATEROOT:
102 if ( strcmp( name, "ucbprop" ) == 0 )
103 return STATE_UCBPROP;
104 break;
106 case STATE_UCBPROP:
107 if ( strcmp( name, "type" ) == 0 )
108 return STATE_TYPE;
109 else if ( strcmp( name, "value" ) == 0 )
110 return STATE_VALUE;
111 break;
114 return NE_XML_DECLINE;
117 //////////////////////////////////////////////////////////////////////////
118 extern "C" int UCBDeadPropertyValue_chardata_callback(
119 void *userdata,
120 int state,
121 const char *buf,
122 size_t len )
124 UCBDeadPropertyValueParseContext * pCtx
125 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
127 switch ( state )
129 case STATE_TYPE:
130 OSL_ENSURE( !pCtx->pType,
131 "UCBDeadPropertyValue_endelement_callback - "
132 "Type already set!" );
133 pCtx->pType
134 = new rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
135 break;
137 case STATE_VALUE:
138 OSL_ENSURE( !pCtx->pValue,
139 "UCBDeadPropertyValue_endelement_callback - "
140 "Value already set!" );
141 pCtx->pValue
142 = new rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
143 break;
145 return 0; // zero to continue, non-zero to abort parsing
148 //////////////////////////////////////////////////////////////////////////
149 extern "C" int UCBDeadPropertyValue_endelement_callback(
150 void *userdata,
151 int state,
152 const char *,
153 const char * )
155 UCBDeadPropertyValueParseContext * pCtx
156 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
158 switch ( state )
160 case STATE_TYPE:
161 if ( !pCtx->pType )
162 return 1; // abort
163 break;
165 case STATE_VALUE:
166 if ( !pCtx->pValue )
167 return 1; // abort
168 break;
170 case STATE_UCBPROP:
171 if ( !pCtx->pType || ! pCtx->pValue )
172 return 1; // abort
173 break;
175 return 0; // zero to continue, non-zero to abort parsing
178 //////////////////////////////////////////////////////////////////////////
179 static rtl::OUString encodeValue( const rtl::OUString & rValue )
181 // Note: I do not use the usual &amp; + &lt; + &gt; encoding, because
182 // I want to prevent any XML parser from trying to 'understand'
183 // the value. This caused problems:
185 // Example:
186 // - Unencoded property value: x<z
187 // PROPPATCH:
188 // - Encoded property value: x&lt;z
189 // - UCBDeadPropertyValue::toXML result:
190 // <ucbprop><type>string</type><value>x&lt;z</value></ucbprop>
191 // PROPFIND:
192 // - parser replaces &lt; by > ==> error (not well formed)
194 rtl::OUStringBuffer aResult;
195 const sal_Unicode * pValue = rValue.getStr();
197 sal_Int32 nCount = rValue.getLength();
198 for ( sal_Int32 n = 0; n < nCount; ++n )
200 const sal_Unicode c = pValue[ n ];
202 if ( '%' == c )
203 aResult.appendAscii( "%per;" );
204 else if ( '<' == c )
205 aResult.appendAscii( "%lt;" );
206 else if ( '>' == c )
207 aResult.appendAscii( "%gt;" );
208 else
209 aResult.append( c );
211 return rtl::OUString( aResult );
214 //////////////////////////////////////////////////////////////////////////
215 static rtl::OUString decodeValue( const rtl::OUString & rValue )
217 rtl::OUStringBuffer aResult;
218 const sal_Unicode * pValue = rValue.getStr();
220 sal_Int32 nPos = 0;
221 sal_Int32 nEnd = rValue.getLength();
223 while ( nPos < nEnd )
225 sal_Unicode c = pValue[ nPos ];
227 if ( '%' == c )
229 nPos++;
231 if ( nPos == nEnd )
233 OSL_ENSURE( sal_False,
234 "UCBDeadPropertyValue::decodeValue - syntax error!" );
235 return rtl::OUString();
238 c = pValue[ nPos ];
240 if ( 'p' == c )
242 // %per;
244 if ( nPos > nEnd - 4 )
246 OSL_ENSURE( sal_False,
247 "UCBDeadPropertyValue::decodeValue - syntax error!" );
248 return rtl::OUString();
251 if ( ( 'e' == pValue[ nPos + 1 ] )
253 ( 'r' == pValue[ nPos + 2 ] )
255 ( ';' == pValue[ nPos + 3 ] ) )
257 aResult.append( sal_Unicode( '%' ) );
258 nPos += 3;
260 else
262 OSL_ENSURE( sal_False,
263 "UCBDeadPropertyValue::decodeValue - syntax error!" );
264 return rtl::OUString();
267 else if ( 'l' == c )
269 // %lt;
271 if ( nPos > nEnd - 3 )
273 OSL_ENSURE( sal_False,
274 "UCBDeadPropertyValue::decodeValue - syntax error!" );
275 return rtl::OUString();
278 if ( ( 't' == pValue[ nPos + 1 ] )
280 ( ';' == pValue[ nPos + 2 ] ) )
282 aResult.append( sal_Unicode( '<' ) );
283 nPos += 2;
285 else
287 OSL_ENSURE( sal_False,
288 "UCBDeadPropertyValue::decodeValue - syntax error!" );
289 return rtl::OUString();
292 else if ( 'g' == c )
294 // %gt;
296 if ( nPos > nEnd - 3 )
298 OSL_ENSURE( sal_False,
299 "UCBDeadPropertyValue::decodeValue - syntax error!" );
300 return rtl::OUString();
303 if ( ( 't' == pValue[ nPos + 1 ] )
305 ( ';' == pValue[ nPos + 2 ] ) )
307 aResult.append( sal_Unicode( '>' ) );
308 nPos += 2;
310 else
312 OSL_ENSURE( sal_False,
313 "UCBDeadPropertyValue::decodeValue - syntax error!" );
314 return rtl::OUString();
317 else
319 OSL_ENSURE( sal_False,
320 "UCBDeadPropertyValue::decodeValue - syntax error!" );
321 return rtl::OUString();
324 else
325 aResult.append( c );
327 nPos++;
330 return rtl::OUString( aResult );
333 //////////////////////////////////////////////////////////////////////////
334 // static
335 bool UCBDeadPropertyValue::supportsType( const uno::Type & rType )
337 if ( ( rType != getCppuType( static_cast< const rtl::OUString * >( 0 ) ) )
339 ( rType != getCppuType( static_cast< const sal_Int32 * >( 0 ) ) )
341 ( rType != getCppuType( static_cast< const sal_Int16 * >( 0 ) ) )
343 ( rType != getCppuBooleanType() )
345 ( rType != getCppuCharType() )
347 ( rType != getCppuType( static_cast< const sal_Int8 * >( 0 ) ) )
349 ( rType != getCppuType( static_cast< const sal_Int64 * >( 0 ) ) )
351 ( rType != getCppuType( static_cast< const float * >( 0 ) ) )
353 ( rType != getCppuType( static_cast< const double * >( 0 ) ) ) )
355 return false;
358 return true;
361 //////////////////////////////////////////////////////////////////////////
362 // static
363 bool UCBDeadPropertyValue::createFromXML( const rtl::OString & rInData,
364 uno::Any & rOutData )
366 bool success = false;
368 ne_xml_parser * parser = ne_xml_create();
369 if ( parser )
371 UCBDeadPropertyValueParseContext aCtx;
372 ne_xml_push_handler( parser,
373 UCBDeadPropertyValue_startelement_callback,
374 UCBDeadPropertyValue_chardata_callback,
375 UCBDeadPropertyValue_endelement_callback,
376 &aCtx );
378 ne_xml_parse( parser, rInData.getStr(), rInData.getLength() );
380 #if NEON_VERSION >= 0x0250
381 success = !ne_xml_failed( parser );
382 #else
383 success = !!ne_xml_valid( parser );
384 #endif
386 ne_xml_destroy( parser );
388 if ( success )
390 if ( aCtx.pType && aCtx.pValue )
392 // Decode aCtx.pValue! It may contain XML reserved chars.
393 rtl::OUString aStringValue = decodeValue( *aCtx.pValue );
394 if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeString ) )
396 rOutData <<= aStringValue;
398 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeLong ) )
400 rOutData <<= aStringValue.toInt32();
402 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeShort ) )
404 rOutData <<= sal_Int16( aStringValue.toInt32() );
406 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeBoolean ) )
408 if ( aStringValue.equalsIgnoreAsciiCase(
409 rtl::OUString::createFromAscii( "true" ) ) )
410 rOutData <<= sal_Bool( sal_True );
411 else
412 rOutData <<= sal_Bool( sal_False );
414 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeChar ) )
416 rOutData <<= aStringValue.toChar();
418 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeByte ) )
420 rOutData <<= sal_Int8( aStringValue.toChar() );
422 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeHyper ) )
424 rOutData <<= aStringValue.toInt64();
426 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeFloat ) )
428 rOutData <<= aStringValue.toFloat();
430 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeDouble ) )
432 rOutData <<= aStringValue.toDouble();
434 else
436 OSL_ENSURE( sal_False,
437 "UCBDeadPropertyValue::createFromXML - "
438 "Unsupported property type!" );
439 success = false;
442 else
443 success = false;
447 return success;
450 //////////////////////////////////////////////////////////////////////////
451 // static
452 bool UCBDeadPropertyValue::toXML( const uno::Any & rInData,
453 rtl::OUString & rOutData )
455 // <ucbprop><type>the_type</type><value>the_value</value></ucbprop>
457 // Check property type. Extract type and value as string.
459 const uno::Type& rType = rInData.getValueType();
460 rtl::OUString aStringValue;
461 rtl::OUString aStringType;
463 if ( rType == getCppuType( static_cast< const rtl::OUString * >( 0 ) ) )
465 // string
466 rInData >>= aStringValue;
467 aStringType = aTypeString;
469 else if ( rType == getCppuType( static_cast< const sal_Int32 * >( 0 ) ) )
471 // long
472 sal_Int32 nValue = 0;
473 rInData >>= nValue;
474 aStringValue = rtl::OUString::valueOf( nValue );
475 aStringType = aTypeLong;
477 else if ( rType == getCppuType( static_cast< const sal_Int16 * >( 0 ) ) )
479 // short
480 sal_Int32 nValue = 0;
481 rInData >>= nValue;
482 aStringValue = rtl::OUString::valueOf( nValue );
483 aStringType = aTypeShort;
485 else if ( rType == getCppuBooleanType() )
487 // boolean
488 sal_Bool bValue = false;
489 rInData >>= bValue;
490 aStringValue = rtl::OUString::valueOf( bValue );
491 aStringType = aTypeBoolean;
493 else if ( rType == getCppuCharType() )
495 // char
496 sal_Unicode cValue = 0;
497 rInData >>= cValue;
498 aStringValue = rtl::OUString::valueOf( cValue );
499 aStringType = aTypeChar;
501 else if ( rType == getCppuType( static_cast< const sal_Int8 * >( 0 ) ) )
503 // byte
504 sal_Int8 nValue = 0;
505 rInData >>= nValue;
506 aStringValue = rtl::OUString::valueOf( sal_Unicode( nValue ) );
507 aStringType = aTypeByte;
509 else if ( rType == getCppuType( static_cast< const sal_Int64 * >( 0 ) ) )
511 // hyper
512 sal_Int64 nValue = 0;
513 rInData >>= nValue;
514 aStringValue = rtl::OUString::valueOf( nValue );
515 aStringType = aTypeHyper;
517 else if ( rType == getCppuType( static_cast< const float * >( 0 ) ) )
519 // float
520 float nValue = 0;
521 rInData >>= nValue;
522 aStringValue = rtl::OUString::valueOf( nValue );
523 aStringType = aTypeFloat;
525 else if ( rType == getCppuType( static_cast< const double * >( 0 ) ) )
527 // double
528 double nValue = 0;
529 rInData >>= nValue;
530 aStringValue = rtl::OUString::valueOf( nValue );
531 aStringType = aTypeDouble;
533 else
535 OSL_ENSURE( sal_False,
536 "UCBDeadPropertyValue::toXML - "
537 "Unsupported property type!" );
538 return false;
541 // Encode value! It must not contain XML reserved chars!
542 aStringValue = encodeValue( aStringValue );
544 rOutData = aXMLPre;
545 rOutData += aStringType;
546 rOutData += aXMLMid;
547 rOutData += aStringValue;
548 rOutData += aXMLEnd;
550 return true;