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 :
30 : #include "osl/diagnose.h"
31 : #include "rtl/strbuf.hxx"
32 : #include "NeonTypes.hxx"
33 : #include "DAVException.hxx"
34 : #include "DAVProperties.hxx"
35 : #include "NeonPropFindRequest.hxx"
36 : #include "LinkSequence.hxx"
37 : #include "LockSequence.hxx"
38 : #include "LockEntrySequence.hxx"
39 : #include "UCBDeadPropertyValue.hxx"
40 :
41 : using namespace com::sun::star::uno;
42 : using namespace com::sun::star::ucb;
43 : using namespace std;
44 : using namespace webdav_ucp;
45 :
46 : using ::rtl::OUString;
47 : using ::rtl::OString;
48 : using ::rtl::OStringToOUString;
49 :
50 : // -------------------------------------------------------------------
51 : namespace
52 : {
53 : // strip "DAV:" namespace from XML snippets to avoid
54 : // parser error (undeclared namespace) later on.
55 0 : rtl::OString stripDavNamespace( const rtl::OString & in )
56 : {
57 0 : const rtl::OString inXML( in.toAsciiLowerCase() );
58 :
59 0 : rtl::OStringBuffer buf;
60 0 : sal_Int32 start = 0;
61 0 : sal_Int32 end = inXML.indexOf( "dav:" );
62 0 : while ( end != -1 )
63 : {
64 0 : if ( inXML[ end - 1 ] == '<' ||
65 0 : inXML[ end - 1 ] == '/' )
66 : {
67 : // copy from original buffer - preserve case.
68 0 : buf.append( in.copy( start, end - start ) );
69 : }
70 : else
71 : {
72 : // copy from original buffer - preserve case.
73 0 : buf.append( in.copy( start, end - start + 4 ) );
74 : }
75 0 : start = end + 4;
76 0 : end = inXML.indexOf( "dav:", start );
77 : }
78 0 : buf.append( inXML.copy( start ) );
79 :
80 0 : return rtl::OString( buf.makeStringAndClear() );
81 : }
82 : }
83 :
84 : // -------------------------------------------------------------------
85 0 : extern "C" 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 0 : if ( status->klass > 2 )
109 0 : return 0; // Error getting this property. Go on.
110 :
111 : // Create & set the PropertyValue
112 0 : DAVPropertyValue thePropertyValue;
113 0 : thePropertyValue.IsCaseSensitive = true;
114 :
115 : OSL_ENSURE( pname->nspace, "NPFR_propfind_iter - No namespace!" );
116 :
117 : DAVProperties::createUCBPropName( pname->nspace,
118 : pname->name,
119 0 : thePropertyValue.Name );
120 0 : bool bHasValue = false;
121 0 : if ( DAVProperties::isUCBDeadProperty( *pname ) )
122 : {
123 : // DAV dead property added by WebDAV UCP?
124 0 : if ( UCBDeadPropertyValue::createFromXML(
125 0 : value, thePropertyValue.Value ) )
126 : {
127 : OSL_ENSURE( thePropertyValue.Value.hasValue(),
128 : "NPFR_propfind_iter - No value!" );
129 0 : bHasValue = true;
130 : }
131 : }
132 :
133 0 : if ( !bHasValue )
134 : {
135 0 : if ( rtl_str_compareIgnoreAsciiCase(
136 0 : pname->name, "resourcetype" ) == 0 )
137 : {
138 0 : OString aValue( value );
139 0 : aValue = aValue.trim(); // #107358# remove leading/trailing spaces
140 0 : if ( !aValue.isEmpty() )
141 : {
142 0 : aValue = stripDavNamespace( aValue ).toAsciiLowerCase();
143 0 : if ( aValue.compareTo(
144 0 : RTL_CONSTASCII_STRINGPARAM( "<collection" ) ) == 0 )
145 : {
146 : thePropertyValue.Value
147 0 : <<= OUString("collection");
148 : }
149 : }
150 :
151 0 : if ( !thePropertyValue.Value.hasValue() )
152 : {
153 : // Take over the value exactly as supplied by the server.
154 0 : thePropertyValue.Value <<= OUString::createFromAscii( value );
155 0 : }
156 : }
157 0 : else if ( rtl_str_compareIgnoreAsciiCase(
158 0 : pname->name, "supportedlock" ) == 0 )
159 : {
160 0 : Sequence< LockEntry > aEntries;
161 : LockEntrySequence::createFromXML(
162 0 : stripDavNamespace( value ), aEntries );
163 0 : thePropertyValue.Value <<= aEntries;
164 : }
165 0 : else if ( rtl_str_compareIgnoreAsciiCase(
166 0 : pname->name, "lockdiscovery" ) == 0 )
167 : {
168 0 : Sequence< Lock > aLocks;
169 : LockSequence::createFromXML(
170 0 : stripDavNamespace( value ), aLocks );
171 0 : thePropertyValue.Value <<= aLocks;
172 : }
173 0 : else if ( rtl_str_compareIgnoreAsciiCase( pname->name, "source" ) == 0 )
174 : {
175 0 : Sequence< Link > aLinks;
176 : LinkSequence::createFromXML(
177 0 : stripDavNamespace( value ), aLinks );
178 0 : thePropertyValue.Value <<= aLinks;
179 : }
180 : else
181 : {
182 : thePropertyValue.Value
183 0 : <<= OStringToOUString( value, RTL_TEXTENCODING_UTF8 );
184 : }
185 : }
186 :
187 : // Add the newly created PropertyValue
188 0 : DAVResource* theResource = static_cast< DAVResource * >( userdata );
189 0 : theResource->properties.push_back( thePropertyValue );
190 :
191 0 : return 0; // Go on.
192 : }
193 :
194 : // -------------------------------------------------------------------
195 0 : extern "C" void NPFR_propfind_results( void* userdata,
196 : const ne_uri* uri,
197 : const NeonPropFindResultSet* set )
198 : {
199 : // @@@ href is not the uri! DAVResource ctor wants uri!
200 :
201 : DAVResource theResource(
202 0 : OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
203 :
204 0 : ne_propset_iterate( set, NPFR_propfind_iter, &theResource );
205 :
206 : // Add entry to resources list.
207 : vector< DAVResource > * theResources
208 0 : = static_cast< vector< DAVResource > * >( userdata );
209 0 : theResources->push_back( theResource );
210 0 : }
211 : // -------------------------------------------------------------------
212 0 : extern "C" int NPFR_propnames_iter( void* userdata,
213 : const NeonPropName* pname,
214 : const char* /*value*/,
215 : const HttpStatus* /*status*/ )
216 : {
217 0 : OUString aFullName;
218 : DAVProperties::createUCBPropName( pname->nspace,
219 : pname->name,
220 0 : aFullName );
221 :
222 0 : DAVResourceInfo* theResource = static_cast< DAVResourceInfo * >( userdata );
223 0 : theResource->properties.push_back( aFullName );
224 0 : return 0;
225 : }
226 :
227 : // -------------------------------------------------------------------
228 0 : extern "C" void NPFR_propnames_results( void* userdata,
229 : const ne_uri* uri,
230 : const NeonPropFindResultSet* results )
231 : {
232 : // @@@ href is not the uri! DAVResourceInfo ctor wants uri!
233 : // Create entry for the resource.
234 : DAVResourceInfo theResource(
235 0 : OStringToOUString( uri->path, RTL_TEXTENCODING_UTF8 ) );
236 :
237 : // Fill entry.
238 0 : ne_propset_iterate( results, NPFR_propnames_iter, &theResource );
239 :
240 : // Add entry to resources list.
241 : vector< DAVResourceInfo > * theResources
242 0 : = static_cast< vector< DAVResourceInfo > * >( userdata );
243 0 : theResources->push_back( theResource );
244 0 : }
245 :
246 : extern osl::Mutex aGlobalNeonMutex;
247 :
248 : // -------------------------------------------------------------------
249 : // Constructor
250 : // -------------------------------------------------------------------
251 :
252 0 : NeonPropFindRequest::NeonPropFindRequest( HttpSession* inSession,
253 : const char* inPath,
254 : const Depth inDepth,
255 : const vector< OUString >& inPropNames,
256 : vector< DAVResource >& ioResources,
257 : int & nError )
258 : {
259 : // Generate the list of properties we're looking for
260 0 : int thePropCount = inPropNames.size();
261 0 : if ( thePropCount > 0 )
262 : {
263 0 : NeonPropName* thePropNames = new NeonPropName[ thePropCount + 1 ];
264 : int theIndex;
265 :
266 0 : for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
267 : {
268 : // Split fullname into namespace and name!
269 : DAVProperties::createNeonPropName(
270 0 : inPropNames[ theIndex ], thePropNames[ theIndex ] );
271 : }
272 0 : thePropNames[ theIndex ].nspace = NULL;
273 0 : thePropNames[ theIndex ].name = NULL;
274 :
275 : {
276 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
277 : nError = ne_simple_propfind( inSession,
278 : inPath,
279 : inDepth,
280 : thePropNames,
281 : NPFR_propfind_results,
282 0 : &ioResources );
283 : }
284 :
285 0 : for ( theIndex = 0; theIndex < thePropCount; theIndex ++ )
286 0 : free( (void *)thePropNames[ theIndex ].name );
287 :
288 0 : delete [] thePropNames;
289 : }
290 : else
291 : {
292 : // ALLPROP
293 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
294 : nError = ne_simple_propfind( inSession,
295 : inPath,
296 : inDepth,
297 : NULL, // 0 == allprop
298 : NPFR_propfind_results,
299 0 : &ioResources );
300 : }
301 :
302 : // #87585# - Sometimes neon lies (because some servers lie).
303 0 : if ( ( nError == NE_OK ) && ioResources.empty() )
304 0 : nError = NE_ERROR;
305 0 : }
306 :
307 : // -------------------------------------------------------------------
308 : // Constructor
309 : // - obtains property names
310 : // -------------------------------------------------------------------
311 :
312 0 : NeonPropFindRequest::NeonPropFindRequest(
313 : HttpSession* inSession,
314 : const char* inPath,
315 : const Depth inDepth,
316 : std::vector< DAVResourceInfo > & ioResInfo,
317 : int & nError )
318 : {
319 : {
320 0 : osl::Guard< osl::Mutex > theGlobalGuard( aGlobalNeonMutex );
321 : nError = ne_propnames( inSession,
322 : inPath,
323 : inDepth,
324 : NPFR_propnames_results,
325 0 : &ioResInfo );
326 : }
327 :
328 : // #87585# - Sometimes neon lies (because some servers lie).
329 0 : if ( ( nError == NE_OK ) && ioResInfo.empty() )
330 0 : nError = NE_ERROR;
331 0 : }
332 :
333 : // -------------------------------------------------------------------
334 : // Destructor
335 : // -------------------------------------------------------------------
336 0 : NeonPropFindRequest::~NeonPropFindRequest( )
337 : {
338 0 : }
339 :
340 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|