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 <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>
43 using namespace com::sun::star::uno
;
44 using namespace com::sun::star::ucb
;
46 using namespace webdav_ucp
;
51 // strip "DAV:" namespace from XML snippets to avoid
52 // parser error (undeclared namespace) later on.
53 OString
stripDavNamespace( const OString
& in
)
55 const OString
inXML( in
.toAsciiLowerCase() );
59 sal_Int32 end
= inXML
.indexOf( "dav:" );
62 if ( inXML
[ end
- 1 ] == '<' ||
63 inXML
[ end
- 1 ] == '/' )
65 // copy from original buffer - preserve case.
66 buf
.append( in
.copy( start
, end
- start
) );
70 // copy from original buffer - preserve case.
71 buf
.append( in
.copy( start
, end
- start
+ 4 ) );
74 end
= inXML
.indexOf( "dav:", start
);
76 buf
.append( inXML
.copy( start
) );
78 return OString( buf
.makeStringAndClear() );
82 extern "C" int NPFR_propfind_iter( void* userdata
,
83 const NeonPropName
* pname
,
85 const HttpStatus
* status
)
88 HTTP Response Status Classes:
90 - 1: Informational - Request received, continuing process
92 - 2: Success - The action was successfully received,
93 understood, and accepted
95 - 3: Redirection - Further action must be taken in order to
98 - 4: Client Error - The request contains bad syntax or cannot
101 - 5: Server Error - The server failed to fulfill an apparently
105 if ( status
->klass
> 2 )
106 return 0; // Error getting this property. Go on.
108 // Create & set the PropertyValue
109 DAVPropertyValue thePropertyValue
;
110 thePropertyValue
.IsCaseSensitive
= true;
112 OSL_ENSURE( pname
->nspace
, "NPFR_propfind_iter - No namespace!" );
114 DAVProperties::createUCBPropName( pname
->nspace
,
116 thePropertyValue
.Name
);
117 bool bHasValue
= false;
118 if ( DAVProperties::isUCBDeadProperty( *pname
) )
120 // DAV dead property added by WebDAV UCP?
121 if ( UCBDeadPropertyValue::createFromXML(
122 value
, thePropertyValue
.Value
) )
124 OSL_ENSURE( thePropertyValue
.Value
.hasValue(),
125 "NPFR_propfind_iter - No value!" );
132 if ( rtl_str_compareIgnoreAsciiCase(
133 pname
->name
, "resourcetype" ) == 0 )
135 OString
aValue( value
);
136 aValue
= aValue
.trim(); // #107358# remove leading/trailing spaces
137 if ( !aValue
.isEmpty() )
139 aValue
= stripDavNamespace( aValue
).toAsciiLowerCase();
140 if ( aValue
.startsWith("<collection") )
142 thePropertyValue
.Value
143 <<= OUString("collection");
147 if ( !thePropertyValue
.Value
.hasValue() )
149 // Take over the value exactly as supplied by the server.
150 thePropertyValue
.Value
<<= OUString::createFromAscii( value
);
153 else if ( rtl_str_compareIgnoreAsciiCase(
154 pname
->name
, "supportedlock" ) == 0 )
156 Sequence
< LockEntry
> aEntries
;
157 LockEntrySequence::createFromXML(
158 stripDavNamespace( value
), aEntries
);
159 thePropertyValue
.Value
<<= aEntries
;
161 else if ( rtl_str_compareIgnoreAsciiCase(
162 pname
->name
, "lockdiscovery" ) == 0 )
164 Sequence
< Lock
> aLocks
;
165 LockSequence::createFromXML(
166 stripDavNamespace( value
), aLocks
);
167 thePropertyValue
.Value
<<= aLocks
;
169 else if ( rtl_str_compareIgnoreAsciiCase( pname
->name
, "source" ) == 0 )
171 Sequence
< Link
> aLinks
;
172 LinkSequence::createFromXML(
173 stripDavNamespace( value
), aLinks
);
174 thePropertyValue
.Value
<<= aLinks
;
178 thePropertyValue
.Value
179 <<= OStringToOUString( value
, RTL_TEXTENCODING_UTF8
);
183 // Add the newly created PropertyValue
184 DAVResource
* theResource
= static_cast< DAVResource
* >( userdata
);
185 theResource
->properties
.push_back( thePropertyValue
);
190 extern "C" void NPFR_propfind_results( void* userdata
,
192 const NeonPropFindResultSet
* set
)
194 // @@@ href is not the uri! DAVResource ctor wants uri!
196 DAVResource
theResource(
197 OStringToOUString( uri
->path
, RTL_TEXTENCODING_UTF8
) );
199 ne_propset_iterate( set
, NPFR_propfind_iter
, &theResource
);
201 // Add entry to resources list.
202 vector
< DAVResource
> * theResources
203 = static_cast< vector
< DAVResource
> * >( userdata
);
204 theResources
->push_back( theResource
);
207 extern "C" int NPFR_propnames_iter( void* userdata
,
208 const NeonPropName
* pname
,
209 const char* /*value*/,
210 const HttpStatus
* /*status*/ )
213 DAVProperties::createUCBPropName( pname
->nspace
,
217 DAVResourceInfo
* theResource
= static_cast< DAVResourceInfo
* >( userdata
);
218 theResource
->properties
.push_back( aFullName
);
222 extern "C" void NPFR_propnames_results( void* userdata
,
224 const NeonPropFindResultSet
* results
)
226 // @@@ href is not the uri! DAVResourceInfo ctor wants uri!
227 // Create entry for the resource.
228 DAVResourceInfo
theResource(
229 OStringToOUString( uri
->path
, RTL_TEXTENCODING_UTF8
) );
232 ne_propset_iterate( results
, NPFR_propnames_iter
, &theResource
);
234 // Add entry to resources list.
235 vector
< DAVResourceInfo
> * theResources
236 = static_cast< vector
< DAVResourceInfo
> * >( userdata
);
237 theResources
->push_back( theResource
);
240 extern osl::Mutex aGlobalNeonMutex
;
242 NeonPropFindRequest::NeonPropFindRequest( HttpSession
* inSession
,
245 const vector
< OUString
>& inPropNames
,
246 vector
< DAVResource
>& ioResources
,
249 // Generate the list of properties we're looking for
250 int thePropCount
= inPropNames
.size();
251 if ( thePropCount
> 0 )
253 boost::scoped_array
<NeonPropName
> thePropNames(new NeonPropName
[ thePropCount
+ 1 ]);
256 for ( theIndex
= 0; theIndex
< thePropCount
; theIndex
++ )
258 // Split fullname into namespace and name!
259 DAVProperties::createNeonPropName(
260 inPropNames
[ theIndex
], thePropNames
[ theIndex
] );
262 thePropNames
[ theIndex
].nspace
= NULL
;
263 thePropNames
[ theIndex
].name
= NULL
;
266 osl::Guard
< osl::Mutex
> theGlobalGuard( aGlobalNeonMutex
);
267 nError
= ne_simple_propfind( inSession
,
271 NPFR_propfind_results
,
275 for ( theIndex
= 0; theIndex
< thePropCount
; theIndex
++ )
276 free( (void *)thePropNames
[ theIndex
].name
);
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: */