1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <osl/diagnose.h>
22 #include <rtl/ustrbuf.hxx>
23 #include "UCBDeadPropertyValue.hxx"
25 using namespace http_dav_ucp
;
26 using namespace ::com::sun::star
;
30 const OUString
UCBDeadPropertyValue::aTypeString
31 = OUString( "string" );
32 const OUString
UCBDeadPropertyValue::aTypeLong
34 const OUString
UCBDeadPropertyValue::aTypeShort
35 = OUString( "short" );
36 const OUString
UCBDeadPropertyValue::aTypeBoolean
37 = OUString( "boolean" );
38 const OUString
UCBDeadPropertyValue::aTypeChar
40 const OUString
UCBDeadPropertyValue::aTypeByte
42 const OUString
UCBDeadPropertyValue::aTypeHyper
43 = OUString( "hyper" );
44 const OUString
UCBDeadPropertyValue::aTypeFloat
45 = OUString( "float" );
46 const OUString
UCBDeadPropertyValue::aTypeDouble
47 = OUString( "double" );
50 const OUString
UCBDeadPropertyValue::aXMLPre
51 = OUString( "<ucbprop><type>" );
52 const OUString
UCBDeadPropertyValue::aXMLMid
53 = OUString( "</type><value>" );
54 const OUString
UCBDeadPropertyValue::aXMLEnd
55 = OUString( "</value></ucbprop>" );
61 #define STATE_UCBPROP (STATE_TOP)
62 #define STATE_TYPE (STATE_TOP + 1)
63 #define STATE_VALUE (STATE_TOP + 2)
65 extern "C" int UCBDeadPropertyValue_startelement_callback(
76 case NE_XML_STATEROOT:
77 if ( strcmp( name, "ucbprop" ) == 0 )
82 if ( strcmp( name, "type" ) == 0 )
84 else if ( strcmp( name, "value" ) == 0 )
89 return NE_XML_DECLINE;
93 extern "C" int UCBDeadPropertyValue_chardata_callback(
99 UCBDeadPropertyValueParseContext * pCtx
100 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
105 SAL_WARN_IF( pCtx->pType, "ucb.ucp.webdav",
106 "UCBDeadPropertyValue_endelement_callback - "
107 "Type already set!" );
109 = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
113 SAL_WARN_IF( pCtx->pValue, "ucb.ucp.webdav",
114 "UCBDeadPropertyValue_endelement_callback - "
115 "Value already set!" );
117 = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
120 return 0; // zero to continue, non-zero to abort parsing
124 extern "C" int UCBDeadPropertyValue_endelement_callback(
130 UCBDeadPropertyValueParseContext * pCtx
131 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
146 if ( !pCtx->pType || ! pCtx->pValue )
150 return 0; // zero to continue, non-zero to abort parsing
155 static OUString
encodeValue( const OUString
& rValue
)
157 // Note: I do not use the usual & + < + > encoding, because
158 // I want to prevent any XML parser from trying to 'understand'
159 // the value. This caused problems:
162 // - Unencoded property value: x<z
164 // - Encoded property value: x<z
165 // - UCBDeadPropertyValue::toXML result:
166 // <ucbprop><type>string</type><value>x<z</value></ucbprop>
168 // - parser replaces < by > ==> error (not well formed)
170 OUStringBuffer aResult
;
171 const sal_Unicode
* pValue
= rValue
.getStr();
173 sal_Int32 nCount
= rValue
.getLength();
174 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
176 const sal_Unicode c
= pValue
[ n
];
179 aResult
.appendAscii( "%per;" );
181 aResult
.appendAscii( "%lt;" );
183 aResult
.appendAscii( "%gt;" );
187 return aResult
.makeStringAndClear();
192 static OUString decodeValue( const OUString & rValue )
194 OUStringBuffer aResult;
195 const sal_Unicode * pValue = rValue.getStr();
198 sal_Int32 nEnd = rValue.getLength();
200 while ( nPos < nEnd )
202 sal_Unicode c = pValue[ nPos ];
210 SAL_WARN( "ucb.ucp.webdav",
211 "UCBDeadPropertyValue::decodeValue - syntax error!" );
221 if ( nPos > nEnd - 4 )
223 SAL_WARN( "ucb.ucp.webdav",
224 "UCBDeadPropertyValue::decodeValue - syntax error!" );
228 if ( ( 'e' == pValue[ nPos + 1 ] )
230 ( 'r' == pValue[ nPos + 2 ] )
232 ( ';' == pValue[ nPos + 3 ] ) )
234 aResult.append( '%' );
239 SAL_WARN( "ucb.ucp.webdav",
240 "UCBDeadPropertyValue::decodeValue - syntax error!" );
248 if ( nPos > nEnd - 3 )
250 SAL_WARN( "ucb.ucp.webdav",
251 "UCBDeadPropertyValue::decodeValue - syntax error!" );
255 if ( ( 't' == pValue[ nPos + 1 ] )
257 ( ';' == pValue[ nPos + 2 ] ) )
259 aResult.append( '<' );
264 SAL_WARN( "ucb.ucp.webdav",
265 "UCBDeadPropertyValue::decodeValue - syntax error!" );
273 if ( nPos > nEnd - 3 )
275 SAL_WARN( "ucb.ucp.webdav",
276 "UCBDeadPropertyValue::decodeValue - syntax error!" );
280 if ( ( 't' == pValue[ nPos + 1 ] )
282 ( ';' == pValue[ nPos + 2 ] ) )
284 aResult.append( '>' );
289 SAL_WARN( "ucb.ucp.webdav",
290 "UCBDeadPropertyValue::decodeValue - syntax error!" );
296 SAL_WARN( "ucb.ucp.webdav",
297 "UCBDeadPropertyValue::decodeValue - syntax error!" );
307 return OUString( aResult );
313 bool UCBDeadPropertyValue::supportsType( const uno::Type
& rType
)
315 if ( ( rType
!= cppu::UnoType
<OUString
>::get() )
317 ( rType
!= cppu::UnoType
<sal_Int32
>::get() )
319 ( rType
!= cppu::UnoType
<sal_Int16
>::get() )
321 ( rType
!= cppu::UnoType
<bool>::get() )
323 ( rType
!= cppu::UnoType
<cppu::UnoCharType
>::get() )
325 ( rType
!= cppu::UnoType
<sal_Int8
>::get() )
327 ( rType
!= cppu::UnoType
<sal_Int64
>::get() )
329 ( rType
!= cppu::UnoType
<float>::get() )
331 ( rType
!= cppu::UnoType
<double>::get() ) )
341 bool UCBDeadPropertyValue::createFromXML( const OString
& /*rInData*/,
342 uno::Any
& /*rOutData*/ )
344 bool success
= false;
347 ne_xml_parser * parser = ne_xml_create();
350 UCBDeadPropertyValueParseContext aCtx;
351 ne_xml_push_handler( parser,
352 UCBDeadPropertyValue_startelement_callback,
353 UCBDeadPropertyValue_chardata_callback,
354 UCBDeadPropertyValue_endelement_callback,
357 ne_xml_parse( parser, rInData.getStr(), rInData.getLength() );
359 success = !ne_xml_failed( parser );
361 ne_xml_destroy( parser );
365 if ( aCtx.pType && aCtx.pValue )
367 // Decode aCtx.pValue! It may contain XML reserved chars.
368 OUString aStringValue = decodeValue( *aCtx.pValue );
369 if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeString ) )
371 rOutData <<= aStringValue;
373 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeLong ) )
375 rOutData <<= aStringValue.toInt32();
377 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeShort ) )
379 rOutData <<= sal_Int16( aStringValue.toInt32() );
381 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeBoolean ) )
383 if ( aStringValue.equalsIgnoreAsciiCase(
384 OUString( "true" ) ) )
385 rOutData <<= sal_Bool( sal_True );
387 rOutData <<= sal_Bool( sal_False );
389 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeChar ) )
391 rOutData <<= aStringValue.toChar();
393 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeByte ) )
395 rOutData <<= sal_Int8( aStringValue.toChar() );
397 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeHyper ) )
399 rOutData <<= aStringValue.toInt64();
401 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeFloat ) )
403 rOutData <<= aStringValue.toFloat();
405 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeDouble ) )
407 rOutData <<= aStringValue.toDouble();
411 SAL_WARN( "ucb.ucp.webdav",
412 "UCBDeadPropertyValue::createFromXML - "
413 "Unsupported property type!" );
427 bool UCBDeadPropertyValue::toXML( const uno::Any
& rInData
,
428 OUString
& rOutData
)
430 // <ucbprop><type>the_type</type><value>the_value</value></ucbprop>
432 // Check property type. Extract type and value as string.
434 const uno::Type
& rType
= rInData
.getValueType();
435 OUString aStringValue
;
436 OUString aStringType
;
438 if ( rType
== cppu::UnoType
<OUString
>::get() )
441 rInData
>>= aStringValue
;
442 aStringType
= aTypeString
;
444 else if ( rType
== cppu::UnoType
<sal_Int32
>::get() )
447 sal_Int32 nValue
= 0;
449 aStringValue
= OUString::number( nValue
);
450 aStringType
= aTypeLong
;
452 else if ( rType
== cppu::UnoType
<sal_Int16
>::get() )
455 sal_Int32 nValue
= 0;
457 aStringValue
= OUString::number( nValue
);
458 aStringType
= aTypeShort
;
460 else if ( rType
== cppu::UnoType
<bool>::get() )
463 sal_Bool bValue
= false;
465 aStringValue
= OUString::boolean( bValue
);
466 aStringType
= aTypeBoolean
;
468 else if ( rType
== cppu::UnoType
<cppu::UnoCharType
>::get() )
471 sal_Unicode cValue
= 0;
473 aStringValue
= OUString( cValue
);
474 aStringType
= aTypeChar
;
476 else if ( rType
== cppu::UnoType
<sal_Int8
>::get() )
481 aStringValue
= OUString( sal_Unicode( nValue
) );
482 aStringType
= aTypeByte
;
484 else if ( rType
== cppu::UnoType
<sal_Int64
>::get() )
487 sal_Int64 nValue
= 0;
489 aStringValue
= OUString::number( nValue
);
490 aStringType
= aTypeHyper
;
492 else if ( rType
== cppu::UnoType
<float>::get() )
497 aStringValue
= OUString::number( nValue
);
498 aStringType
= aTypeFloat
;
500 else if ( rType
== cppu::UnoType
<double>::get() )
505 aStringValue
= OUString::number( nValue
);
506 aStringType
= aTypeDouble
;
510 SAL_WARN( "ucb.ucp.webdav",
511 "UCBDeadPropertyValue::toXML - "
512 "Unsupported property type!" );
516 // Encode value! It must not contain XML reserved chars!
517 aStringValue
= encodeValue( aStringValue
);
520 rOutData
+= aStringType
;
522 rOutData
+= aStringValue
;
527 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */