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