Bump for 3.6-28
[LibreOffice.git] / ucb / source / ucp / webdav / LockSequence.cxx
blob3b31b1f9fa11b9960857eafc87fc8c862fbd5ac1
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 ************************************************************************/
30 #include <string.h>
31 #include <ne_xml.h>
32 #include "LockSequence.hxx"
34 using namespace webdav_ucp;
35 using namespace com::sun::star;
37 #define BEEHIVE_BUGS_WORKAROUND
39 //////////////////////////////////////////////////////////////////////////
41 struct LockSequenceParseContext
43 ucb::Lock * pLock;
44 bool hasLockScope;
45 bool hasLockType;
46 bool hasDepth;
47 bool hasHREF;
48 bool hasTimeout;
50 LockSequenceParseContext()
51 : pLock( 0 ), hasLockScope( false ), hasLockType( false ),
52 hasDepth( false ), hasHREF( false ), hasTimeout( false ) {}
54 ~LockSequenceParseContext() { delete pLock; }
57 #define STATE_TOP (1)
59 #define STATE_ACTIVELOCK (STATE_TOP)
60 #define STATE_LOCKSCOPE (STATE_TOP + 1)
61 #define STATE_LOCKTYPE (STATE_TOP + 2)
62 #define STATE_DEPTH (STATE_TOP + 3)
63 #define STATE_OWNER (STATE_TOP + 4)
64 #define STATE_TIMEOUT (STATE_TOP + 5)
65 #define STATE_LOCKTOKEN (STATE_TOP + 6)
66 #define STATE_EXCLUSIVE (STATE_TOP + 7)
67 #define STATE_SHARED (STATE_TOP + 8)
68 #define STATE_WRITE (STATE_TOP + 9)
69 #define STATE_HREF (STATE_TOP + 10)
71 //////////////////////////////////////////////////////////////////////////
72 extern "C" int LockSequence_startelement_callback(
73 void *,
74 int parent,
75 const char * /*nspace*/,
76 const char *name,
77 const char ** )
79 if ( name != 0 )
81 switch ( parent )
83 case NE_XML_STATEROOT:
84 if ( strcmp( name, "activelock" ) == 0 )
85 return STATE_ACTIVELOCK;
86 break;
88 case STATE_ACTIVELOCK:
89 if ( strcmp( name, "lockscope" ) == 0 )
90 return STATE_LOCKSCOPE;
91 else if ( strcmp( name, "locktype" ) == 0 )
92 return STATE_LOCKTYPE;
93 else if ( strcmp( name, "depth" ) == 0 )
94 return STATE_DEPTH;
95 else if ( strcmp( name, "owner" ) == 0 )
96 return STATE_OWNER;
97 else if ( strcmp( name, "timeout" ) == 0 )
98 return STATE_TIMEOUT;
99 else if ( strcmp( name, "locktoken" ) == 0 )
100 return STATE_LOCKTOKEN;
101 break;
103 case STATE_LOCKSCOPE:
104 if ( strcmp( name, "exclusive" ) == 0 )
105 return STATE_EXCLUSIVE;
106 else if ( strcmp( name, "shared" ) == 0 )
107 return STATE_SHARED;
108 break;
110 case STATE_LOCKTYPE:
111 if ( strcmp( name, "write" ) == 0 )
112 return STATE_WRITE;
113 break;
115 case STATE_LOCKTOKEN:
116 if ( strcmp( name, "href" ) == 0 )
117 return STATE_HREF;
118 break;
120 case STATE_OWNER:
121 // owner elem contains ANY. Accept anything; no state change.
122 return STATE_OWNER;
125 return NE_XML_DECLINE;
128 //////////////////////////////////////////////////////////////////////////
129 extern "C" int LockSequence_chardata_callback(
130 void *userdata,
131 int state,
132 #ifdef BEEHIVE_BUGS_WORKAROUND
133 const char *buf1,
134 #else
135 const char *buf,
136 #endif
137 size_t len )
139 LockSequenceParseContext * pCtx
140 = static_cast< LockSequenceParseContext * >( userdata );
141 if ( !pCtx->pLock )
142 pCtx->pLock = new ucb::Lock;
144 #ifdef BEEHIVE_BUGS_WORKAROUND
145 // Beehive sends XML values containing trailing newlines.
146 if ( buf1[ len - 1 ] == 0x0a )
147 len--;
149 char * buf = new char[ len + 1 ]();
150 strncpy( buf, buf1, len );
151 #endif
153 switch ( state )
155 case STATE_DEPTH:
156 if ( rtl_str_compareIgnoreAsciiCase_WithLength(
157 buf, len, "0", 1 ) == 0 )
159 pCtx->pLock->Depth = ucb::LockDepth_ZERO;
160 pCtx->hasDepth = true;
162 else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
163 buf, len, "1", 1 ) == 0 )
165 pCtx->pLock->Depth = ucb::LockDepth_ONE;
166 pCtx->hasDepth = true;
168 else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
169 buf, len, "infinity", 8 ) == 0 )
171 pCtx->pLock->Depth = ucb::LockDepth_INFINITY;
172 pCtx->hasDepth = true;
174 else
175 OSL_FAIL( "LockSequence_chardata_callback - Unknown depth!" );
176 break;
178 case STATE_OWNER:
180 // collect raw XML data... (owner contains ANY)
181 rtl::OUString aValue;
182 pCtx->pLock->Owner >>= aValue;
183 aValue += rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
184 pCtx->pLock->Owner <<= aValue;
185 break;
188 case STATE_TIMEOUT:
190 // RFC2518, RFC2616:
192 // TimeType = ("Second-" DAVTimeOutVal | "Infinite" | Other)
193 // DAVTimeOutVal = 1*digit
194 // Other = "Extend" field-value
195 // field-value = *( field-content | LWS )
196 // field-content = <the OCTETs making up the field-value
197 // and consisting of either *TEXT or combinations
198 // of token, separators, and quoted-string>
200 if ( rtl_str_compareIgnoreAsciiCase_WithLength(
201 buf, len, "Infinite", 8 ) == 0 )
203 pCtx->pLock->Timeout = sal_Int64( -1 );
204 pCtx->hasTimeout = true;
206 else if ( rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
207 buf, len, "Second-", 7, 7 ) == 0 )
209 pCtx->pLock->Timeout
210 = rtl::OString( buf + 7, len - 7 ).toInt64();
211 pCtx->hasTimeout = true;
213 // else if ( rtl_str_shortenedCompareIgnoreCase_WithLength(
214 // buf, len, "Extend", 6, 6 ) == 0 )
215 // {
216 // @@@
217 // }
218 else
220 pCtx->pLock->Timeout = sal_Int64( -1 );
221 pCtx->hasTimeout = true;
222 OSL_FAIL( "LockSequence_chardata_callback - Unknown timeout!" );
224 break;
226 case STATE_HREF:
228 // collect hrefs.
229 sal_Int32 nPos = pCtx->pLock->LockTokens.getLength();
230 pCtx->pLock->LockTokens.realloc( nPos + 1 );
231 pCtx->pLock->LockTokens[ nPos ]
232 = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
233 pCtx->hasHREF = true;
234 break;
239 #ifdef BEEHIVE_BUGS_WORKAROUND
240 delete [] buf;
241 #endif
243 return 0; // zero to continue, non-zero to abort parsing
246 //////////////////////////////////////////////////////////////////////////
247 extern "C" int LockSequence_endelement_callback(
248 void *userdata,
249 int state,
250 const char *,
251 const char * )
253 LockSequenceParseContext * pCtx
254 = static_cast< LockSequenceParseContext * >( userdata );
255 if ( !pCtx->pLock )
256 pCtx->pLock = new ucb::Lock;
258 switch ( state )
260 case STATE_EXCLUSIVE:
261 pCtx->pLock->Scope = ucb::LockScope_EXCLUSIVE;
262 pCtx->hasLockScope = true;
263 break;
265 case STATE_SHARED:
266 pCtx->pLock->Scope = ucb::LockScope_SHARED;
267 pCtx->hasLockScope = true;
268 break;
270 case STATE_WRITE:
271 pCtx->pLock->Type = ucb::LockType_WRITE;
272 pCtx->hasLockType = true;
273 break;
275 case STATE_DEPTH:
276 if ( !pCtx->hasDepth )
277 return 1; // abort
278 break;
280 case STATE_HREF:
281 if ( !pCtx->hasHREF )
282 return 1; // abort
283 break;
285 case STATE_TIMEOUT:
286 if ( !pCtx->hasTimeout )
287 return 1; // abort
288 break;
290 case STATE_LOCKSCOPE:
291 if ( !pCtx->hasLockScope )
292 return 1; // abort
293 break;
295 case STATE_LOCKTYPE:
296 if ( !pCtx->hasLockType )
297 return 1; // abort
298 break;
300 case STATE_ACTIVELOCK:
301 if ( !pCtx->hasLockType || !pCtx->hasDepth )
302 return 1; // abort
303 break;
305 default:
306 break;
308 return 0; // zero to continue, non-zero to abort parsing
311 //////////////////////////////////////////////////////////////////////////
312 // static
313 bool LockSequence::createFromXML( const rtl::OString & rInData,
314 uno::Sequence< ucb::Lock > & rOutData )
316 const sal_Int32 TOKEN_LENGTH = 13; // </activelock>
317 bool success = true;
319 // rInData may contain multiple <activelock>...</activelock> tags.
320 sal_Int32 nCount = 0;
321 sal_Int32 nStart = 0;
322 sal_Int32 nEnd = rInData.indexOf( "</activelock>" );
323 while ( nEnd > -1 )
325 ne_xml_parser * parser = ne_xml_create();
326 if ( !parser )
328 success = false;
329 break;
332 LockSequenceParseContext aCtx;
333 ne_xml_push_handler( parser,
334 LockSequence_startelement_callback,
335 LockSequence_chardata_callback,
336 LockSequence_endelement_callback,
337 &aCtx );
339 ne_xml_parse( parser,
340 rInData.getStr() + nStart,
341 nEnd - nStart + TOKEN_LENGTH );
343 success = !ne_xml_failed( parser );
345 ne_xml_destroy( parser );
347 if ( !success )
348 break;
350 if ( aCtx.pLock )
352 nCount++;
353 if ( nCount > rOutData.getLength() )
354 rOutData.realloc( rOutData.getLength() + 1 );
356 rOutData[ nCount - 1 ] = *aCtx.pLock;
359 nStart = nEnd + TOKEN_LENGTH;
360 nEnd = rInData.indexOf( "</activelock>", nStart );
363 return success;
366 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */