1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_webdav.hxx"
26
27 /**************************************************************************
28 TODO
29 **************************************************************************
30
31 *************************************************************************/
32 #include <osl/diagnose.h>
33 #include <com/sun/star/ucb/OpenMode.hpp>
34 #include <ucbhelper/contentidentifier.hxx>
35 #include <ucbhelper/providerhelper.hxx>
36 #include "webdavdatasupplier.hxx"
37 #include "webdavcontent.hxx"
38 #include "ContentProperties.hxx"
39 #ifndef _WEBDAV_SESSION_HXX
40 #include "DAVSession.hxx"
41 #endif
42 #include "CurlUri.hxx"
43
44 using namespace com::sun::star;
45 using namespace http_dav_ucp;
46
47 namespace http_dav_ucp
48 {
49
50 //=========================================================================
51 //
52 // struct ResultListEntry.
53 //
54 //=========================================================================
55
56 struct ResultListEntry
57 {
58 rtl::OUString aId;
59 uno::Reference< ucb::XContentIdentifier > xId;
60 uno::Reference< ucb::XContent > xContent;
61 uno::Reference< sdbc::XRow > xRow;
62 const ContentProperties* pData;
63
ResultListEntryhttp_dav_ucp::ResultListEntry64 ResultListEntry( const ContentProperties* pEntry ) : pData( pEntry ) {};
~ResultListEntryhttp_dav_ucp::ResultListEntry65 ~ResultListEntry() { delete pData; }
66 };
67
68 //=========================================================================
69 //
70 // ResultList.
71 //
72 //=========================================================================
73
74 typedef std::vector< ResultListEntry* > ResultList;
75
76 //=========================================================================
77 //
78 // struct DataSupplier_Impl.
79 //
80 //=========================================================================
81
82 struct DataSupplier_Impl
83 {
84 osl::Mutex m_aMutex;
85 ResultList m_aResults;
86 rtl::Reference< Content > m_xContent;
87 uno::Reference< lang::XMultiServiceFactory > m_xSMgr;
88 sal_Int32 m_nOpenMode;
89 sal_Bool m_bCountFinal;
90 sal_Bool m_bThrowException;
91
DataSupplier_Implhttp_dav_ucp::DataSupplier_Impl92 DataSupplier_Impl(
93 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
94 const rtl::Reference< Content >& rContent,
95 sal_Int32 nOpenMode )
96 : m_xContent( rContent ), m_xSMgr( rxSMgr ), m_nOpenMode( nOpenMode ),
97 m_bCountFinal( sal_False ), m_bThrowException( sal_False ) {}
98 ~DataSupplier_Impl();
99 };
100
101 //=========================================================================
~DataSupplier_Impl()102 DataSupplier_Impl::~DataSupplier_Impl()
103 {
104 ResultList::const_iterator it = m_aResults.begin();
105 ResultList::const_iterator end = m_aResults.end();
106
107 while ( it != end )
108 {
109 delete (*it);
110 it++;
111 }
112 }
113
114 }
115
116 //=========================================================================
117 //=========================================================================
118 //
119 // DataSupplier Implementation.
120 //
121 //=========================================================================
122 //=========================================================================
123
DataSupplier(const uno::Reference<lang::XMultiServiceFactory> & rxSMgr,const rtl::Reference<Content> & rContent,sal_Int32 nOpenMode)124 DataSupplier::DataSupplier(
125 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
126 const rtl::Reference< Content >& rContent,
127 sal_Int32 nOpenMode )
128 : m_pImpl( new DataSupplier_Impl( rxSMgr, rContent, nOpenMode ) )
129 {
130 }
131
132 //=========================================================================
133 // virtual
~DataSupplier()134 DataSupplier::~DataSupplier()
135 {
136 delete m_pImpl;
137 }
138
139 //=========================================================================
140 // virtual
queryContentIdentifierString(sal_uInt32 nIndex)141 rtl::OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
142 {
143 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
144
145 if ( nIndex < m_pImpl->m_aResults.size() )
146 {
147 rtl::OUString aId = m_pImpl->m_aResults[ nIndex ]->aId;
148 if ( aId.getLength() )
149 {
150 // Already cached.
151 return aId;
152 }
153 }
154
155 if ( getResult( nIndex ) )
156 {
157 rtl::OUString aId = m_pImpl->m_xContent->getResourceAccess().getURL();
158
159 const ContentProperties& props
160 = *( m_pImpl->m_aResults[ nIndex ]->pData );
161
162 if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
163 aId += rtl::OUString::createFromAscii( "/" );
164
165 aId += props.getEscapedTitle();
166
167 if ( props.isTrailingSlash() )
168 aId += rtl::OUString::createFromAscii( "/" );
169
170 m_pImpl->m_aResults[ nIndex ]->aId = aId;
171 return aId;
172 }
173 return rtl::OUString();
174 }
175
176 //=========================================================================
177 // virtual
178 uno::Reference< ucb::XContentIdentifier >
queryContentIdentifier(sal_uInt32 nIndex)179 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
180 {
181 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
182
183 if ( nIndex < m_pImpl->m_aResults.size() )
184 {
185 uno::Reference< ucb::XContentIdentifier > xId
186 = m_pImpl->m_aResults[ nIndex ]->xId;
187 if ( xId.is() )
188 {
189 // Already cached.
190 return xId;
191 }
192 }
193
194 rtl::OUString aId = queryContentIdentifierString( nIndex );
195 if ( aId.getLength() )
196 {
197 uno::Reference< ucb::XContentIdentifier > xId
198 = new ::ucbhelper::ContentIdentifier( aId );
199 m_pImpl->m_aResults[ nIndex ]->xId = xId;
200 return xId;
201 }
202 return uno::Reference< ucb::XContentIdentifier >();
203 }
204
205 //=========================================================================
206 // virtual
207 uno::Reference< ucb::XContent >
queryContent(sal_uInt32 nIndex)208 DataSupplier::queryContent( sal_uInt32 nIndex )
209 {
210 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
211
212 if ( nIndex < m_pImpl->m_aResults.size() )
213 {
214 uno::Reference< ucb::XContent > xContent
215 = m_pImpl->m_aResults[ nIndex ]->xContent;
216 if ( xContent.is() )
217 {
218 // Already cached.
219 return xContent;
220 }
221 }
222
223 uno::Reference< ucb::XContentIdentifier > xId
224 = queryContentIdentifier( nIndex );
225 if ( xId.is() )
226 {
227 try
228 {
229 uno::Reference< ucb::XContent > xContent
230 = m_pImpl->m_xContent->getProvider()->queryContent( xId );
231 m_pImpl->m_aResults[ nIndex ]->xContent = xContent;
232 return xContent;
233
234 }
235 catch ( ucb::IllegalIdentifierException& )
236 {
237 }
238 }
239 return uno::Reference< ucb::XContent >();
240 }
241
242 //=========================================================================
243 // virtual
getResult(sal_uInt32 nIndex)244 sal_Bool DataSupplier::getResult( sal_uInt32 nIndex )
245 {
246 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
247
248 if ( m_pImpl->m_aResults.size() > nIndex )
249 {
250 // Result already present.
251 return sal_True;
252 }
253
254 // Obtain values...
255 if ( getData() )
256 {
257 if ( m_pImpl->m_aResults.size() > nIndex )
258 {
259 // Result already present.
260 return sal_True;
261 }
262 }
263
264 return sal_False;
265 }
266
267 //=========================================================================
268 // virtual
totalCount()269 sal_uInt32 DataSupplier::totalCount()
270 {
271 // Obtain values...
272 getData();
273
274 return m_pImpl->m_aResults.size();
275 }
276
277 //=========================================================================
278 // virtual
currentCount()279 sal_uInt32 DataSupplier::currentCount()
280 {
281 return m_pImpl->m_aResults.size();
282 }
283
284 //=========================================================================
285 // virtual
isCountFinal()286 sal_Bool DataSupplier::isCountFinal()
287 {
288 return m_pImpl->m_bCountFinal;
289 }
290
291 //=========================================================================
292 // virtual
queryPropertyValues(sal_uInt32 nIndex)293 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
294 sal_uInt32 nIndex )
295 {
296 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
297
298 if ( nIndex < m_pImpl->m_aResults.size() )
299 {
300 uno::Reference< sdbc::XRow > xRow = m_pImpl->m_aResults[ nIndex ]->xRow;
301 if ( xRow.is() )
302 {
303 // Already cached.
304 return xRow;
305 }
306 }
307
308 if ( getResult( nIndex ) )
309 {
310 uno::Reference< sdbc::XRow > xRow
311 = Content::getPropertyValues(
312 m_pImpl->m_xSMgr,
313 getResultSet()->getProperties(),
314 *(m_pImpl->m_aResults[ nIndex ]->pData),
315 rtl::Reference< ::ucbhelper::ContentProviderImplHelper >(
316 m_pImpl->m_xContent->getProvider().get() ),
317 queryContentIdentifierString( nIndex ) );
318 m_pImpl->m_aResults[ nIndex ]->xRow = xRow;
319 return xRow;
320 }
321
322 return uno::Reference< sdbc::XRow >();
323 }
324
325 //=========================================================================
326 // virtual
releasePropertyValues(sal_uInt32 nIndex)327 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
328 {
329 osl::Guard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
330
331 if ( nIndex < m_pImpl->m_aResults.size() )
332 m_pImpl->m_aResults[ nIndex ]->xRow = uno::Reference< sdbc::XRow >();
333 }
334
335 //=========================================================================
336 // virtual
close()337 void DataSupplier::close()
338 {
339 }
340
341 //=========================================================================
342 // virtual
validate()343 void DataSupplier::validate()
344 {
345 if ( m_pImpl->m_bThrowException )
346 throw ucb::ResultSetException();
347 }
348
349 //=========================================================================
getData()350 sal_Bool DataSupplier::getData()
351 {
352 osl::ClearableGuard< osl::Mutex > aGuard( m_pImpl->m_aMutex );
353
354 if ( !m_pImpl->m_bCountFinal )
355 {
356 std::vector< rtl::OUString > propertyNames;
357 ContentProperties::UCBNamesToDAVNames(
358 getResultSet()->getProperties(), propertyNames );
359
360 // Append "resourcetype", if not already present. It's value is
361 // needed to get a valid ContentProperties::pIsFolder value, which
362 // is needed for OpenMode handling.
363
364 std::vector< rtl::OUString >::const_iterator it
365 = propertyNames.begin();
366 std::vector< rtl::OUString >::const_iterator end
367 = propertyNames.end();
368
369 while ( it != end )
370 {
371 if ( (*it).equals( DAVProperties::RESOURCETYPE ) )
372 break;
373
374 it++;
375 }
376
377 if ( it == end )
378 propertyNames.push_back( DAVProperties::RESOURCETYPE );
379
380 std::vector< DAVResource > resources;
381 try
382 {
383 // propfind depth 1, get property values for parent AND for each
384 // child
385 m_pImpl->m_xContent->getResourceAccess()
386 .PROPFIND( DAVONE,
387 propertyNames,
388 resources,
389 getResultSet()->getEnvironment() );
390 }
391 catch ( DAVException & )
392 {
393 // OSL_ENSURE( sal_False, "PROPFIND : DAVException" );
394 m_pImpl->m_bThrowException = sal_True;
395 }
396
397 if ( !m_pImpl->m_bThrowException )
398 {
399 try
400 {
401 CurlUri aURI(
402 m_pImpl->m_xContent->getResourceAccess().getURL() );
403 rtl::OUString aPath = aURI.GetPath();
404
405 if ( aPath.getStr()[ aPath.getLength() - 1 ]
406 == sal_Unicode( '/' ) )
407 aPath = aPath.copy( 0, aPath.getLength() - 1 );
408
409 aPath = CurlUri::unescape( aPath );
410 bool bFoundParent = false;
411
412 for ( sal_uInt32 n = 0; n < resources.size(); ++n )
413 {
414 const DAVResource & rRes = resources[ n ];
415
416 // Filter parent, which is contained somewhere(!) in
417 // the vector.
418 if ( !bFoundParent )
419 {
420 try
421 {
422 CurlUri aCurrURI( rRes.uri );
423 rtl::OUString aCurrPath = aCurrURI.GetPath();
424 if ( aCurrPath.getStr()[
425 aCurrPath.getLength() - 1 ]
426 == sal_Unicode( '/' ) )
427 aCurrPath
428 = aCurrPath.copy(
429 0,
430 aCurrPath.getLength() - 1 );
431
432 aCurrPath = CurlUri::unescape( aCurrPath );
433 if ( aPath == aCurrPath )
434 {
435 bFoundParent = true;
436 continue;
437 }
438 }
439 catch ( DAVException const & )
440 {
441 // do nothing, ignore error. continue.
442 }
443 }
444
445 ContentProperties* pContentProperties
446 = new ContentProperties( rRes );
447
448 // Check resource against open mode.
449 switch ( m_pImpl->m_nOpenMode )
450 {
451 case ucb::OpenMode::FOLDERS:
452 {
453 sal_Bool bFolder = sal_False;
454
455 const uno::Any & rValue
456 = pContentProperties->getValue(
457 rtl::OUString(
458 RTL_CONSTASCII_USTRINGPARAM(
459 "IsFolder" ) ) );
460 rValue >>= bFolder;
461
462 if ( !bFolder )
463 continue;
464
465 break;
466 }
467
468 case ucb::OpenMode::DOCUMENTS:
469 {
470 sal_Bool bDocument = sal_False;
471
472 const uno::Any & rValue
473 = pContentProperties->getValue(
474 rtl::OUString(
475 RTL_CONSTASCII_USTRINGPARAM(
476 "IsDocument" ) ) );
477 rValue >>= bDocument;
478
479 if ( !bDocument )
480 continue;
481
482 break;
483 }
484
485 case ucb::OpenMode::ALL:
486 default:
487 break;
488 }
489
490 m_pImpl->m_aResults.push_back(
491 new ResultListEntry( pContentProperties ) );
492 }
493 }
494 catch ( DAVException const & )
495 {
496 }
497 }
498
499 m_pImpl->m_bCountFinal = sal_True;
500
501 // Callback possible, because listeners may be informed!
502 aGuard.clear();
503 getResultSet()->rowCountFinal();
504 }
505 return !m_pImpl->m_bThrowException;
506 }
507