Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
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.
15 : : *
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).
21 : : *
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.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <string.h>
31 : : #include <ne_xml.h>
32 : : #include "LockSequence.hxx"
33 : :
34 : : using namespace webdav_ucp;
35 : : using namespace com::sun::star;
36 : :
37 : : #define BEEHIVE_BUGS_WORKAROUND
38 : :
39 : : //////////////////////////////////////////////////////////////////////////
40 : :
41 : : struct LockSequenceParseContext
42 : : {
43 : : ucb::Lock * pLock;
44 : : bool hasLockScope;
45 : : bool hasLockType;
46 : : bool hasDepth;
47 : : bool hasHREF;
48 : : bool hasTimeout;
49 : :
50 : 0 : LockSequenceParseContext()
51 : : : pLock( 0 ), hasLockScope( false ), hasLockType( false ),
52 : 0 : hasDepth( false ), hasHREF( false ), hasTimeout( false ) {}
53 : :
54 [ # # ]: 0 : ~LockSequenceParseContext() { delete pLock; }
55 : : };
56 : :
57 : : #define STATE_TOP (1)
58 : :
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)
70 : :
71 : : //////////////////////////////////////////////////////////////////////////
72 : 0 : extern "C" int LockSequence_startelement_callback(
73 : : void *,
74 : : int parent,
75 : : const char * /*nspace*/,
76 : : const char *name,
77 : : const char ** )
78 : : {
79 [ # # ]: 0 : if ( name != 0 )
80 : : {
81 [ # # # # : 0 : switch ( parent )
# # # ]
82 : : {
83 : : case NE_XML_STATEROOT:
84 [ # # ]: 0 : if ( strcmp( name, "activelock" ) == 0 )
85 : 0 : return STATE_ACTIVELOCK;
86 : 0 : break;
87 : :
88 : : case STATE_ACTIVELOCK:
89 [ # # ]: 0 : if ( strcmp( name, "lockscope" ) == 0 )
90 : 0 : return STATE_LOCKSCOPE;
91 [ # # ]: 0 : else if ( strcmp( name, "locktype" ) == 0 )
92 : 0 : return STATE_LOCKTYPE;
93 [ # # ]: 0 : else if ( strcmp( name, "depth" ) == 0 )
94 : 0 : return STATE_DEPTH;
95 [ # # ]: 0 : else if ( strcmp( name, "owner" ) == 0 )
96 : 0 : return STATE_OWNER;
97 [ # # ]: 0 : else if ( strcmp( name, "timeout" ) == 0 )
98 : 0 : return STATE_TIMEOUT;
99 [ # # ]: 0 : else if ( strcmp( name, "locktoken" ) == 0 )
100 : 0 : return STATE_LOCKTOKEN;
101 : 0 : break;
102 : :
103 : : case STATE_LOCKSCOPE:
104 [ # # ]: 0 : if ( strcmp( name, "exclusive" ) == 0 )
105 : 0 : return STATE_EXCLUSIVE;
106 [ # # ]: 0 : else if ( strcmp( name, "shared" ) == 0 )
107 : 0 : return STATE_SHARED;
108 : 0 : break;
109 : :
110 : : case STATE_LOCKTYPE:
111 [ # # ]: 0 : if ( strcmp( name, "write" ) == 0 )
112 : 0 : return STATE_WRITE;
113 : 0 : break;
114 : :
115 : : case STATE_LOCKTOKEN:
116 [ # # ]: 0 : if ( strcmp( name, "href" ) == 0 )
117 : 0 : return STATE_HREF;
118 : 0 : break;
119 : :
120 : : case STATE_OWNER:
121 : : // owner elem contains ANY. Accept anything; no state change.
122 : 0 : return STATE_OWNER;
123 : : }
124 : : }
125 : 0 : return NE_XML_DECLINE;
126 : : }
127 : :
128 : : //////////////////////////////////////////////////////////////////////////
129 : 0 : 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 )
138 : : {
139 : : LockSequenceParseContext * pCtx
140 : 0 : = static_cast< LockSequenceParseContext * >( userdata );
141 [ # # ]: 0 : if ( !pCtx->pLock )
142 [ # # ]: 0 : pCtx->pLock = new ucb::Lock;
143 : :
144 : : #ifdef BEEHIVE_BUGS_WORKAROUND
145 : : // Beehive sends XML values containing trailing newlines.
146 [ # # ]: 0 : if ( buf1[ len - 1 ] == 0x0a )
147 : 0 : len--;
148 : :
149 [ # # ]: 0 : char * buf = new char[ len + 1 ]();
150 : 0 : strncpy( buf, buf1, len );
151 : : #endif
152 : :
153 [ # # # # : 0 : switch ( state )
# ]
154 : : {
155 : : case STATE_DEPTH:
156 [ # # ]: 0 : if ( rtl_str_compareIgnoreAsciiCase_WithLength(
157 : 0 : buf, len, "0", 1 ) == 0 )
158 : : {
159 : 0 : pCtx->pLock->Depth = ucb::LockDepth_ZERO;
160 : 0 : pCtx->hasDepth = true;
161 : : }
162 [ # # ]: 0 : else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
163 : 0 : buf, len, "1", 1 ) == 0 )
164 : : {
165 : 0 : pCtx->pLock->Depth = ucb::LockDepth_ONE;
166 : 0 : pCtx->hasDepth = true;
167 : : }
168 [ # # ]: 0 : else if ( rtl_str_compareIgnoreAsciiCase_WithLength(
169 : 0 : buf, len, "infinity", 8 ) == 0 )
170 : : {
171 : 0 : pCtx->pLock->Depth = ucb::LockDepth_INFINITY;
172 : 0 : pCtx->hasDepth = true;
173 : : }
174 : : else
175 : : OSL_FAIL( "LockSequence_chardata_callback - Unknown depth!" );
176 : 0 : break;
177 : :
178 : : case STATE_OWNER:
179 : : {
180 : : // collect raw XML data... (owner contains ANY)
181 : 0 : rtl::OUString aValue;
182 : 0 : pCtx->pLock->Owner >>= aValue;
183 [ # # ]: 0 : aValue += rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
184 [ # # ]: 0 : pCtx->pLock->Owner <<= aValue;
185 : 0 : break;
186 : : }
187 : :
188 : : case STATE_TIMEOUT:
189 : : //
190 : : // RFC2518, RFC2616:
191 : : //
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>
199 : :
200 [ # # ]: 0 : if ( rtl_str_compareIgnoreAsciiCase_WithLength(
201 : 0 : buf, len, "Infinite", 8 ) == 0 )
202 : : {
203 : 0 : pCtx->pLock->Timeout = sal_Int64( -1 );
204 : 0 : pCtx->hasTimeout = true;
205 : : }
206 [ # # ]: 0 : else if ( rtl_str_shortenedCompareIgnoreAsciiCase_WithLength(
207 : 0 : buf, len, "Second-", 7, 7 ) == 0 )
208 : : {
209 : : pCtx->pLock->Timeout
210 : 0 : = rtl::OString( buf + 7, len - 7 ).toInt64();
211 : 0 : pCtx->hasTimeout = true;
212 : : }
213 : : // else if ( rtl_str_shortenedCompareIgnoreCase_WithLength(
214 : : // buf, len, "Extend", 6, 6 ) == 0 )
215 : : // {
216 : : // @@@
217 : : // }
218 : : else
219 : : {
220 : 0 : pCtx->pLock->Timeout = sal_Int64( -1 );
221 : 0 : pCtx->hasTimeout = true;
222 : : OSL_FAIL( "LockSequence_chardata_callback - Unknown timeout!" );
223 : : }
224 : 0 : break;
225 : :
226 : : case STATE_HREF:
227 : : {
228 : : // collect hrefs.
229 : 0 : sal_Int32 nPos = pCtx->pLock->LockTokens.getLength();
230 : 0 : pCtx->pLock->LockTokens.realloc( nPos + 1 );
231 [ # # ]: 0 : pCtx->pLock->LockTokens[ nPos ]
232 : 0 : = rtl::OUString( buf, len, RTL_TEXTENCODING_ASCII_US );
233 : 0 : pCtx->hasHREF = true;
234 : 0 : break;
235 : : }
236 : :
237 : : }
238 : :
239 : : #ifdef BEEHIVE_BUGS_WORKAROUND
240 [ # # ]: 0 : delete [] buf;
241 : : #endif
242 : :
243 : 0 : return 0; // zero to continue, non-zero to abort parsing
244 : : }
245 : :
246 : : //////////////////////////////////////////////////////////////////////////
247 : 0 : extern "C" int LockSequence_endelement_callback(
248 : : void *userdata,
249 : : int state,
250 : : const char *,
251 : : const char * )
252 : : {
253 : : LockSequenceParseContext * pCtx
254 : 0 : = static_cast< LockSequenceParseContext * >( userdata );
255 [ # # ]: 0 : if ( !pCtx->pLock )
256 [ # # ]: 0 : pCtx->pLock = new ucb::Lock;
257 : :
258 [ # # # # : 0 : switch ( state )
# # # # #
# ]
259 : : {
260 : : case STATE_EXCLUSIVE:
261 : 0 : pCtx->pLock->Scope = ucb::LockScope_EXCLUSIVE;
262 : 0 : pCtx->hasLockScope = true;
263 : 0 : break;
264 : :
265 : : case STATE_SHARED:
266 : 0 : pCtx->pLock->Scope = ucb::LockScope_SHARED;
267 : 0 : pCtx->hasLockScope = true;
268 : 0 : break;
269 : :
270 : : case STATE_WRITE:
271 : 0 : pCtx->pLock->Type = ucb::LockType_WRITE;
272 : 0 : pCtx->hasLockType = true;
273 : 0 : break;
274 : :
275 : : case STATE_DEPTH:
276 [ # # ]: 0 : if ( !pCtx->hasDepth )
277 : 0 : return 1; // abort
278 : 0 : break;
279 : :
280 : : case STATE_HREF:
281 [ # # ]: 0 : if ( !pCtx->hasHREF )
282 : 0 : return 1; // abort
283 : 0 : break;
284 : :
285 : : case STATE_TIMEOUT:
286 [ # # ]: 0 : if ( !pCtx->hasTimeout )
287 : 0 : return 1; // abort
288 : 0 : break;
289 : :
290 : : case STATE_LOCKSCOPE:
291 [ # # ]: 0 : if ( !pCtx->hasLockScope )
292 : 0 : return 1; // abort
293 : 0 : break;
294 : :
295 : : case STATE_LOCKTYPE:
296 [ # # ]: 0 : if ( !pCtx->hasLockType )
297 : 0 : return 1; // abort
298 : 0 : break;
299 : :
300 : : case STATE_ACTIVELOCK:
301 [ # # ][ # # ]: 0 : if ( !pCtx->hasLockType || !pCtx->hasDepth )
302 : 0 : return 1; // abort
303 : 0 : break;
304 : :
305 : : default:
306 : 0 : break;
307 : : }
308 : 0 : return 0; // zero to continue, non-zero to abort parsing
309 : : }
310 : :
311 : : //////////////////////////////////////////////////////////////////////////
312 : : // static
313 : 0 : bool LockSequence::createFromXML( const rtl::OString & rInData,
314 : : uno::Sequence< ucb::Lock > & rOutData )
315 : : {
316 : 0 : const sal_Int32 TOKEN_LENGTH = 13; // </activelock>
317 : 0 : bool success = true;
318 : :
319 : : // rInData may contain multiple <activelock>...</activelock> tags.
320 : 0 : sal_Int32 nCount = 0;
321 : 0 : sal_Int32 nStart = 0;
322 : 0 : sal_Int32 nEnd = rInData.indexOf( "</activelock>" );
323 [ # # ]: 0 : while ( nEnd > -1 )
324 : : {
325 [ # # ]: 0 : ne_xml_parser * parser = ne_xml_create();
326 [ # # ]: 0 : if ( !parser )
327 : : {
328 : 0 : success = false;
329 : : break;
330 : : }
331 : :
332 : 0 : LockSequenceParseContext aCtx;
333 : : ne_xml_push_handler( parser,
334 : : LockSequence_startelement_callback,
335 : : LockSequence_chardata_callback,
336 : : LockSequence_endelement_callback,
337 [ # # ]: 0 : &aCtx );
338 : :
339 : : ne_xml_parse( parser,
340 : 0 : rInData.getStr() + nStart,
341 [ # # ]: 0 : nEnd - nStart + TOKEN_LENGTH );
342 : :
343 [ # # ]: 0 : success = !ne_xml_failed( parser );
344 : :
345 [ # # ]: 0 : ne_xml_destroy( parser );
346 : :
347 [ # # ]: 0 : if ( !success )
348 : : break;
349 : :
350 [ # # ]: 0 : if ( aCtx.pLock )
351 : : {
352 : 0 : nCount++;
353 [ # # ]: 0 : if ( nCount > rOutData.getLength() )
354 [ # # ]: 0 : rOutData.realloc( rOutData.getLength() + 1 );
355 : :
356 [ # # ][ # # ]: 0 : rOutData[ nCount - 1 ] = *aCtx.pLock;
357 : : }
358 : :
359 : 0 : nStart = nEnd + TOKEN_LENGTH;
360 [ # # ]: 0 : nEnd = rInData.indexOf( "</activelock>", nStart );
361 [ # # ]: 0 : }
362 : :
363 : 0 : return success;
364 : : }
365 : :
366 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|