LibreOffice Module ucb (master) 1
webdavdatasupplier.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21#include <sal/log.hxx>
22
23#include <utility>
24
25#include <rtl/ustrbuf.hxx>
26#include <com/sun/star/ucb/OpenMode.hpp>
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>
36
37using namespace com::sun::star;
38using namespace http_dav_ucp;
39
40namespace http_dav_ucp
41{
42
43namespace {
44
45auto DumpResources(std::vector<DAVResource> const& rResources) -> OUString
46{
47 OUStringBuffer buf;
48 for (auto const& rResource : rResources)
49 {
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! ");
59 }
60 buf.append("properties: ");
61 for (auto const& it : rResource.properties)
62 {
63 buf.append("\"" + it.Name + "\" ");
64 }
65 buf.append("\n");
66 }
67 buf.stripEnd('\n'); // the last newline is superfluous, remove it
68 return buf.makeStringAndClear();
69}
70
71}
72
73}
74
75
76// DataSupplier Implementation.
77
78
79DataSupplier::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 )
85{
86}
87
88
89// virtual
90DataSupplier::~DataSupplier()
91{}
92
93
94// virtual
95OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
96{
97 osl::Guard< osl::Mutex > aGuard( m_aMutex );
98
99 if (nIndex < m_Results.size())
100 {
101 OUString aId = m_Results[ nIndex ]->aId;
102 if ( aId.getLength() )
103 {
104 // Already cached.
105 return aId;
106 }
107 }
108
109 if ( getResult( nIndex ) )
110 {
111 OUString aId = m_xContent->getResourceAccess().getURL();
112
114
115 if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
116 aId += "/";
117
118 aId += props.getEscapedTitle();
119
120 if ( props.isTrailingSlash() )
121 aId += "/";
122
123 m_Results[ nIndex ]->aId = aId;
124 return aId;
125 }
126 return OUString();
127}
128
129
130// virtual
131uno::Reference< ucb::XContentIdentifier >
133{
134 osl::Guard< osl::Mutex > aGuard( m_aMutex );
135
136 if (nIndex < m_Results.size())
137 {
138 uno::Reference< ucb::XContentIdentifier > xId
139 = m_Results[ nIndex ]->xId;
140 if ( xId.is() )
141 {
142 // Already cached.
143 return xId;
144 }
145 }
146
147 OUString aId = queryContentIdentifierString( nIndex );
148 if ( aId.getLength() )
149 {
150 uno::Reference< ucb::XContentIdentifier > xId
151 = new ::ucbhelper::ContentIdentifier( aId );
152 m_Results[ nIndex ]->xId = xId;
153 return xId;
154 }
155 return uno::Reference< ucb::XContentIdentifier >();
156}
157
158
159// virtual
160uno::Reference< ucb::XContent >
161DataSupplier::queryContent( sal_uInt32 nIndex )
162{
163 osl::Guard< osl::Mutex > aGuard( m_aMutex );
164
165 if (nIndex < m_Results.size())
166 {
167 uno::Reference< ucb::XContent > xContent
168 = m_Results[ nIndex ]->xContent;
169 if ( xContent.is() )
170 {
171 // Already cached.
172 return xContent;
173 }
174 }
175
176 uno::Reference< ucb::XContentIdentifier > xId
178 if ( xId.is() )
179 {
180 try
181 {
182 uno::Reference< ucb::XContent > xContent
183 = m_xContent->getProvider()->queryContent( xId );
184 m_Results[ nIndex ]->xContent = xContent;
185 return xContent;
186
187 }
188 catch ( ucb::IllegalIdentifierException& )
189 {
190 }
191 }
192 return uno::Reference< ucb::XContent >();
193}
194
195
196// virtual
197bool DataSupplier::getResult( sal_uInt32 nIndex )
198{
199 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
200
201 if (nIndex < m_Results.size())
202 {
203 // Result already present.
204 return true;
205 }
206
207 // Obtain values...
208 if ( getData() )
209 {
210 if (nIndex < m_Results.size())
211 {
212 // Result already present.
213 return true;
214 }
215 }
216
217 return false;
218}
219
220
221// virtual
223{
224 // Obtain values...
225 getData();
226
227 return m_Results.size();
228}
229
230
231// virtual
233{
234 return m_Results.size();
235}
236
237
238// virtual
240{
241 return m_bCountFinal;
242}
243
244
245// virtual
246uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
247 sal_uInt32 nIndex )
248{
249 osl::Guard< osl::Mutex > aGuard( m_aMutex );
250
251 if (nIndex < m_Results.size())
252 {
253 uno::Reference< sdbc::XRow > xRow = m_Results[ nIndex ]->xRow;
254 if ( xRow.is() )
255 {
256 // Already cached.
257 return xRow;
258 }
259 }
260
261 if ( getResult( nIndex ) )
262 {
263 uno::Reference< sdbc::XRow > xRow
266 getResultSet()->getProperties(),
267 *(m_Results[ nIndex ]->pData),
268 m_xContent->getProvider(),
270 m_Results[ nIndex ]->xRow = xRow;
271 return xRow;
272 }
273
274 return uno::Reference< sdbc::XRow >();
275}
276
277
278// virtual
279void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
280{
281 osl::Guard< osl::Mutex > aGuard( m_aMutex );
282
283 if (nIndex < m_Results.size())
284 m_Results[ nIndex ]->xRow.clear();
285}
286
287
288// virtual
290{
291}
292
293
294// virtual
296{
297 if ( m_bThrowException )
298 throw ucb::ResultSetException();
299}
300
302{
303 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
304
305 if ( !m_bCountFinal )
306 {
307 std::vector< OUString > propertyNames;
309 getResultSet()->getProperties(), propertyNames );
310
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.
314
315 bool isNoResourceType = std::none_of(propertyNames.begin(), propertyNames.end(),
316 [](const OUString& rPropName) { return rPropName.equals(DAVProperties::RESOURCETYPE); });
317
318 if ( isNoResourceType )
319 propertyNames.push_back( DAVProperties::RESOURCETYPE );
320
321 std::vector< DAVResource > resources;
322 try
323 {
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,
331 SAL_INFO("ucb.ucp.webdav", "getData() - " << DumpResources(resources));
332 }
333 catch ( DAVException & )
334 {
335 TOOLS_WARN_EXCEPTION( "ucb.ucp.webdav", "PROPFIND : DAVException" );
336 m_bThrowException = true;
337 }
338
339 if ( !m_bThrowException )
340 {
341 try
342 {
343 CurlUri const aURI(
344 m_xContent->getResourceAccess().getURL() );
345 OUString aPath = aURI.GetPath();
346
347 if ( aPath.endsWith("/") )
348 aPath = aPath.copy( 0, aPath.getLength() - 1 );
349
350 aPath = DecodeURI(aPath);
351 bool bFoundParent = false;
352
353 for ( size_t n = 0; n < resources.size(); ++n )
354 {
355 const DAVResource & rRes = resources[ n ];
356
357 // Filter parent, which is contained somewhere(!) in
358 // the vector.
359 if ( !bFoundParent )
360 {
361 try
362 {
363 CurlUri const aCurrURI( rRes.uri );
364 OUString aCurrPath = aCurrURI.GetPath();
365 if ( aCurrPath.endsWith("/") )
366 aCurrPath
367 = aCurrPath.copy(
368 0,
369 aCurrPath.getLength() - 1 );
370
371 aCurrPath = DecodeURI(aCurrPath);
372 if ( aPath == aCurrPath )
373 {
374 bFoundParent = true;
375 continue;
376 }
377 }
378 catch ( DAVException const & )
379 {
380 // do nothing, ignore error. continue.
381 }
382 }
383
384 std::unique_ptr<ContentProperties> pContentProperties
385 = std::make_unique<ContentProperties>( rRes );
386
387 // Check resource against open mode.
388 switch ( m_nOpenMode )
389 {
390 case ucb::OpenMode::FOLDERS:
391 {
392 bool bFolder = false;
393
394 const uno::Any & rValue
395 = pContentProperties->getValue( "IsFolder" );
396 rValue >>= bFolder;
397
398 if ( !bFolder )
399 continue;
400
401 break;
402 }
403
404 case ucb::OpenMode::DOCUMENTS:
405 {
406 bool bDocument = false;
407
408 const uno::Any & rValue
409 = pContentProperties->getValue( "IsDocument" );
410 rValue >>= bDocument;
411
412 if ( !bDocument )
413 continue;
414
415 break;
416 }
417
418 case ucb::OpenMode::ALL:
419 default:
420 break;
421 }
422
423 m_Results.push_back(
424 std::make_unique<ResultListEntry>(std::move(pContentProperties)));
425 }
426 }
427 catch ( DAVException const & )
428 {
429 }
430 }
431
432 m_bCountFinal = true;
433
434 // Callback possible, because listeners may be informed!
435 aGuard.clear();
436 getResultSet()->rowCountFinal();
437 }
438 return !m_bThrowException;
439}
440
441/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
uno::Reference< ucb::XContent > m_xContent
Reference< XComponentContext > m_xContext
static void UCBNamesToDAVNames(const css::uno::Sequence< css::beans::Property > &rProps, std::vector< OUString > &resources)
css::uno::Reference< css::sdbc::XRow > getPropertyValues(const css::uno::Sequence< css::beans::Property > &rProperties, const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
OUString const & GetPath() const
Definition: CurlUri.hxx:72
virtual css::uno::Reference< css::ucb::XContentIdentifier > queryContentIdentifier(sal_uInt32 nIndex) override
virtual css::uno::Reference< css::sdbc::XRow > queryPropertyValues(sal_uInt32 nIndex) override
virtual void validate() override
css::uno::Reference< css::uno::XComponentContext > m_xContext
virtual css::uno::Reference< css::ucb::XContent > queryContent(sal_uInt32 nIndex) override
virtual OUString queryContentIdentifierString(sal_uInt32 nIndex) override
virtual sal_uInt32 currentCount() override
virtual bool isCountFinal() override
virtual sal_uInt32 totalCount() override
virtual bool getResult(sal_uInt32 nIndex) override
virtual void close() override
rtl::Reference< Content > m_xContent
virtual void releasePropertyValues(sal_uInt32 nIndex) override
rtl::Reference< ResultSet > getResultSet() const
#define TOOLS_WARN_EXCEPTION(area, stream)
sal_Int32 nIndex
sal_Int64 n
#define SAL_INFO(area, stream)
std::unique_ptr< sal_Int32[]> pData
css::uno::Environment getEnvironment(OUString const &name, std::u16string_view implementation)
OUString DecodeURI(OUString const &rURI)
Definition: CurlUri.cxx:302
dictionary props
static constexpr OUStringLiteral RESOURCETYPE