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 .
20 #include <rtl/ustrbuf.hxx>
21 #include <sal/log.hxx>
22 #include "UCBDeadPropertyValue.hxx"
24 using namespace http_dav_ucp
;
25 using namespace ::com::sun::star
;
29 const OUString
UCBDeadPropertyValue::aTypeString
31 const OUString
UCBDeadPropertyValue::aTypeLong
33 const OUString
UCBDeadPropertyValue::aTypeShort
35 const OUString
UCBDeadPropertyValue::aTypeBoolean
37 const OUString
UCBDeadPropertyValue::aTypeChar
39 const OUString
UCBDeadPropertyValue::aTypeByte
41 const OUString
UCBDeadPropertyValue::aTypeHyper
43 const OUString
UCBDeadPropertyValue::aTypeFloat
45 const OUString
UCBDeadPropertyValue::aTypeDouble
49 const OUString
UCBDeadPropertyValue::aXMLPre
51 const OUString
UCBDeadPropertyValue::aXMLMid
53 const OUString
UCBDeadPropertyValue::aXMLEnd
54 = "</value></ucbprop>";
60 #define STATE_UCBPROP (STATE_TOP)
61 #define STATE_TYPE (STATE_TOP + 1)
62 #define STATE_VALUE (STATE_TOP + 2)
64 extern "C" int UCBDeadPropertyValue_startelement_callback(
75 case NE_XML_STATEROOT:
76 if ( strcmp( name, "ucbprop" ) == 0 )
81 if ( strcmp( name, "type" ) == 0 )
83 else if ( strcmp( name, "value" ) == 0 )
88 return NE_XML_DECLINE;
92 extern "C" int UCBDeadPropertyValue_chardata_callback(
98 UCBDeadPropertyValueParseContext * pCtx
99 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
104 SAL_WARN_IF( pCtx->pType, "ucb.ucp.webdav",
105 "UCBDeadPropertyValue_endelement_callback - "
106 "Type already set!" );
108 = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
112 SAL_WARN_IF( pCtx->pValue, "ucb.ucp.webdav",
113 "UCBDeadPropertyValue_endelement_callback - "
114 "Value already set!" );
116 = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
119 return 0; // zero to continue, non-zero to abort parsing
123 extern "C" int UCBDeadPropertyValue_endelement_callback(
129 UCBDeadPropertyValueParseContext * pCtx
130 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
145 if ( !pCtx->pType || ! pCtx->pValue )
149 return 0; // zero to continue, non-zero to abort parsing
154 static OUString
encodeValue( const OUString
& rValue
)
156 // Note: I do not use the usual & + < + > encoding, because
157 // I want to prevent any XML parser from trying to 'understand'
158 // the value. This caused problems:
161 // - Unencoded property value: x<z
163 // - Encoded property value: x<z
164 // - UCBDeadPropertyValue::toXML result:
165 // <ucbprop><type>string</type><value>x<z</value></ucbprop>
167 // - parser replaces < by > ==> error (not well formed)
169 OUStringBuffer aResult
;
170 const sal_Unicode
* pValue
= rValue
.getStr();
172 sal_Int32 nCount
= rValue
.getLength();
173 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
175 const sal_Unicode c
= pValue
[ n
];
178 aResult
.append( "%per;" );
180 aResult
.append( "%lt;" );
182 aResult
.append( "%gt;" );
186 return aResult
.makeStringAndClear();
191 static OUString decodeValue( const OUString & rValue )
193 OUStringBuffer aResult;
194 const sal_Unicode * pValue = rValue.getStr();
197 sal_Int32 nEnd = rValue.getLength();
199 while ( nPos < nEnd )
201 sal_Unicode c = pValue[ nPos ];
209 SAL_WARN( "ucb.ucp.webdav",
210 "UCBDeadPropertyValue::decodeValue - syntax error!" );
220 if ( nPos > nEnd - 4 )
222 SAL_WARN( "ucb.ucp.webdav",
223 "UCBDeadPropertyValue::decodeValue - syntax error!" );
227 if ( ( 'e' == pValue[ nPos + 1 ] )
229 ( 'r' == pValue[ nPos + 2 ] )
231 ( ';' == pValue[ nPos + 3 ] ) )
233 aResult.append( '%' );
238 SAL_WARN( "ucb.ucp.webdav",
239 "UCBDeadPropertyValue::decodeValue - syntax error!" );
247 if ( nPos > nEnd - 3 )
249 SAL_WARN( "ucb.ucp.webdav",
250 "UCBDeadPropertyValue::decodeValue - syntax error!" );
254 if ( ( 't' == pValue[ nPos + 1 ] )
256 ( ';' == pValue[ nPos + 2 ] ) )
258 aResult.append( '<' );
263 SAL_WARN( "ucb.ucp.webdav",
264 "UCBDeadPropertyValue::decodeValue - syntax error!" );
272 if ( nPos > nEnd - 3 )
274 SAL_WARN( "ucb.ucp.webdav",
275 "UCBDeadPropertyValue::decodeValue - syntax error!" );
279 if ( ( 't' == pValue[ nPos + 1 ] )
281 ( ';' == pValue[ nPos + 2 ] ) )
283 aResult.append( '>' );
288 SAL_WARN( "ucb.ucp.webdav",
289 "UCBDeadPropertyValue::decodeValue - syntax error!" );
295 SAL_WARN( "ucb.ucp.webdav",
296 "UCBDeadPropertyValue::decodeValue - syntax error!" );
306 return OUString( aResult );
312 bool UCBDeadPropertyValue::supportsType( const uno::Type
& rType
)
314 if ( ( rType
!= cppu::UnoType
<OUString
>::get() )
316 ( rType
!= cppu::UnoType
<sal_Int32
>::get() )
318 ( rType
!= cppu::UnoType
<sal_Int16
>::get() )
320 ( rType
!= cppu::UnoType
<bool>::get() )
322 ( rType
!= cppu::UnoType
<cppu::UnoCharType
>::get() )
324 ( rType
!= cppu::UnoType
<sal_Int8
>::get() )
326 ( rType
!= cppu::UnoType
<sal_Int64
>::get() )
328 ( rType
!= cppu::UnoType
<float>::get() )
330 ( rType
!= cppu::UnoType
<double>::get() ) )
340 bool UCBDeadPropertyValue::createFromXML( const OString
& /*rInData*/,
341 uno::Any
& /*rOutData*/ )
343 bool success
= false;
346 ne_xml_parser * parser = ne_xml_create();
349 UCBDeadPropertyValueParseContext aCtx;
350 ne_xml_push_handler( parser,
351 UCBDeadPropertyValue_startelement_callback,
352 UCBDeadPropertyValue_chardata_callback,
353 UCBDeadPropertyValue_endelement_callback,
356 ne_xml_parse( parser, rInData.getStr(), rInData.getLength() );
358 success = !ne_xml_failed( parser );
360 ne_xml_destroy( parser );
364 if ( aCtx.pType && aCtx.pValue )
366 // Decode aCtx.pValue! It may contain XML reserved chars.
367 OUString aStringValue = decodeValue( *aCtx.pValue );
368 if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeString ) )
370 rOutData <<= aStringValue;
372 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeLong ) )
374 rOutData <<= aStringValue.toInt32();
376 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeShort ) )
378 rOutData <<= sal_Int16( aStringValue.toInt32() );
380 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeBoolean ) )
382 if ( aStringValue.equalsIgnoreAsciiCase(
383 OUString( "true" ) ) )
384 rOutData <<= sal_Bool( sal_True );
386 rOutData <<= sal_Bool( sal_False );
388 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeChar ) )
390 rOutData <<= aStringValue.toChar();
392 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeByte ) )
394 rOutData <<= sal_Int8( aStringValue.toChar() );
396 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeHyper ) )
398 rOutData <<= aStringValue.toInt64();
400 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeFloat ) )
402 rOutData <<= aStringValue.toFloat();
404 else if ( aCtx.pType->equalsIgnoreAsciiCase( aTypeDouble ) )
406 rOutData <<= aStringValue.toDouble();
410 SAL_WARN( "ucb.ucp.webdav",
411 "UCBDeadPropertyValue::createFromXML - "
412 "Unsupported property type!" );
426 bool UCBDeadPropertyValue::toXML( const uno::Any
& rInData
,
427 OUString
& rOutData
)
429 // <ucbprop><type>the_type</type><value>the_value</value></ucbprop>
431 // Check property type. Extract type and value as string.
433 const uno::Type
& rType
= rInData
.getValueType();
434 OUString aStringValue
;
435 OUString aStringType
;
437 if ( rType
== cppu::UnoType
<OUString
>::get() )
440 rInData
>>= aStringValue
;
441 aStringType
= aTypeString
;
443 else if ( rType
== cppu::UnoType
<sal_Int32
>::get() )
446 sal_Int32 nValue
= 0;
448 aStringValue
= OUString::number( nValue
);
449 aStringType
= aTypeLong
;
451 else if ( rType
== cppu::UnoType
<sal_Int16
>::get() )
454 sal_Int32 nValue
= 0;
456 aStringValue
= OUString::number( nValue
);
457 aStringType
= aTypeShort
;
459 else if ( rType
== cppu::UnoType
<bool>::get() )
464 aStringValue
= OUString::boolean( bValue
);
465 aStringType
= aTypeBoolean
;
467 else if ( rType
== cppu::UnoType
<cppu::UnoCharType
>::get() )
470 sal_Unicode cValue
= 0;
472 aStringValue
= OUString( cValue
);
473 aStringType
= aTypeChar
;
475 else if ( rType
== cppu::UnoType
<sal_Int8
>::get() )
480 aStringValue
= OUString( sal_Unicode( nValue
) );
481 aStringType
= aTypeByte
;
483 else if ( rType
== cppu::UnoType
<sal_Int64
>::get() )
486 sal_Int64 nValue
= 0;
488 aStringValue
= OUString::number( nValue
);
489 aStringType
= aTypeHyper
;
491 else if ( rType
== cppu::UnoType
<float>::get() )
496 aStringValue
= OUString::number( nValue
);
497 aStringType
= aTypeFloat
;
499 else if ( rType
== cppu::UnoType
<double>::get() )
504 aStringValue
= OUString::number( nValue
);
505 aStringType
= aTypeDouble
;
509 SAL_WARN( "ucb.ucp.webdav",
510 "UCBDeadPropertyValue::toXML - "
511 "Unsupported property type!" );
515 // Encode value! It must not contain XML reserved chars!
516 aStringValue
= encodeValue( aStringValue
);
519 rOutData
+= aStringType
;
521 rOutData
+= aStringValue
;
526 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */