LibreOffice Module ucb (master)  1
NeonPropFindRequest.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 
30 #include <osl/mutex.hxx>
31 #include <rtl/strbuf.hxx>
32 #include <sal/log.hxx>
33 #include "NeonSession.hxx"
34 #include "NeonTypes.hxx"
35 #include "DAVException.hxx"
36 #include "DAVProperties.hxx"
37 #include "NeonPropFindRequest.hxx"
38 #include "LinkSequence.hxx"
39 #include "LockSequence.hxx"
40 #include "LockEntrySequence.hxx"
41 #include "UCBDeadPropertyValue.hxx"
42 #include <memory>
43 
44 using namespace com::sun::star::uno;
45 using namespace com::sun::star::ucb;
46 using namespace std;
47 using namespace webdav_ucp;
48 
49 
50 namespace
51 {
52  // strip "DAV:" namespace from XML snippets to avoid
53  // parser error (undeclared namespace) later on.
54  OString stripDavNamespace( const OString & in )
55  {
56  const OString inXML( in.toAsciiLowerCase() );
57 
58  OStringBuffer buf;
59  sal_Int32 start = 0;
60  sal_Int32 end = inXML.indexOf( "dav:" );
61  while ( end != -1 )
62  {
63  if ( inXML[ end - 1 ] == '<' ||
64  inXML[ end - 1 ] == '/' )
65  {
66  // copy from original buffer - preserve case.
67  buf.append( in.copy( start, end - start ) );
68  }
69  else
70  {
71  // copy from original buffer - preserve case.
72  buf.append( in.copy( start, end - start + 4 ) );
73  }
74  start = end + 4;
75  end = inXML.indexOf( "dav:", start );
76  }
77  buf.append( inXML.copy( start ) );
78 
79  return buf.makeStringAndClear();
80  }
81 }
82 
83 extern "C" {
84 
85 static int NPFR_propfind_iter( void* userdata,
86  const NeonPropName* pname,
87  const char* value,
88  const HttpStatus* status )
89 {
90  /*
91  HTTP Response Status Classes:
92 
93  - 1: Informational - Request received, continuing process
94 
95  - 2: Success - The action was successfully received,
96  understood, and accepted
97 
98  - 3: Redirection - Further action must be taken in order to
99  complete the request
100 
101  - 4: Client Error - The request contains bad syntax or cannot
102  be fulfilled
103 
104  - 5: Server Error - The server failed to fulfill an apparently
105  valid request
106  */
107 
108  if ( status->klass > 2 )
109  return 0; // Error getting this property. Go on.
110 
111  // Create & set the PropertyValue
112  DAVPropertyValue thePropertyValue;
113  thePropertyValue.IsCaseSensitive = true;
114 
115  SAL_WARN_IF( !pname->nspace, "ucb.ucp.webdav", "NPFR_propfind_iter - No XML namespace!" );
116 
117  DAVProperties::createUCBPropName( pname->nspace,
118  pname->name,
119  thePropertyValue.Name );
120  bool bHasValue = false;
121  if ( DAVProperties::isUCBDeadProperty( *pname ) )
122  {
123  // DAV dead property added by WebDAV UCP?
124  if ( UCBDeadPropertyValue::createFromXML(
125  value, thePropertyValue.Value ) )
126  {
127  SAL_WARN_IF( !thePropertyValue.Value.hasValue(),
128  "ucb.ucp.webdav", "NPFR_propfind_iter - No value for UCBDeadProperty!" );
129  bHasValue = true;
130  }
131  }
132 
133  if ( !bHasValue )
134  {
135  if ( rtl_str_compareIgnoreAsciiCase(
136  pname->name, "resourcetype" ) == 0 )
137  {
138  OString aValue( value );
139  aValue = aValue.trim(); // #107358# remove leading/trailing spaces
140  if ( !aValue.isEmpty() )
141  {
142  aValue = stripDavNamespace( aValue ).toAsciiLowerCase();
143  if ( aValue.startsWith("<collection") )
144  {
145  thePropertyValue.Value
146  <<= OUString("collection");
147  }
148  }
149 
150  if ( !thePropertyValue.Value.hasValue() )
151  {
152  // Take over the value exactly as supplied by the server.
153  thePropertyValue.Value <<= OUString::createFromAscii( value );
154  }
155  }
156  else if ( rtl_str_compareIgnoreAsciiCase(
157  pname->name, "supportedlock" ) == 0 )
158  {
160  LockEntrySequence::createFromXML(
161  stripDavNamespace( value ), aEntries );
162  thePropertyValue.Value <<= aEntries;
163  }
164  else if ( rtl_str_compareIgnoreAsciiCase(
165  pname->name, "lockdiscovery" ) == 0 )
166  {
167  Sequence< Lock > aLocks;
168  LockSequence::createFromXML(
169  stripDavNamespace( value ), aLocks );
170  thePropertyValue.Value <<= aLocks;
171  }
172  else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "source" ) == 0 )
173  {
174  Sequence< Link > aLinks;
175  LinkSequence::createFromXML(
176  stripDavNamespace( value ), aLinks );
177  thePropertyValue.Value <<= aLinks;
178  }
179  else
180  {
181  thePropertyValue.Value
182  <<= OStringToOUString( value, RTL_TEXTENCODING_UTF8 );
183  }
184  }
185 
186  // Add the newly created PropertyValue
187  DAVResource* theResource = static_cast< DAVResource * >( userdata );
188  theResource->properties.push_back( thePropertyValue );
189 
190  return 0; // Go on.
191 }
192 
193 static void NPFR_propfind_results( void* userdata,
194  const ne_uri* uri,
195  const NeonPropFindResultSet* set )
196 {
197  // @@@ href is not the uri! DAVResource ctor wants uri!
198 
199  DAVResource theResource(
200  OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
201 
202  ne_propset_iterate( set, NPFR_propfind_iter, &theResource );
203 
204  // Add entry to resources list.
205  vector< DAVResource > * theResources
206  = static_cast< vector< DAVResource > * >( userdata );
207  theResources->push_back( theResource );
208 }
209 
210 static int NPFR_propnames_iter( void* userdata,
211  const NeonPropName* pname,
212  const char* /*value*/,
213  const HttpStatus* /*status*/ )
214 {
215  OUString aFullName;
216  DAVProperties::createUCBPropName( pname->nspace,
217  pname->name,
218  aFullName );
219 
220  DAVResourceInfo* theResource = static_cast< DAVResourceInfo * >( userdata );
221  theResource->properties.push_back( aFullName );
222  return 0;
223 }
224 
225 static void NPFR_propnames_results( void* userdata,
226  const ne_uri* /*uri*/,
227  const NeonPropFindResultSet* results )
228 {
229  // @@@ href is not the uri! DAVResourceInfo ctor wants uri!
230  // Create entry for the resource.
231  DAVResourceInfo theResource;
232 
233  // Fill entry.
234  ne_propset_iterate( results, NPFR_propnames_iter, &theResource );
235 
236  // Add entry to resources list.
237  vector< DAVResourceInfo > * theResources
238  = static_cast< vector< DAVResourceInfo > * >( userdata );
239  theResources->push_back( theResource );
240 }
241 
242 }
243 
244 NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession,
245  const char* inPath,
246  const Depth inDepth,
247  const vector< OUString >& inPropNames,
248  vector< DAVResource >& ioResources,
249  int & nError )
250 {
251  // Generate the list of properties we're looking for
252  int thePropCount = inPropNames.size();
253  if ( thePropCount > 0 )
254  {
255  std::unique_ptr<NeonPropName[]> thePropNames(new NeonPropName[ thePropCount + 1 ]);
256  int theIndex;
257 
258  for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
259  {
260  // Split fullname into namespace and name!
261  DAVProperties::createNeonPropName(
262  inPropNames[ theIndex ], thePropNames[ theIndex ] );
263  }
264  thePropNames[ theIndex ].nspace = nullptr;
265  thePropNames[ theIndex ].name = nullptr;
266 
267  {
268  osl::Guard< osl::Mutex > theGlobalGuard(getGlobalNeonMutex());
269  nError = ne_simple_propfind( inSession,
270  inPath,
271  inDepth,
272  thePropNames.get(),
274  &ioResources );
275  }
276 
277  for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
278  free( const_cast<char *>(thePropNames[ theIndex ].name) );
279  }
280  else
281  {
282  // ALLPROP
283  osl::Guard< osl::Mutex > theGlobalGuard(getGlobalNeonMutex());
284  nError = ne_simple_propfind( inSession,
285  inPath,
286  inDepth,
287  nullptr, // 0 == allprop
289  &ioResources );
290  }
291 
292  // #87585# - Sometimes neon lies (because some servers lie).
293  if ( ( nError == NE_OK ) && ioResources.empty() )
294  nError = NE_ERROR;
295 }
296 
297 NeonPropFindRequest::NeonPropFindRequest(
298  HttpSession* inSession,
299  const char* inPath,
300  const Depth inDepth,
301  std::vector< DAVResourceInfo > & ioResInfo,
302  int & nError )
303 {
304  {
305  osl::Guard< osl::Mutex > theGlobalGuard(getGlobalNeonMutex());
306  nError = ne_propnames( inSession,
307  inPath,
308  inDepth,
310  &ioResInfo );
311  }
312 
313  // #87585# - Sometimes neon lies (because some servers lie).
314  if ( ( nError == NE_OK ) && ioResInfo.empty() )
315  nError = NE_ERROR;
316 }
317 
318 NeonPropFindRequest::~NeonPropFindRequest( )
319 {
320 }
321 
322 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
ne_propname NeonPropName
Definition: NeonTypes.hxx:50
ne_session HttpSession
Definition: NeonTypes.hxx:47
static void NPFR_propfind_results(void *userdata, const ne_uri *uri, const NeonPropFindResultSet *set)
std::vector< OUString > properties
osl::Mutex & getGlobalNeonMutex()
ne_prop_result_set NeonPropFindResultSet
Definition: NeonTypes.hxx:51
enumrange< T >::Iterator end(enumrange< T >)
ne_status HttpStatus
Definition: NeonTypes.hxx:48
std::vector< DAVPropertyValue > properties
#define SAL_WARN_IF(condition, area, stream)
static int NPFR_propfind_iter(void *userdata, const NeonPropName *pname, const char *value, const HttpStatus *status)
static void NPFR_propnames_results(void *userdata, const ne_uri *, const NeonPropFindResultSet *results)
ScXMLEditAttributeMap::Entry const aEntries[]
static int NPFR_propnames_iter(void *userdata, const NeonPropName *pname, const char *, const HttpStatus *)