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