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