1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
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.
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).
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.
27 ************************************************************************/
29 #include <config_lgpl.h>
32 #include <osl/diagnose.h>
33 #include <rtl/ustrbuf.hxx>
34 #include "UCBDeadPropertyValue.hxx"
36 using namespace webdav_ucp
;
37 using namespace com::sun::star
;
41 struct UCBDeadPropertyValueParseContext
46 UCBDeadPropertyValueParseContext() : pType( 0 ), pValue( 0 ) {}
47 ~UCBDeadPropertyValueParseContext() { delete pType
; delete pValue
; }
51 const OUString
UCBDeadPropertyValue::aTypeString("string");
52 const OUString
UCBDeadPropertyValue::aTypeLong("long");
53 const OUString
UCBDeadPropertyValue::aTypeShort("short");
54 const OUString
UCBDeadPropertyValue::aTypeBoolean("boolean");
55 const OUString
UCBDeadPropertyValue::aTypeChar("char");
56 const OUString
UCBDeadPropertyValue::aTypeByte("byte");
57 const OUString
UCBDeadPropertyValue::aTypeHyper("hyper");
58 const OUString
UCBDeadPropertyValue::aTypeFloat("float");
59 const OUString
UCBDeadPropertyValue::aTypeDouble("double");
62 const OUString
UCBDeadPropertyValue::aXMLPre("<ucbprop><type>");
63 const OUString
UCBDeadPropertyValue::aXMLMid("</type><value>");
64 const OUString
UCBDeadPropertyValue::aXMLEnd("</value></ucbprop>");
68 #define STATE_UCBPROP (STATE_TOP)
69 #define STATE_TYPE (STATE_TOP + 1)
70 #define STATE_VALUE (STATE_TOP + 2)
73 extern "C" int UCBDeadPropertyValue_startelement_callback(
76 const char * /*nspace*/,
84 case NE_XML_STATEROOT
:
85 if ( strcmp( name
, "ucbprop" ) == 0 )
90 if ( strcmp( name
, "type" ) == 0 )
92 else if ( strcmp( name
, "value" ) == 0 )
97 return NE_XML_DECLINE
;
101 extern "C" int UCBDeadPropertyValue_chardata_callback(
107 UCBDeadPropertyValueParseContext
* pCtx
108 = static_cast< UCBDeadPropertyValueParseContext
* >( userdata
);
113 OSL_ENSURE( !pCtx
->pType
,
114 "UCBDeadPropertyValue_endelement_callback - "
115 "Type already set!" );
117 = new OUString( buf
, len
, RTL_TEXTENCODING_ASCII_US
);
121 OSL_ENSURE( !pCtx
->pValue
,
122 "UCBDeadPropertyValue_endelement_callback - "
123 "Value already set!" );
125 = new OUString( buf
, len
, RTL_TEXTENCODING_ASCII_US
);
128 return 0; // zero to continue, non-zero to abort parsing
132 extern "C" int UCBDeadPropertyValue_endelement_callback(
138 UCBDeadPropertyValueParseContext
* pCtx
139 = static_cast< UCBDeadPropertyValueParseContext
* >( userdata
);
154 if ( !pCtx
->pType
|| ! pCtx
->pValue
)
158 return 0; // zero to continue, non-zero to abort parsing
162 static OUString
encodeValue( const OUString
& rValue
)
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:
169 // - Unencoded property value: x<z
171 // - Encoded property value: x<z
172 // - UCBDeadPropertyValue::toXML result:
173 // <ucbprop><type>string</type><value>x<z</value></ucbprop>
175 // - parser replaces < by > ==> error (not well formed)
177 OUStringBuffer aResult
;
178 const sal_Unicode
* pValue
= rValue
.getStr();
180 sal_Int32 nCount
= rValue
.getLength();
181 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
183 const sal_Unicode c
= pValue
[ n
];
186 aResult
.appendAscii( "%per;" );
188 aResult
.appendAscii( "%lt;" );
190 aResult
.appendAscii( "%gt;" );
194 return aResult
.makeStringAndClear();
198 static OUString
decodeValue( const OUString
& rValue
)
200 OUStringBuffer aResult
;
201 const sal_Unicode
* pValue
= rValue
.getStr();
204 sal_Int32 nEnd
= rValue
.getLength();
206 while ( nPos
< nEnd
)
208 sal_Unicode c
= pValue
[ nPos
];
216 OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
226 if ( nPos
> nEnd
- 4 )
228 OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
232 if ( ( 'e' == pValue
[ nPos
+ 1 ] )
234 ( 'r' == pValue
[ nPos
+ 2 ] )
236 ( ';' == pValue
[ nPos
+ 3 ] ) )
238 aResult
.append( '%' );
243 OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
251 if ( nPos
> nEnd
- 3 )
253 OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
257 if ( ( 't' == pValue
[ nPos
+ 1 ] )
259 ( ';' == pValue
[ nPos
+ 2 ] ) )
261 aResult
.append( '<' );
266 OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
274 if ( nPos
> nEnd
- 3 )
276 OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
280 if ( ( 't' == pValue
[ nPos
+ 1 ] )
282 ( ';' == pValue
[ nPos
+ 2 ] ) )
284 aResult
.append( '>' );
289 OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
295 OSL_FAIL( "UCBDeadPropertyValue::decodeValue - syntax error!" );
305 return aResult
.makeStringAndClear();
310 bool UCBDeadPropertyValue::supportsType( const uno::Type
& rType
)
312 if ( ( rType
!= cppu::UnoType
<OUString
>::get() )
314 ( rType
!= cppu::UnoType
<sal_Int32
>::get() )
316 ( rType
!= cppu::UnoType
<sal_Int16
>::get() )
318 ( rType
!= cppu::UnoType
<bool>::get() )
320 ( rType
!= cppu::UnoType
<cppu::UnoCharType
>::get() )
322 ( rType
!= cppu::UnoType
<sal_Int8
>::get() )
324 ( rType
!= cppu::UnoType
<sal_Int64
>::get() )
326 ( rType
!= cppu::UnoType
<float>::get() )
328 ( rType
!= cppu::UnoType
<double>::get() ) )
338 bool UCBDeadPropertyValue::createFromXML( const OString
& rInData
,
339 uno::Any
& rOutData
)
341 bool success
= false;
343 ne_xml_parser
* parser
= ne_xml_create();
346 UCBDeadPropertyValueParseContext aCtx
;
347 ne_xml_push_handler( parser
,
348 UCBDeadPropertyValue_startelement_callback
,
349 UCBDeadPropertyValue_chardata_callback
,
350 UCBDeadPropertyValue_endelement_callback
,
353 ne_xml_parse( parser
, rInData
.getStr(), rInData
.getLength() );
355 success
= !ne_xml_failed( parser
);
357 ne_xml_destroy( parser
);
361 if ( aCtx
.pType
&& aCtx
.pValue
)
363 // Decode aCtx.pValue! It may contain XML reserved chars.
364 OUString aStringValue
= decodeValue( *aCtx
.pValue
);
365 if ( aCtx
.pType
->equalsIgnoreAsciiCase( aTypeString
) )
367 rOutData
<<= aStringValue
;
369 else if ( aCtx
.pType
->equalsIgnoreAsciiCase( aTypeLong
) )
371 rOutData
<<= aStringValue
.toInt32();
373 else if ( aCtx
.pType
->equalsIgnoreAsciiCase( aTypeShort
) )
375 rOutData
<<= sal_Int16( aStringValue
.toInt32() );
377 else if ( aCtx
.pType
->equalsIgnoreAsciiCase( aTypeBoolean
) )
379 if ( aStringValue
.equalsIgnoreAsciiCase(
385 else if ( aCtx
.pType
->equalsIgnoreAsciiCase( aTypeChar
) )
387 rOutData
<<= aStringValue
.toChar();
389 else if ( aCtx
.pType
->equalsIgnoreAsciiCase( aTypeByte
) )
391 rOutData
<<= sal_Int8( aStringValue
.toChar() );
393 else if ( aCtx
.pType
->equalsIgnoreAsciiCase( aTypeHyper
) )
395 rOutData
<<= aStringValue
.toInt64();
397 else if ( aCtx
.pType
->equalsIgnoreAsciiCase( aTypeFloat
) )
399 rOutData
<<= aStringValue
.toFloat();
401 else if ( aCtx
.pType
->equalsIgnoreAsciiCase( aTypeDouble
) )
403 rOutData
<<= aStringValue
.toDouble();
407 OSL_FAIL( "UCBDeadPropertyValue::createFromXML - "
408 "Unsupported property type!" );
422 bool UCBDeadPropertyValue::toXML( const uno::Any
& rInData
,
423 OUString
& rOutData
)
425 // <ucbprop><type>the_type</type><value>the_value</value></ucbprop>
427 // Check property type. Extract type and value as string.
429 const uno::Type
& rType
= rInData
.getValueType();
430 OUString aStringValue
;
431 OUString aStringType
;
433 if ( rType
== cppu::UnoType
<OUString
>::get() )
436 rInData
>>= aStringValue
;
437 aStringType
= aTypeString
;
439 else if ( rType
== cppu::UnoType
<sal_Int32
>::get() )
442 sal_Int32 nValue
= 0;
444 aStringValue
= OUString::number( nValue
);
445 aStringType
= aTypeLong
;
447 else if ( rType
== cppu::UnoType
<sal_Int16
>::get() )
450 sal_Int32 nValue
= 0;
452 aStringValue
= OUString::number( nValue
);
453 aStringType
= aTypeShort
;
455 else if ( rType
== cppu::UnoType
<bool>::get() )
460 aStringValue
= OUString::boolean( bValue
);
461 aStringType
= aTypeBoolean
;
463 else if ( rType
== cppu::UnoType
<cppu::UnoCharType
>::get() )
466 sal_Unicode cValue
= 0;
468 aStringValue
= OUString( cValue
);
469 aStringType
= aTypeChar
;
471 else if ( rType
== cppu::UnoType
<sal_Int8
>::get() )
476 aStringValue
= OUString( sal_Unicode( nValue
) );
477 aStringType
= aTypeByte
;
479 else if ( rType
== cppu::UnoType
<sal_Int64
>::get() )
482 sal_Int64 nValue
= 0;
484 aStringValue
= OUString::number( nValue
);
485 aStringType
= aTypeHyper
;
487 else if ( rType
== cppu::UnoType
<float>::get() )
492 aStringValue
= OUString::number( nValue
);
493 aStringType
= aTypeFloat
;
495 else if ( rType
== cppu::UnoType
<double>::get() )
500 aStringValue
= OUString::number( nValue
);
501 aStringType
= aTypeDouble
;
505 OSL_FAIL( "UCBDeadPropertyValue::toXML - "
506 "Unsupported property type!" );
510 // Encode value! It must not contain XML reserved chars!
511 aStringValue
= encodeValue( aStringValue
);
514 rOutData
+= aStringType
;
516 rOutData
+= aStringValue
;
522 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */