LibreOffice Module ucb (master)  1
LockEntrySequence.cxx
Go to the documentation of this file.
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 "LockEntrySequence.hxx"
33 #include <memory>
34 
35 using namespace webdav_ucp;
36 using namespace com::sun::star;
37 
38 namespace {
39 
40 struct LockEntrySequenceParseContext
41 {
42  std::unique_ptr<ucb::LockEntry> pEntry;
43  bool hasScope;
44  bool hasType;
45 
46  LockEntrySequenceParseContext()
47  : hasScope( false ), hasType( false ) {}
48 };
49 
50 }
51 
52 #define STATE_TOP (1)
53 
54 #define STATE_LOCKENTRY (STATE_TOP)
55 #define STATE_LOCKSCOPE (STATE_TOP + 1)
56 #define STATE_EXCLUSIVE (STATE_TOP + 2)
57 #define STATE_SHARED (STATE_TOP + 3)
58 #define STATE_LOCKTYPE (STATE_TOP + 4)
59 #define STATE_WRITE (STATE_TOP + 5)
60 
61 
62 extern "C" {
63 
65  void *,
66  int parent,
67  const char * /*nspace*/,
68  const char *name,
69  const char ** )
70 {
71  if ( name != nullptr )
72  {
73  switch ( parent )
74  {
75  case NE_XML_STATEROOT:
76  if ( strcmp( name, "lockentry" ) == 0 )
77  return STATE_LOCKENTRY;
78  break;
79 
80  case STATE_LOCKENTRY:
81  if ( strcmp( name, "lockscope" ) == 0 )
82  return STATE_LOCKSCOPE;
83  else if ( strcmp( name, "locktype" ) == 0 )
84  return STATE_LOCKTYPE;
85 
86 #define IIS_BUGS_WORKAROUND
87 
88 #ifdef IIS_BUGS_WORKAROUND
89  /* IIS (6) returns XML violating RFC 4918
90  for DAV:supportedlock property value.
91 
92  <lockentry>
93  <write></write>
94  <shared></shared>
95  </lockentry>
96  <lockentry>
97  <write></write>
98  <exclusive></exclusive>
99  </lockentry>
100 
101  Bother...
102  */
103  else if ( strcmp( name, "exclusive" ) == 0 )
104  return STATE_EXCLUSIVE;
105  else if ( strcmp( name, "shared" ) == 0 )
106  return STATE_SHARED;
107  else if ( strcmp( name, "write" ) == 0 )
108  return STATE_WRITE;
109 #endif
110  break;
111 
112  case STATE_LOCKSCOPE:
113  if ( strcmp( name, "exclusive" ) == 0 )
114  return STATE_EXCLUSIVE;
115  else if ( strcmp( name, "shared" ) == 0 )
116  return STATE_SHARED;
117  break;
118 
119  case STATE_LOCKTYPE:
120  if ( strcmp( name, "write" ) == 0 )
121  return STATE_WRITE;
122  break;
123  }
124  }
125  return NE_XML_DECLINE;
126 }
127 
128 
130  void *,
131  int,
132  const char *,
133  size_t )
134 {
135  return 0; // zero to continue, non-zero to abort parsing
136 }
137 
138 
140  void *userdata,
141  int state,
142  const char *,
143  const char * )
144 {
145  LockEntrySequenceParseContext * pCtx
146  = static_cast< LockEntrySequenceParseContext * >( userdata );
147  if ( !pCtx->pEntry )
148  pCtx->pEntry.reset( new ucb::LockEntry );
149 
150  switch ( state )
151  {
152  case STATE_EXCLUSIVE:
153  pCtx->pEntry->Scope = ucb::LockScope_EXCLUSIVE;
154  pCtx->hasScope = true;
155  break;
156 
157  case STATE_SHARED:
158  pCtx->pEntry->Scope = ucb::LockScope_SHARED;
159  pCtx->hasScope = true;
160  break;
161 
162  case STATE_WRITE:
163  pCtx->pEntry->Type = ucb::LockType_WRITE;
164  pCtx->hasType = true;
165  break;
166 
167  case STATE_LOCKSCOPE:
168  if ( !pCtx->hasScope )
169  return 1; // abort
170  break;
171 
172  case STATE_LOCKTYPE:
173  if ( !pCtx->hasType )
174  return 1; // abort
175  break;
176 
177  case STATE_LOCKENTRY:
178  if ( !pCtx->hasType || !pCtx->hasScope )
179  return 1; // abort
180  break;
181 
182  default:
183  break;
184  }
185  return 0; // zero to continue, non-zero to abort parsing
186 }
187 
188 }
189 
190 // static
191 bool LockEntrySequence::createFromXML( const OString & rInData,
192  uno::Sequence<
193  ucb::LockEntry > & rOutData )
194 {
195  const sal_Int32 TOKEN_LENGTH = 12; // </lockentry>
196  bool success = true;
197 
198  // rInData may contain multiple <lockentry>...</lockentry> tags.
199  sal_Int32 nCount = 0;
200  sal_Int32 nStart = 0;
201  sal_Int32 nEnd = rInData.indexOf( "</lockentry>" );
202  while ( nEnd > -1 )
203  {
204  ne_xml_parser * parser = ne_xml_create();
205  if ( !parser )
206  {
207  success = false;
208  break;
209  }
210 
211  LockEntrySequenceParseContext aCtx;
212  ne_xml_push_handler( parser,
216  &aCtx );
217 
218  ne_xml_parse( parser,
219  rInData.getStr() + nStart,
220  nEnd - nStart + TOKEN_LENGTH );
221 
222  success = !ne_xml_failed( parser );
223 
224  ne_xml_destroy( parser );
225 
226  if ( !success )
227  break;
228 
229  if ( aCtx.pEntry )
230  {
231  nCount++;
232  if ( nCount > rOutData.getLength() )
233  rOutData.realloc( rOutData.getLength() + 2 );
234 
235  rOutData[ nCount - 1 ] = *aCtx.pEntry;
236  }
237 
238  nStart = nEnd + TOKEN_LENGTH;
239  nEnd = rInData.indexOf( "</lockentry>", nStart );
240  }
241 
242  rOutData.realloc( nCount );
243  return success;
244 }
245 
246 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
#define STATE_LOCKTYPE
tuple parser
#define STATE_LOCKENTRY
#define STATE_EXCLUSIVE
static int LockEntrySequence_endelement_callback(void *userdata, int state, const char *, const char *)
static int LockEntrySequence_startelement_callback(void *, int parent, const char *, const char *name, const char **)
int nCount
static bool createFromXML(const OString &rInData, css::uno::Sequence< css::ucb::LockEntry > &rOutData)
static int LockEntrySequence_chardata_callback(void *, int, const char *, size_t)
#define STATE_LOCKSCOPE
#define STATE_SHARED
#define STATE_WRITE