Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / ucb / source / ucp / webdav-neon / NeonPropFindRequest.cxx
blobcf03274c59521d46c3bddf410801139105e8a770
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
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.
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).
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.
27 ************************************************************************/
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>
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star::ucb;
45 using namespace std;
46 using namespace webdav_ucp;
49 namespace
51 // strip "DAV:" namespace from XML snippets to avoid
52 // parser error (undeclared namespace) later on.
53 OString stripDavNamespace( const OString & in )
55 const OString inXML( in.toAsciiLowerCase() );
57 OStringBuffer buf;
58 sal_Int32 start = 0;
59 sal_Int32 end = inXML.indexOf( "dav:" );
60 while ( end != -1 )
62 if ( inXML[ end - 1 ] == '<' ||
63 inXML[ end - 1 ] == '/' )
65 // copy from original buffer - preserve case.
66 buf.append( in.copy( start, end - start ) );
68 else
70 // copy from original buffer - preserve case.
71 buf.append( in.copy( start, end - start + 4 ) );
73 start = end + 4;
74 end = inXML.indexOf( "dav:", start );
76 buf.append( inXML.copy( start ) );
78 return buf.makeStringAndClear();
82 extern "C" {
84 static int NPFR_propfind_iter( void* userdata,
85 const NeonPropName* pname,
86 const char* value,
87 const HttpStatus* status )
90 HTTP Response Status Classes:
92 - 1: Informational - Request received, continuing process
94 - 2: Success - The action was successfully received,
95 understood, and accepted
97 - 3: Redirection - Further action must be taken in order to
98 complete the request
100 - 4: Client Error - The request contains bad syntax or cannot
101 be fulfilled
103 - 5: Server Error - The server failed to fulfill an apparently
104 valid request
107 if ( status->klass > 2 )
108 return 0; // Error getting this property. Go on.
110 // Create & set the PropertyValue
111 DAVPropertyValue thePropertyValue;
112 thePropertyValue.IsCaseSensitive = true;
114 SAL_WARN_IF( !pname->nspace, "ucb.ucp.webdav", "NPFR_propfind_iter - No XML namespace!" );
116 DAVProperties::createUCBPropName( pname->nspace,
117 pname->name,
118 thePropertyValue.Name );
119 bool bHasValue = false;
120 if ( DAVProperties::isUCBDeadProperty( *pname ) )
122 // DAV dead property added by WebDAV UCP?
123 if ( UCBDeadPropertyValue::createFromXML(
124 value, thePropertyValue.Value ) )
126 SAL_WARN_IF( !thePropertyValue.Value.hasValue(),
127 "ucb.ucp.webdav", "NPFR_propfind_iter - No value for UCBDeadProperty!" );
128 bHasValue = true;
132 if ( !bHasValue )
134 if ( rtl_str_compareIgnoreAsciiCase(
135 pname->name, "resourcetype" ) == 0 )
137 OString aValue( value );
138 aValue = aValue.trim(); // #107358# remove leading/trailing spaces
139 if ( !aValue.isEmpty() )
141 aValue = stripDavNamespace( aValue ).toAsciiLowerCase();
142 if ( aValue.startsWith("<collection") )
144 thePropertyValue.Value
145 <<= OUString("collection");
149 if ( !thePropertyValue.Value.hasValue() )
151 // Take over the value exactly as supplied by the server.
152 thePropertyValue.Value <<= OUString::createFromAscii( value );
155 else if ( rtl_str_compareIgnoreAsciiCase(
156 pname->name, "supportedlock" ) == 0 )
158 Sequence< LockEntry > aEntries;
159 LockEntrySequence::createFromXML(
160 stripDavNamespace( value ), aEntries );
161 thePropertyValue.Value <<= aEntries;
163 else if ( rtl_str_compareIgnoreAsciiCase(
164 pname->name, "lockdiscovery" ) == 0 )
166 Sequence< Lock > aLocks;
167 LockSequence::createFromXML(
168 stripDavNamespace( value ), aLocks );
169 thePropertyValue.Value <<= aLocks;
171 else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "source" ) == 0 )
173 Sequence< Link > aLinks;
174 LinkSequence::createFromXML(
175 stripDavNamespace( value ), aLinks );
176 thePropertyValue.Value <<= aLinks;
178 else
180 thePropertyValue.Value
181 <<= OStringToOUString( value, RTL_TEXTENCODING_UTF8 );
185 // Add the newly created PropertyValue
186 DAVResource* theResource = static_cast< DAVResource * >( userdata );
187 theResource->properties.push_back( thePropertyValue );
189 return 0; // Go on.
192 static void NPFR_propfind_results( void* userdata,
193 const ne_uri* uri,
194 const NeonPropFindResultSet* set )
196 // @@@ href is not the uri! DAVResource ctor wants uri!
198 DAVResource theResource(
199 OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
201 ne_propset_iterate( set, NPFR_propfind_iter, &theResource );
203 // Add entry to resources list.
204 vector< DAVResource > * theResources
205 = static_cast< vector< DAVResource > * >( userdata );
206 theResources->push_back( theResource );
209 static int NPFR_propnames_iter( void* userdata,
210 const NeonPropName* pname,
211 const char* /*value*/,
212 const HttpStatus* /*status*/ )
214 OUString aFullName;
215 DAVProperties::createUCBPropName( pname->nspace,
216 pname->name,
217 aFullName );
219 DAVResourceInfo* theResource = static_cast< DAVResourceInfo * >( userdata );
220 theResource->properties.push_back( aFullName );
221 return 0;
224 static void NPFR_propnames_results( void* userdata,
225 const ne_uri* /*uri*/,
226 const NeonPropFindResultSet* results )
228 // @@@ href is not the uri! DAVResourceInfo ctor wants uri!
229 // Create entry for the resource.
230 DAVResourceInfo theResource;
232 // Fill entry.
233 ne_propset_iterate( results, NPFR_propnames_iter, &theResource );
235 // Add entry to resources list.
236 vector< DAVResourceInfo > * theResources
237 = static_cast< vector< DAVResourceInfo > * >( userdata );
238 theResources->push_back( theResource );
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 )
250 // Generate the list of properties we're looking for
251 int thePropCount = inPropNames.size();
252 if ( thePropCount > 0 )
254 std::unique_ptr<NeonPropName[]> thePropNames(new NeonPropName[ thePropCount + 1 ]);
255 int theIndex;
257 for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
259 // Split fullname into namespace and name!
260 DAVProperties::createNeonPropName(
261 inPropNames[ theIndex ], thePropNames[ theIndex ] );
263 thePropNames[ theIndex ].nspace = nullptr;
264 thePropNames[ theIndex ].name = nullptr;
267 osl::Guard< osl::Mutex > theGlobalGuard(getGlobalNeonMutex());
268 nError = ne_simple_propfind( inSession,
269 inPath,
270 inDepth,
271 thePropNames.get(),
272 NPFR_propfind_results,
273 &ioResources );
276 for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
277 free( const_cast<char *>(thePropNames[ theIndex ].name) );
279 else
281 // ALLPROP
282 osl::Guard< osl::Mutex > theGlobalGuard(getGlobalNeonMutex());
283 nError = ne_simple_propfind( inSession,
284 inPath,
285 inDepth,
286 nullptr, // 0 == allprop
287 NPFR_propfind_results,
288 &ioResources );
291 // #87585# - Sometimes neon lies (because some servers lie).
292 if ( ( nError == NE_OK ) && ioResources.empty() )
293 nError = NE_ERROR;
296 NeonPropFindRequest::NeonPropFindRequest(
297 HttpSession* inSession,
298 const char* inPath,
299 const Depth inDepth,
300 std::vector< DAVResourceInfo > & ioResInfo,
301 int & nError )
304 osl::Guard< osl::Mutex > theGlobalGuard(getGlobalNeonMutex());
305 nError = ne_propnames( inSession,
306 inPath,
307 inDepth,
308 NPFR_propnames_results,
309 &ioResInfo );
312 // #87585# - Sometimes neon lies (because some servers lie).
313 if ( ( nError == NE_OK ) && ioResInfo.empty() )
314 nError = NE_ERROR;
317 NeonPropFindRequest::~NeonPropFindRequest( )
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */