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