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/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"
41 using namespace com::sun::star::uno
;
42 using namespace com::sun::star::ucb
;
44 using namespace webdav_ucp
;
49 // strip "DAV:" namespace from XML snippets to avoid
50 // parser error (undeclared namespace) later on.
51 OString
stripDavNamespace( const OString
& in
)
53 const OString
inXML( in
.toAsciiLowerCase() );
57 sal_Int32 end
= inXML
.indexOf( "dav:" );
60 if ( inXML
[ end
- 1 ] == '<' ||
61 inXML
[ end
- 1 ] == '/' )
63 // copy from original buffer - preserve case.
64 buf
.append( in
.copy( start
, end
- start
) );
68 // copy from original buffer - preserve case.
69 buf
.append( in
.copy( start
, end
- start
+ 4 ) );
72 end
= inXML
.indexOf( "dav:", start
);
74 buf
.append( inXML
.copy( start
) );
76 return OString( buf
.makeStringAndClear() );
80 extern "C" int NPFR_propfind_iter( void* userdata
,
81 const NeonPropName
* pname
,
83 const HttpStatus
* status
)
86 HTTP Response Status Classes:
88 - 1: Informational - Request received, continuing process
90 - 2: Success - The action was successfully received,
91 understood, and accepted
93 - 3: Redirection - Further action must be taken in order to
96 - 4: Client Error - The request contains bad syntax or cannot
99 - 5: Server Error - The server failed to fulfill an apparently
103 if ( status
->klass
> 2 )
104 return 0; // Error getting this property. Go on.
106 // Create & set the PropertyValue
107 DAVPropertyValue thePropertyValue
;
108 thePropertyValue
.IsCaseSensitive
= true;
110 OSL_ENSURE( pname
->nspace
, "NPFR_propfind_iter - No namespace!" );
112 DAVProperties::createUCBPropName( pname
->nspace
,
114 thePropertyValue
.Name
);
115 bool bHasValue
= false;
116 if ( DAVProperties::isUCBDeadProperty( *pname
) )
118 // DAV dead property added by WebDAV UCP?
119 if ( UCBDeadPropertyValue::createFromXML(
120 value
, thePropertyValue
.Value
) )
122 OSL_ENSURE( thePropertyValue
.Value
.hasValue(),
123 "NPFR_propfind_iter - No value!" );
130 if ( rtl_str_compareIgnoreAsciiCase(
131 pname
->name
, "resourcetype" ) == 0 )
133 OString
aValue( value
);
134 aValue
= aValue
.trim(); // #107358# remove leading/trailing spaces
135 if ( !aValue
.isEmpty() )
137 aValue
= stripDavNamespace( aValue
).toAsciiLowerCase();
138 if ( aValue
.startsWith("<collection") )
140 thePropertyValue
.Value
141 <<= OUString("collection");
145 if ( !thePropertyValue
.Value
.hasValue() )
147 // Take over the value exactly as supplied by the server.
148 thePropertyValue
.Value
<<= OUString::createFromAscii( value
);
151 else if ( rtl_str_compareIgnoreAsciiCase(
152 pname
->name
, "supportedlock" ) == 0 )
154 Sequence
< LockEntry
> aEntries
;
155 LockEntrySequence::createFromXML(
156 stripDavNamespace( value
), aEntries
);
157 thePropertyValue
.Value
<<= aEntries
;
159 else if ( rtl_str_compareIgnoreAsciiCase(
160 pname
->name
, "lockdiscovery" ) == 0 )
162 Sequence
< Lock
> aLocks
;
163 LockSequence::createFromXML(
164 stripDavNamespace( value
), aLocks
);
165 thePropertyValue
.Value
<<= aLocks
;
167 else if ( rtl_str_compareIgnoreAsciiCase( pname
->name
, "source" ) == 0 )
169 Sequence
< Link
> aLinks
;
170 LinkSequence::createFromXML(
171 stripDavNamespace( value
), aLinks
);
172 thePropertyValue
.Value
<<= aLinks
;
176 thePropertyValue
.Value
177 <<= OStringToOUString( value
, RTL_TEXTENCODING_UTF8
);
181 // Add the newly created PropertyValue
182 DAVResource
* theResource
= static_cast< DAVResource
* >( userdata
);
183 theResource
->properties
.push_back( thePropertyValue
);
188 extern "C" void NPFR_propfind_results( void* userdata
,
190 const NeonPropFindResultSet
* set
)
192 // @@@ href is not the uri! DAVResource ctor wants uri!
194 DAVResource
theResource(
195 OStringToOUString( uri
->path
, RTL_TEXTENCODING_UTF8
) );
197 ne_propset_iterate( set
, NPFR_propfind_iter
, &theResource
);
199 // Add entry to resources list.
200 vector
< DAVResource
> * theResources
201 = static_cast< vector
< DAVResource
> * >( userdata
);
202 theResources
->push_back( theResource
);
205 extern "C" int NPFR_propnames_iter( void* userdata
,
206 const NeonPropName
* pname
,
207 const char* /*value*/,
208 const HttpStatus
* /*status*/ )
211 DAVProperties::createUCBPropName( pname
->nspace
,
215 DAVResourceInfo
* theResource
= static_cast< DAVResourceInfo
* >( userdata
);
216 theResource
->properties
.push_back( aFullName
);
220 extern "C" void NPFR_propnames_results( void* userdata
,
222 const NeonPropFindResultSet
* results
)
224 // @@@ href is not the uri! DAVResourceInfo ctor wants uri!
225 // Create entry for the resource.
226 DAVResourceInfo
theResource(
227 OStringToOUString( uri
->path
, RTL_TEXTENCODING_UTF8
) );
230 ne_propset_iterate( results
, NPFR_propnames_iter
, &theResource
);
232 // Add entry to resources list.
233 vector
< DAVResourceInfo
> * theResources
234 = static_cast< vector
< DAVResourceInfo
> * >( userdata
);
235 theResources
->push_back( theResource
);
238 extern osl::Mutex aGlobalNeonMutex
;
240 NeonPropFindRequest::NeonPropFindRequest( HttpSession
* inSession
,
243 const vector
< OUString
>& inPropNames
,
244 vector
< DAVResource
>& ioResources
,
247 // Generate the list of properties we're looking for
248 int thePropCount
= inPropNames
.size();
249 if ( thePropCount
> 0 )
251 NeonPropName
* thePropNames
= new NeonPropName
[ thePropCount
+ 1 ];
254 for ( theIndex
= 0; theIndex
< thePropCount
; theIndex
++ )
256 // Split fullname into namespace and name!
257 DAVProperties::createNeonPropName(
258 inPropNames
[ theIndex
], thePropNames
[ theIndex
] );
260 thePropNames
[ theIndex
].nspace
= NULL
;
261 thePropNames
[ theIndex
].name
= NULL
;
264 osl::Guard
< osl::Mutex
> theGlobalGuard( aGlobalNeonMutex
);
265 nError
= ne_simple_propfind( inSession
,
269 NPFR_propfind_results
,
273 for ( theIndex
= 0; theIndex
< thePropCount
; theIndex
++ )
274 free( (void *)thePropNames
[ theIndex
].name
);
276 delete [] thePropNames
;
281 osl::Guard
< osl::Mutex
> theGlobalGuard( aGlobalNeonMutex
);
282 nError
= ne_simple_propfind( inSession
,
285 NULL
, // 0 == allprop
286 NPFR_propfind_results
,
290 // #87585# - Sometimes neon lies (because some servers lie).
291 if ( ( nError
== NE_OK
) && ioResources
.empty() )
295 NeonPropFindRequest::NeonPropFindRequest(
296 HttpSession
* inSession
,
299 std::vector
< DAVResourceInfo
> & ioResInfo
,
303 osl::Guard
< osl::Mutex
> theGlobalGuard( aGlobalNeonMutex
);
304 nError
= ne_propnames( inSession
,
307 NPFR_propnames_results
,
311 // #87585# - Sometimes neon lies (because some servers lie).
312 if ( ( nError
== NE_OK
) && ioResInfo
.empty() )
316 NeonPropFindRequest::~NeonPropFindRequest( )
320 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */