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/mutex.hxx>
31 #include <rtl/strbuf.hxx>
32 #include <sal/log.hxx>
33 #include "NeonSession.hxx"
34 #include "NeonTypes.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"
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 buf
.makeStringAndClear();
84 static int NPFR_propfind_iter( void* userdata
,
85 const NeonPropName
* pname
,
87 const HttpStatus
* status
)
90 HTTP Response Status Classes:
92 - 1: Informational - Request received, continuing process
94 - 2: Success - The action was successfully received,
95 understood, and accepted
97 - 3: Redirection - Further action must be taken in order to
100 - 4: Client Error - The request contains bad syntax or cannot
103 - 5: Server Error - The server failed to fulfill an apparently
107 if ( status
->klass
> 2 )
108 return 0; // Error getting this property. Go on.
110 // Create & set the PropertyValue
111 DAVPropertyValue thePropertyValue
;
112 thePropertyValue
.IsCaseSensitive
= true;
114 SAL_WARN_IF( !pname
->nspace
, "ucb.ucp.webdav", "NPFR_propfind_iter - No XML namespace!" );
116 DAVProperties::createUCBPropName( pname
->nspace
,
118 thePropertyValue
.Name
);
119 bool bHasValue
= false;
120 if ( DAVProperties::isUCBDeadProperty( *pname
) )
122 // DAV dead property added by WebDAV UCP?
123 if ( UCBDeadPropertyValue::createFromXML(
124 value
, thePropertyValue
.Value
) )
126 SAL_WARN_IF( !thePropertyValue
.Value
.hasValue(),
127 "ucb.ucp.webdav", "NPFR_propfind_iter - No value for UCBDeadProperty!" );
134 if ( rtl_str_compareIgnoreAsciiCase(
135 pname
->name
, "resourcetype" ) == 0 )
137 OString
aValue( value
);
138 aValue
= aValue
.trim(); // #107358# remove leading/trailing spaces
139 if ( !aValue
.isEmpty() )
141 aValue
= stripDavNamespace( aValue
).toAsciiLowerCase();
142 if ( aValue
.startsWith("<collection") )
144 thePropertyValue
.Value
145 <<= OUString("collection");
149 if ( !thePropertyValue
.Value
.hasValue() )
151 // Take over the value exactly as supplied by the server.
152 thePropertyValue
.Value
<<= OUString::createFromAscii( value
);
155 else if ( rtl_str_compareIgnoreAsciiCase(
156 pname
->name
, "supportedlock" ) == 0 )
158 Sequence
< LockEntry
> aEntries
;
159 LockEntrySequence::createFromXML(
160 stripDavNamespace( value
), aEntries
);
161 thePropertyValue
.Value
<<= aEntries
;
163 else if ( rtl_str_compareIgnoreAsciiCase(
164 pname
->name
, "lockdiscovery" ) == 0 )
166 Sequence
< Lock
> aLocks
;
167 LockSequence::createFromXML(
168 stripDavNamespace( value
), aLocks
);
169 thePropertyValue
.Value
<<= aLocks
;
171 else if ( rtl_str_compareIgnoreAsciiCase( pname
->name
, "source" ) == 0 )
173 Sequence
< Link
> aLinks
;
174 LinkSequence::createFromXML(
175 stripDavNamespace( value
), aLinks
);
176 thePropertyValue
.Value
<<= aLinks
;
180 thePropertyValue
.Value
181 <<= OStringToOUString( value
, RTL_TEXTENCODING_UTF8
);
185 // Add the newly created PropertyValue
186 DAVResource
* theResource
= static_cast< DAVResource
* >( userdata
);
187 theResource
->properties
.push_back( thePropertyValue
);
192 static void NPFR_propfind_results( void* userdata
,
194 const NeonPropFindResultSet
* set
)
196 // @@@ href is not the uri! DAVResource ctor wants uri!
198 DAVResource
theResource(
199 OStringToOUString( uri
->path
, RTL_TEXTENCODING_UTF8
) );
201 ne_propset_iterate( set
, NPFR_propfind_iter
, &theResource
);
203 // Add entry to resources list.
204 vector
< DAVResource
> * theResources
205 = static_cast< vector
< DAVResource
> * >( userdata
);
206 theResources
->push_back( theResource
);
209 static int NPFR_propnames_iter( void* userdata
,
210 const NeonPropName
* pname
,
211 const char* /*value*/,
212 const HttpStatus
* /*status*/ )
215 DAVProperties::createUCBPropName( pname
->nspace
,
219 DAVResourceInfo
* theResource
= static_cast< DAVResourceInfo
* >( userdata
);
220 theResource
->properties
.push_back( aFullName
);
224 static void NPFR_propnames_results( void* userdata
,
225 const ne_uri
* /*uri*/,
226 const NeonPropFindResultSet
* results
)
228 // @@@ href is not the uri! DAVResourceInfo ctor wants uri!
229 // Create entry for the resource.
230 DAVResourceInfo theResource
;
233 ne_propset_iterate( results
, NPFR_propnames_iter
, &theResource
);
235 // Add entry to resources list.
236 vector
< DAVResourceInfo
> * theResources
237 = static_cast< vector
< DAVResourceInfo
> * >( userdata
);
238 theResources
->push_back( theResource
);
243 NeonPropFindRequest::NeonPropFindRequest( HttpSession
* inSession
,
246 const vector
< OUString
>& inPropNames
,
247 vector
< DAVResource
>& ioResources
,
250 // Generate the list of properties we're looking for
251 int thePropCount
= inPropNames
.size();
252 if ( thePropCount
> 0 )
254 std::unique_ptr
<NeonPropName
[]> thePropNames(new NeonPropName
[ thePropCount
+ 1 ]);
257 for ( theIndex
= 0; theIndex
< thePropCount
; theIndex
++ )
259 // Split fullname into namespace and name!
260 DAVProperties::createNeonPropName(
261 inPropNames
[ theIndex
], thePropNames
[ theIndex
] );
263 thePropNames
[ theIndex
].nspace
= nullptr;
264 thePropNames
[ theIndex
].name
= nullptr;
267 osl::Guard
< osl::Mutex
> theGlobalGuard(getGlobalNeonMutex());
268 nError
= ne_simple_propfind( inSession
,
272 NPFR_propfind_results
,
276 for ( theIndex
= 0; theIndex
< thePropCount
; theIndex
++ )
277 free( const_cast<char *>(thePropNames
[ theIndex
].name
) );
282 osl::Guard
< osl::Mutex
> theGlobalGuard(getGlobalNeonMutex());
283 nError
= ne_simple_propfind( inSession
,
286 nullptr, // 0 == allprop
287 NPFR_propfind_results
,
291 // #87585# - Sometimes neon lies (because some servers lie).
292 if ( ( nError
== NE_OK
) && ioResources
.empty() )
296 NeonPropFindRequest::NeonPropFindRequest(
297 HttpSession
* inSession
,
300 std::vector
< DAVResourceInfo
> & ioResInfo
,
304 osl::Guard
< osl::Mutex
> theGlobalGuard(getGlobalNeonMutex());
305 nError
= ne_propnames( inSession
,
308 NPFR_propnames_results
,
312 // #87585# - Sometimes neon lies (because some servers lie).
313 if ( ( nError
== NE_OK
) && ioResInfo
.empty() )
317 NeonPropFindRequest::~NeonPropFindRequest( )
321 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */