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