Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / ucb / source / ucp / webdav-curl / webdavdatasupplier.cxx
blob4b7f7786eb8bdac901027db75a66596024d00d55
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <utility>
25 #include <rtl/ustrbuf.hxx>
26 #include <com/sun/star/ucb/OpenMode.hpp>
27 #include <ucbhelper/contentidentifier.hxx>
28 #include <ucbhelper/providerhelper.hxx>
29 #include "webdavdatasupplier.hxx"
30 #include "webdavcontent.hxx"
31 #include "DAVProperties.hxx"
32 #include "CurlUri.hxx"
33 #include <com/sun/star/ucb/IllegalIdentifierException.hpp>
34 #include <com/sun/star/ucb/ResultSetException.hpp>
35 #include <comphelper/diagnose_ex.hxx>
37 using namespace com::sun::star;
38 using namespace http_dav_ucp;
40 namespace http_dav_ucp
43 namespace {
45 auto DumpResources(std::vector<DAVResource> const& rResources) -> OUString
47 OUStringBuffer buf;
48 for (auto const& rResource : rResources)
50 buf.append("resource URL: <" + rResource.uri);
51 try {
52 CurlUri const uri(rResource.uri);
53 buf.append("> parsed URL: <"
54 + DecodeURI(uri.GetRelativeReference())
55 + "> ");
56 } catch (...) {
57 // parsing uri could fail
58 buf.append("> parsing URL failed! ");
60 buf.append("properties: ");
61 for (auto const& it : rResource.properties)
63 buf.append("\"" + it.Name + "\" ");
65 buf.append("\n");
67 buf.stripEnd('\n'); // the last newline is superfluous, remove it
68 return buf.makeStringAndClear();
76 // DataSupplier Implementation.
79 DataSupplier::DataSupplier(
80 const uno::Reference< uno::XComponentContext >& rxContext,
81 const rtl::Reference< Content >& rContent,
82 sal_Int32 nOpenMode )
83 : m_xContent( rContent ), m_xContext( rxContext ), m_nOpenMode( nOpenMode ),
84 m_bCountFinal( false ), m_bThrowException( false )
89 // virtual
90 DataSupplier::~DataSupplier()
94 // virtual
95 OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
97 osl::Guard< osl::Mutex > aGuard( m_aMutex );
99 if (nIndex < m_Results.size())
101 OUString aId = m_Results[ nIndex ]->aId;
102 if ( aId.getLength() )
104 // Already cached.
105 return aId;
109 if ( getResult( nIndex ) )
111 OUString aId = m_xContent->getResourceAccess().getURL();
113 const ContentProperties& props(*(m_Results[ nIndex ]->pData));
115 if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
116 aId += "/";
118 aId += props.getEscapedTitle();
120 if ( props.isTrailingSlash() )
121 aId += "/";
123 m_Results[ nIndex ]->aId = aId;
124 return aId;
126 return OUString();
130 // virtual
131 uno::Reference< ucb::XContentIdentifier >
132 DataSupplier::queryContentIdentifier( sal_uInt32 nIndex )
134 osl::Guard< osl::Mutex > aGuard( m_aMutex );
136 if (nIndex < m_Results.size())
138 uno::Reference< ucb::XContentIdentifier > xId
139 = m_Results[ nIndex ]->xId;
140 if ( xId.is() )
142 // Already cached.
143 return xId;
147 OUString aId = queryContentIdentifierString( nIndex );
148 if ( aId.getLength() )
150 uno::Reference< ucb::XContentIdentifier > xId
151 = new ::ucbhelper::ContentIdentifier( aId );
152 m_Results[ nIndex ]->xId = xId;
153 return xId;
155 return uno::Reference< ucb::XContentIdentifier >();
159 // virtual
160 uno::Reference< ucb::XContent >
161 DataSupplier::queryContent( sal_uInt32 nIndex )
163 osl::Guard< osl::Mutex > aGuard( m_aMutex );
165 if (nIndex < m_Results.size())
167 uno::Reference< ucb::XContent > xContent
168 = m_Results[ nIndex ]->xContent;
169 if ( xContent.is() )
171 // Already cached.
172 return xContent;
176 uno::Reference< ucb::XContentIdentifier > xId
177 = queryContentIdentifier( nIndex );
178 if ( xId.is() )
182 uno::Reference< ucb::XContent > xContent
183 = m_xContent->getProvider()->queryContent( xId );
184 m_Results[ nIndex ]->xContent = xContent;
185 return xContent;
188 catch ( ucb::IllegalIdentifierException& )
192 return uno::Reference< ucb::XContent >();
196 // virtual
197 bool DataSupplier::getResult( sal_uInt32 nIndex )
199 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
201 if (nIndex < m_Results.size())
203 // Result already present.
204 return true;
207 // Obtain values...
208 if ( getData() )
210 if (nIndex < m_Results.size())
212 // Result already present.
213 return true;
217 return false;
221 // virtual
222 sal_uInt32 DataSupplier::totalCount()
224 // Obtain values...
225 getData();
227 return m_Results.size();
231 // virtual
232 sal_uInt32 DataSupplier::currentCount()
234 return m_Results.size();
238 // virtual
239 bool DataSupplier::isCountFinal()
241 return m_bCountFinal;
245 // virtual
246 uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
247 sal_uInt32 nIndex )
249 osl::Guard< osl::Mutex > aGuard( m_aMutex );
251 if (nIndex < m_Results.size())
253 uno::Reference< sdbc::XRow > xRow = m_Results[ nIndex ]->xRow;
254 if ( xRow.is() )
256 // Already cached.
257 return xRow;
261 if ( getResult( nIndex ) )
263 uno::Reference< sdbc::XRow > xRow
264 = Content::getPropertyValues(
265 m_xContext,
266 getResultSet()->getProperties(),
267 *(m_Results[ nIndex ]->pData),
268 m_xContent->getProvider(),
269 queryContentIdentifierString( nIndex ) );
270 m_Results[ nIndex ]->xRow = xRow;
271 return xRow;
274 return uno::Reference< sdbc::XRow >();
278 // virtual
279 void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
281 osl::Guard< osl::Mutex > aGuard( m_aMutex );
283 if (nIndex < m_Results.size())
284 m_Results[ nIndex ]->xRow.clear();
288 // virtual
289 void DataSupplier::close()
294 // virtual
295 void DataSupplier::validate()
297 if ( m_bThrowException )
298 throw ucb::ResultSetException();
301 bool DataSupplier::getData()
303 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
305 if ( !m_bCountFinal )
307 std::vector< OUString > propertyNames;
308 ContentProperties::UCBNamesToDAVNames(
309 getResultSet()->getProperties(), propertyNames );
311 // Append "resourcetype", if not already present. It's value is
312 // needed to get a valid ContentProperties::pIsFolder value, which
313 // is needed for OpenMode handling.
315 bool isNoResourceType = std::none_of(propertyNames.begin(), propertyNames.end(),
316 [](const OUString& rPropName) { return rPropName.equals(DAVProperties::RESOURCETYPE); });
318 if ( isNoResourceType )
319 propertyNames.push_back( DAVProperties::RESOURCETYPE );
321 std::vector< DAVResource > resources;
324 // propfind depth 1, get property values for parent AND for each
325 // child
326 m_xContent->getResourceAccess()
327 .PROPFIND( DAVONE,
328 propertyNames,
329 resources,
330 getResultSet()->getEnvironment() );
331 SAL_INFO("ucb.ucp.webdav", "getData() - " << DumpResources(resources));
333 catch ( DAVException & )
335 TOOLS_WARN_EXCEPTION( "ucb.ucp.webdav", "PROPFIND : DAVException" );
336 m_bThrowException = true;
339 if ( !m_bThrowException )
343 CurlUri const aURI(
344 m_xContent->getResourceAccess().getURL() );
345 OUString aPath = aURI.GetPath();
347 if ( aPath.endsWith("/") )
348 aPath = aPath.copy( 0, aPath.getLength() - 1 );
350 aPath = DecodeURI(aPath);
351 bool bFoundParent = false;
353 for ( size_t n = 0; n < resources.size(); ++n )
355 const DAVResource & rRes = resources[ n ];
357 // Filter parent, which is contained somewhere(!) in
358 // the vector.
359 if ( !bFoundParent )
363 CurlUri const aCurrURI( rRes.uri );
364 OUString aCurrPath = aCurrURI.GetPath();
365 if ( aCurrPath.endsWith("/") )
366 aCurrPath
367 = aCurrPath.copy(
369 aCurrPath.getLength() - 1 );
371 aCurrPath = DecodeURI(aCurrPath);
372 if ( aPath == aCurrPath )
374 bFoundParent = true;
375 continue;
378 catch ( DAVException const & )
380 // do nothing, ignore error. continue.
384 std::unique_ptr<ContentProperties> pContentProperties
385 = std::make_unique<ContentProperties>( rRes );
387 // Check resource against open mode.
388 switch ( m_nOpenMode )
390 case ucb::OpenMode::FOLDERS:
392 bool bFolder = false;
394 const uno::Any & rValue
395 = pContentProperties->getValue( "IsFolder" );
396 rValue >>= bFolder;
398 if ( !bFolder )
399 continue;
401 break;
404 case ucb::OpenMode::DOCUMENTS:
406 bool bDocument = false;
408 const uno::Any & rValue
409 = pContentProperties->getValue( "IsDocument" );
410 rValue >>= bDocument;
412 if ( !bDocument )
413 continue;
415 break;
418 case ucb::OpenMode::ALL:
419 default:
420 break;
423 m_Results.push_back(
424 std::make_unique<ResultListEntry>(std::move(pContentProperties)));
427 catch ( DAVException const & )
432 m_bCountFinal = true;
434 // Callback possible, because listeners may be informed!
435 aGuard.clear();
436 getResultSet()->rowCountFinal();
438 return !m_bThrowException;
441 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */