nss: upgrade to release 3.73
[LibreOffice.git] / ucb / source / ucp / webdav / UCBDeadPropertyValue.cxx
blob0f3543012ce7f0f8fa44fc96aee8dd42ba75be1b
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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;
28 // static
29 const OUString UCBDeadPropertyValue::aTypeString
30 = "string";
31 const OUString UCBDeadPropertyValue::aTypeLong
32 = "long";
33 const OUString UCBDeadPropertyValue::aTypeShort
34 = "short";
35 const OUString UCBDeadPropertyValue::aTypeBoolean
36 = "boolean";
37 const OUString UCBDeadPropertyValue::aTypeChar
38 = "char";
39 const OUString UCBDeadPropertyValue::aTypeByte
40 = "byte";
41 const OUString UCBDeadPropertyValue::aTypeHyper
42 = "hyper";
43 const OUString UCBDeadPropertyValue::aTypeFloat
44 = "float";
45 const OUString UCBDeadPropertyValue::aTypeDouble
46 = "double";
48 // static
49 const OUString UCBDeadPropertyValue::aXMLPre
50 = "<ucbprop><type>";
51 const OUString UCBDeadPropertyValue::aXMLMid
52 = "</type><value>";
53 const OUString UCBDeadPropertyValue::aXMLEnd
54 = "</value></ucbprop>";
58 #define STATE_TOP (1)
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(
65 void *,
66 int parent,
67 const char * nspace,
68 const char *name,
69 const char ** )
71 if ( name != 0 )
73 switch ( parent )
75 case NE_XML_STATEROOT:
76 if ( strcmp( name, "ucbprop" ) == 0 )
77 return STATE_UCBPROP;
78 break;
80 case STATE_UCBPROP:
81 if ( strcmp( name, "type" ) == 0 )
82 return STATE_TYPE;
83 else if ( strcmp( name, "value" ) == 0 )
84 return STATE_VALUE;
85 break;
88 return NE_XML_DECLINE;
92 extern "C" int UCBDeadPropertyValue_chardata_callback(
93 void *userdata,
94 int state,
95 const char *buf,
96 size_t len )
98 UCBDeadPropertyValueParseContext * pCtx
99 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
101 switch ( state )
103 case STATE_TYPE:
104 SAL_WARN_IF( pCtx->pType, "ucb.ucp.webdav",
105 "UCBDeadPropertyValue_endelement_callback - "
106 "Type already set!" );
107 pCtx->pType
108 = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
109 break;
111 case STATE_VALUE:
112 SAL_WARN_IF( pCtx->pValue, "ucb.ucp.webdav",
113 "UCBDeadPropertyValue_endelement_callback - "
114 "Value already set!" );
115 pCtx->pValue
116 = new OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
117 break;
119 return 0; // zero to continue, non-zero to abort parsing
123 extern "C" int UCBDeadPropertyValue_endelement_callback(
124 void *userdata,
125 int state,
126 const char *,
127 const char * )
129 UCBDeadPropertyValueParseContext * pCtx
130 = static_cast< UCBDeadPropertyValueParseContext * >( userdata );
132 switch ( state )
134 case STATE_TYPE:
135 if ( !pCtx->pType )
136 return 1; // abort
137 break;
139 case STATE_VALUE:
140 if ( !pCtx->pValue )
141 return 1; // abort
142 break;
144 case STATE_UCBPROP:
145 if ( !pCtx->pType || ! pCtx->pValue )
146 return 1; // abort
147 break;
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 &amp; + &lt; + &gt; encoding, because
157 // I want to prevent any XML parser from trying to 'understand'
158 // the value. This caused problems:
160 // Example:
161 // - Unencoded property value: x<z
162 // PROPPATCH:
163 // - Encoded property value: x&lt;z
164 // - UCBDeadPropertyValue::toXML result:
165 // <ucbprop><type>string</type><value>x&lt;z</value></ucbprop>
166 // PROPFIND:
167 // - parser replaces &lt; 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 ];
177 if ( '%' == c )
178 aResult.append( "%per;" );
179 else if ( '<' == c )
180 aResult.append( "%lt;" );
181 else if ( '>' == c )
182 aResult.append( "%gt;" );
183 else
184 aResult.append( c );
186 return aResult.makeStringAndClear();
191 static OUString decodeValue( const OUString & rValue )
193 OUStringBuffer aResult;
194 const sal_Unicode * pValue = rValue.getStr();
196 sal_Int32 nPos = 0;
197 sal_Int32 nEnd = rValue.getLength();
199 while ( nPos < nEnd )
201 sal_Unicode c = pValue[ nPos ];
203 if ( '%' == c )
205 nPos++;
207 if ( nPos == nEnd )
209 SAL_WARN( "ucb.ucp.webdav",
210 "UCBDeadPropertyValue::decodeValue - syntax error!" );
211 return OUString();
214 c = pValue[ nPos ];
216 if ( 'p' == c )
218 // %per;
220 if ( nPos > nEnd - 4 )
222 SAL_WARN( "ucb.ucp.webdav",
223 "UCBDeadPropertyValue::decodeValue - syntax error!" );
224 return OUString();
227 if ( ( 'e' == pValue[ nPos + 1 ] )
229 ( 'r' == pValue[ nPos + 2 ] )
231 ( ';' == pValue[ nPos + 3 ] ) )
233 aResult.append( '%' );
234 nPos += 3;
236 else
238 SAL_WARN( "ucb.ucp.webdav",
239 "UCBDeadPropertyValue::decodeValue - syntax error!" );
240 return OUString();
243 else if ( 'l' == c )
245 // %lt;
247 if ( nPos > nEnd - 3 )
249 SAL_WARN( "ucb.ucp.webdav",
250 "UCBDeadPropertyValue::decodeValue - syntax error!" );
251 return OUString();
254 if ( ( 't' == pValue[ nPos + 1 ] )
256 ( ';' == pValue[ nPos + 2 ] ) )
258 aResult.append( '<' );
259 nPos += 2;
261 else
263 SAL_WARN( "ucb.ucp.webdav",
264 "UCBDeadPropertyValue::decodeValue - syntax error!" );
265 return OUString();
268 else if ( 'g' == c )
270 // %gt;
272 if ( nPos > nEnd - 3 )
274 SAL_WARN( "ucb.ucp.webdav",
275 "UCBDeadPropertyValue::decodeValue - syntax error!" );
276 return OUString();
279 if ( ( 't' == pValue[ nPos + 1 ] )
281 ( ';' == pValue[ nPos + 2 ] ) )
283 aResult.append( '>' );
284 nPos += 2;
286 else
288 SAL_WARN( "ucb.ucp.webdav",
289 "UCBDeadPropertyValue::decodeValue - syntax error!" );
290 return OUString();
293 else
295 SAL_WARN( "ucb.ucp.webdav",
296 "UCBDeadPropertyValue::decodeValue - syntax error!" );
297 return OUString();
300 else
301 aResult.append( c );
303 nPos++;
306 return OUString( aResult );
311 // static
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() ) )
332 return false;
335 return true;
339 // static
340 bool UCBDeadPropertyValue::createFromXML( const OString & /*rInData*/,
341 uno::Any & /*rOutData*/ )
343 bool success = false;
346 ne_xml_parser * parser = ne_xml_create();
347 if ( parser )
349 UCBDeadPropertyValueParseContext aCtx;
350 ne_xml_push_handler( parser,
351 UCBDeadPropertyValue_startelement_callback,
352 UCBDeadPropertyValue_chardata_callback,
353 UCBDeadPropertyValue_endelement_callback,
354 &aCtx );
356 ne_xml_parse( parser, rInData.getStr(), rInData.getLength() );
358 success = !ne_xml_failed( parser );
360 ne_xml_destroy( parser );
362 if ( success )
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 );
385 else
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();
408 else
410 SAL_WARN( "ucb.ucp.webdav",
411 "UCBDeadPropertyValue::createFromXML - "
412 "Unsupported property type!" );
413 success = false;
416 else
417 success = false;
421 return success;
425 // static
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() )
439 // string
440 rInData >>= aStringValue;
441 aStringType = aTypeString;
443 else if ( rType == cppu::UnoType<sal_Int32>::get() )
445 // long
446 sal_Int32 nValue = 0;
447 rInData >>= nValue;
448 aStringValue = OUString::number( nValue );
449 aStringType = aTypeLong;
451 else if ( rType == cppu::UnoType<sal_Int16>::get() )
453 // short
454 sal_Int32 nValue = 0;
455 rInData >>= nValue;
456 aStringValue = OUString::number( nValue );
457 aStringType = aTypeShort;
459 else if ( rType == cppu::UnoType<bool>::get() )
461 // boolean
462 bool bValue = false;
463 rInData >>= bValue;
464 aStringValue = OUString::boolean( bValue );
465 aStringType = aTypeBoolean;
467 else if ( rType == cppu::UnoType<cppu::UnoCharType>::get() )
469 // char
470 sal_Unicode cValue = 0;
471 rInData >>= cValue;
472 aStringValue = OUString( cValue );
473 aStringType = aTypeChar;
475 else if ( rType == cppu::UnoType<sal_Int8>::get() )
477 // byte
478 sal_Int8 nValue = 0;
479 rInData >>= nValue;
480 aStringValue = OUString( sal_Unicode( nValue ) );
481 aStringType = aTypeByte;
483 else if ( rType == cppu::UnoType<sal_Int64>::get() )
485 // hyper
486 sal_Int64 nValue = 0;
487 rInData >>= nValue;
488 aStringValue = OUString::number( nValue );
489 aStringType = aTypeHyper;
491 else if ( rType == cppu::UnoType<float>::get() )
493 // float
494 float nValue = 0;
495 rInData >>= nValue;
496 aStringValue = OUString::number( nValue );
497 aStringType = aTypeFloat;
499 else if ( rType == cppu::UnoType<double>::get() )
501 // double
502 double nValue = 0;
503 rInData >>= nValue;
504 aStringValue = OUString::number( nValue );
505 aStringType = aTypeDouble;
507 else
509 SAL_WARN( "ucb.ucp.webdav",
510 "UCBDeadPropertyValue::toXML - "
511 "Unsupported property type!" );
512 return false;
515 // Encode value! It must not contain XML reserved chars!
516 aStringValue = encodeValue( aStringValue );
518 rOutData = aXMLPre;
519 rOutData += aStringType;
520 rOutData += aXMLMid;
521 rOutData += aStringValue;
522 rOutData += aXMLEnd;
523 return true;
526 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */