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 : #include <config_lgpl.h>
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 : OUString aValue;
182 0 : pCtx->pLock->Owner >>= aValue;
183 0 : aValue += 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 : = 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 : = 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 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 0 : 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 0 : 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: */
|