1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: UCBDeadPropertyValue.cxx,v $
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"
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
; }
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" );
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>" );
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(
97 ( ( nspace
== 0 ) || ( strcmp( nspace
, "" ) == 0 ) ) )
101 case NE_XML_STATEROOT
:
102 if ( strcmp( name
, "ucbprop" ) == 0 )
103 return STATE_UCBPROP
;
107 if ( strcmp( name
, "type" ) == 0 )
109 else if ( strcmp( name
, "value" ) == 0 )
114 return NE_XML_DECLINE
;
117 //////////////////////////////////////////////////////////////////////////
118 extern "C" int UCBDeadPropertyValue_chardata_callback(
124 UCBDeadPropertyValueParseContext
* pCtx
125 = static_cast< UCBDeadPropertyValueParseContext
* >( userdata
);
130 OSL_ENSURE( !pCtx
->pType
,
131 "UCBDeadPropertyValue_endelement_callback - "
132 "Type already set!" );
134 = new rtl::OUString( buf
, len
, RTL_TEXTENCODING_ASCII_US
);
138 OSL_ENSURE( !pCtx
->pValue
,
139 "UCBDeadPropertyValue_endelement_callback - "
140 "Value already set!" );
142 = new rtl::OUString( buf
, len
, RTL_TEXTENCODING_ASCII_US
);
145 return 0; // zero to continue, non-zero to abort parsing
148 //////////////////////////////////////////////////////////////////////////
149 extern "C" int UCBDeadPropertyValue_endelement_callback(
155 UCBDeadPropertyValueParseContext
* pCtx
156 = static_cast< UCBDeadPropertyValueParseContext
* >( userdata
);
171 if ( !pCtx
->pType
|| ! pCtx
->pValue
)
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 & + < + > encoding, because
182 // I want to prevent any XML parser from trying to 'understand'
183 // the value. This caused problems:
186 // - Unencoded property value: x<z
188 // - Encoded property value: x<z
189 // - UCBDeadPropertyValue::toXML result:
190 // <ucbprop><type>string</type><value>x<z</value></ucbprop>
192 // - parser replaces < 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
];
203 aResult
.appendAscii( "%per;" );
205 aResult
.appendAscii( "%lt;" );
207 aResult
.appendAscii( "%gt;" );
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();
221 sal_Int32 nEnd
= rValue
.getLength();
223 while ( nPos
< nEnd
)
225 sal_Unicode c
= pValue
[ nPos
];
233 OSL_ENSURE( sal_False
,
234 "UCBDeadPropertyValue::decodeValue - syntax error!" );
235 return rtl::OUString();
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( '%' ) );
262 OSL_ENSURE( sal_False
,
263 "UCBDeadPropertyValue::decodeValue - syntax error!" );
264 return rtl::OUString();
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( '<' ) );
287 OSL_ENSURE( sal_False
,
288 "UCBDeadPropertyValue::decodeValue - syntax error!" );
289 return rtl::OUString();
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( '>' ) );
312 OSL_ENSURE( sal_False
,
313 "UCBDeadPropertyValue::decodeValue - syntax error!" );
314 return rtl::OUString();
319 OSL_ENSURE( sal_False
,
320 "UCBDeadPropertyValue::decodeValue - syntax error!" );
321 return rtl::OUString();
330 return rtl::OUString( aResult
);
333 //////////////////////////////////////////////////////////////////////////
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 ) ) ) )
361 //////////////////////////////////////////////////////////////////////////
363 bool UCBDeadPropertyValue::createFromXML( const rtl::OString
& rInData
,
364 uno::Any
& rOutData
)
366 bool success
= false;
368 ne_xml_parser
* parser
= ne_xml_create();
371 UCBDeadPropertyValueParseContext aCtx
;
372 ne_xml_push_handler( parser
,
373 UCBDeadPropertyValue_startelement_callback
,
374 UCBDeadPropertyValue_chardata_callback
,
375 UCBDeadPropertyValue_endelement_callback
,
378 ne_xml_parse( parser
, rInData
.getStr(), rInData
.getLength() );
380 #if NEON_VERSION >= 0x0250
381 success
= !ne_xml_failed( parser
);
383 success
= !!ne_xml_valid( parser
);
386 ne_xml_destroy( parser
);
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
);
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();
436 OSL_ENSURE( sal_False
,
437 "UCBDeadPropertyValue::createFromXML - "
438 "Unsupported property type!" );
450 //////////////////////////////////////////////////////////////////////////
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 ) ) )
466 rInData
>>= aStringValue
;
467 aStringType
= aTypeString
;
469 else if ( rType
== getCppuType( static_cast< const sal_Int32
* >( 0 ) ) )
472 sal_Int32 nValue
= 0;
474 aStringValue
= rtl::OUString::valueOf( nValue
);
475 aStringType
= aTypeLong
;
477 else if ( rType
== getCppuType( static_cast< const sal_Int16
* >( 0 ) ) )
480 sal_Int32 nValue
= 0;
482 aStringValue
= rtl::OUString::valueOf( nValue
);
483 aStringType
= aTypeShort
;
485 else if ( rType
== getCppuBooleanType() )
488 sal_Bool bValue
= false;
490 aStringValue
= rtl::OUString::valueOf( bValue
);
491 aStringType
= aTypeBoolean
;
493 else if ( rType
== getCppuCharType() )
496 sal_Unicode cValue
= 0;
498 aStringValue
= rtl::OUString::valueOf( cValue
);
499 aStringType
= aTypeChar
;
501 else if ( rType
== getCppuType( static_cast< const sal_Int8
* >( 0 ) ) )
506 aStringValue
= rtl::OUString::valueOf( sal_Unicode( nValue
) );
507 aStringType
= aTypeByte
;
509 else if ( rType
== getCppuType( static_cast< const sal_Int64
* >( 0 ) ) )
512 sal_Int64 nValue
= 0;
514 aStringValue
= rtl::OUString::valueOf( nValue
);
515 aStringType
= aTypeHyper
;
517 else if ( rType
== getCppuType( static_cast< const float * >( 0 ) ) )
522 aStringValue
= rtl::OUString::valueOf( nValue
);
523 aStringType
= aTypeFloat
;
525 else if ( rType
== getCppuType( static_cast< const double * >( 0 ) ) )
530 aStringValue
= rtl::OUString::valueOf( nValue
);
531 aStringType
= aTypeDouble
;
535 OSL_ENSURE( sal_False
,
536 "UCBDeadPropertyValue::toXML - "
537 "Unsupported property type!" );
541 // Encode value! It must not contain XML reserved chars!
542 aStringValue
= encodeValue( aStringValue
);
545 rOutData
+= aStringType
;
547 rOutData
+= aStringValue
;