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>
35#include <tools/diagnose_ex.h>
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: <");
51 buf.append(rResource.uri);
52 try {
53 CurlUri const uri(rResource.uri);
54 buf.append("> parsed URL: <");
55 buf.append(DecodeURI(uri.GetRelativeReference()));
56 buf.append("> ");
57 } catch (...) {
58 // parsing uri could fail
59 buf.append("> parsing URL failed! ");
60 }
61 buf.append("properties: ");
62 for (auto const& it : rResource.properties)
63 {
64 buf.append("\"");
65 buf.append(it.Name);
66 buf.append("\" ");
67 }
68 buf.append("\n");
69 }
70 buf.stripEnd('\n'); // the last newline is superfluous, remove it
71 return buf.makeStringAndClear();
72}
73
74}
75
76}
77
78
79// DataSupplier Implementation.
80
81
82DataSupplier::DataSupplier(
83 const uno::Reference< uno::XComponentContext >& rxContext,
84 const rtl::Reference< Content >& rContent,
85 sal_Int32 nOpenMode )
86 : m_xContent( rContent ), m_xContext( rxContext ), m_nOpenMode( nOpenMode ),
87 m_bCountFinal( false ), m_bThrowException( false )
88{
89}
90
91
92// virtual
93DataSupplier::~DataSupplier()
94{}
95
96
97// virtual
98OUString DataSupplier::queryContentIdentifierString( sal_uInt32 nIndex )
99{
100 osl::Guard< osl::Mutex > aGuard( m_aMutex );
101
102 if (nIndex < m_Results.size())
103 {
104 OUString aId = m_Results[ nIndex ]->aId;
105 if ( aId.getLength() )
106 {
107 // Already cached.
108 return aId;
109 }
110 }
111
112 if ( getResult( nIndex ) )
113 {
114 OUString aId = m_xContent->getResourceAccess().getURL();
115
117
118 if ( ( aId.lastIndexOf( '/' ) + 1 ) != aId.getLength() )
119 aId += "/";
120
121 aId += props.getEscapedTitle();
122
123 if ( props.isTrailingSlash() )
124 aId += "/";
125
126 m_Results[ nIndex ]->aId = aId;
127 return aId;
128 }
129 return OUString();
130}
131
132
133// virtual
134uno::Reference< ucb::XContentIdentifier >
136{
137 osl::Guard< osl::Mutex > aGuard( m_aMutex );
138
139 if (nIndex < m_Results.size())
140 {
141 uno::Reference< ucb::XContentIdentifier > xId
142 = m_Results[ nIndex ]->xId;
143 if ( xId.is() )
144 {
145 // Already cached.
146 return xId;
147 }
148 }
149
151 if ( aId.getLength() )
152 {
153 uno::Reference< ucb::XContentIdentifier > xId
154 = new ::ucbhelper::ContentIdentifier( aId );
155 m_Results[ nIndex ]->xId = xId;
156 return xId;
157 }
158 return uno::Reference< ucb::XContentIdentifier >();
159}
160
161
162// virtual
163uno::Reference< ucb::XContent >
164DataSupplier::queryContent( sal_uInt32 nIndex )
165{
166 osl::Guard< osl::Mutex > aGuard( m_aMutex );
167
168 if (nIndex < m_Results.size())
169 {
170 uno::Reference< ucb::XContent > xContent
171 = m_Results[ nIndex ]->xContent;
172 if ( xContent.is() )
173 {
174 // Already cached.
175 return xContent;
176 }
177 }
178
179 uno::Reference< ucb::XContentIdentifier > xId
181 if ( xId.is() )
182 {
183 try
184 {
185 uno::Reference< ucb::XContent > xContent
186 = m_xContent->getProvider()->queryContent( xId );
187 m_Results[ nIndex ]->xContent = xContent;
188 return xContent;
189
190 }
191 catch ( ucb::IllegalIdentifierException& )
192 {
193 }
194 }
195 return uno::Reference< ucb::XContent >();
196}
197
198
199// virtual
200bool DataSupplier::getResult( sal_uInt32 nIndex )
201{
202 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
203
204 if (nIndex < m_Results.size())
205 {
206 // Result already present.
207 return true;
208 }
209
210 // Obtain values...
211 if ( getData() )
212 {
213 if (nIndex < m_Results.size())
214 {
215 // Result already present.
216 return true;
217 }
218 }
219
220 return false;
221}
222
223
224// virtual
226{
227 // Obtain values...
228 getData();
229
230 return m_Results.size();
231}
232
233
234// virtual
236{
237 return m_Results.size();
238}
239
240
241// virtual
243{
244 return m_bCountFinal;
245}
246
247
248// virtual
249uno::Reference< sdbc::XRow > DataSupplier::queryPropertyValues(
250 sal_uInt32 nIndex )
251{
252 osl::Guard< osl::Mutex > aGuard( m_aMutex );
253
254 if (nIndex < m_Results.size())
255 {
256 uno::Reference< sdbc::XRow > xRow = m_Results[ nIndex ]->xRow;
257 if ( xRow.is() )
258 {
259 // Already cached.
260 return xRow;
261 }
262 }
263
264 if ( getResult( nIndex ) )
265 {
266 uno::Reference< sdbc::XRow > xRow
269 getResultSet()->getProperties(),
270 *(m_Results[ nIndex ]->pData),
271 m_xContent->getProvider(),
273 m_Results[ nIndex ]->xRow = xRow;
274 return xRow;
275 }
276
277 return uno::Reference< sdbc::XRow >();
278}
279
280
281// virtual
282void DataSupplier::releasePropertyValues( sal_uInt32 nIndex )
283{
284 osl::Guard< osl::Mutex > aGuard( m_aMutex );
285
286 if (nIndex < m_Results.size())
287 m_Results[ nIndex ]->xRow.clear();
288}
289
290
291// virtual
293{
294}
295
296
297// virtual
299{
300 if ( m_bThrowException )
301 throw ucb::ResultSetException();
302}
303
305{
306 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
307
308 if ( !m_bCountFinal )
309 {
310 std::vector< OUString > propertyNames;
312 getResultSet()->getProperties(), propertyNames );
313
314 // Append "resourcetype", if not already present. It's value is
315 // needed to get a valid ContentProperties::pIsFolder value, which
316 // is needed for OpenMode handling.
317
318 bool isNoResourceType = std::none_of(propertyNames.begin(), propertyNames.end(),
319 [](const OUString& rPropName) { return rPropName.equals(DAVProperties::RESOURCETYPE); });
320
321 if ( isNoResourceType )
322 propertyNames.push_back( DAVProperties::RESOURCETYPE );
323
324 std::vector< DAVResource > resources;
325 try
326 {
327 // propfind depth 1, get property values for parent AND for each
328 // child
329 m_xContent->getResourceAccess()
330 .PROPFIND( DAVONE,
331 propertyNames,
332 resources,
334 SAL_INFO("ucb.ucp.webdav", "getData() - " << DumpResources(resources));
335 }
336 catch ( DAVException & )
337 {
338 TOOLS_WARN_EXCEPTION( "ucb.ucp.webdav", "PROPFIND : DAVException" );
339 m_bThrowException = true;
340 }
341
342 if ( !m_bThrowException )
343 {
344 try
345 {
346 CurlUri const aURI(
347 m_xContent->getResourceAccess().getURL() );
348 OUString aPath = aURI.GetPath();
349
350 if ( aPath.endsWith("/") )
351 aPath = aPath.copy( 0, aPath.getLength() - 1 );
352
353 aPath = DecodeURI(aPath);
354 bool bFoundParent = false;
355
356 for ( size_t n = 0; n < resources.size(); ++n )
357 {
358 const DAVResource & rRes = resources[ n ];
359
360 // Filter parent, which is contained somewhere(!) in
361 // the vector.
362 if ( !bFoundParent )
363 {
364 try
365 {
366 CurlUri const aCurrURI( rRes.uri );
367 OUString aCurrPath = aCurrURI.GetPath();
368 if ( aCurrPath.endsWith("/") )
369 aCurrPath
370 = aCurrPath.copy(
371 0,
372 aCurrPath.getLength() - 1 );
373
374 aCurrPath = DecodeURI(aCurrPath);
375 if ( aPath == aCurrPath )
376 {
377 bFoundParent = true;
378 continue;
379 }
380 }
381 catch ( DAVException const & )
382 {
383 // do nothing, ignore error. continue.
384 }
385 }
386
387 std::unique_ptr<ContentProperties> pContentProperties
388 = std::make_unique<ContentProperties>( rRes );
389
390 // Check resource against open mode.
391 switch ( m_nOpenMode )
392 {
393 case ucb::OpenMode::FOLDERS:
394 {
395 bool bFolder = false;
396
397 const uno::Any & rValue
398 = pContentProperties->getValue( "IsFolder" );
399 rValue >>= bFolder;
400
401 if ( !bFolder )
402 continue;
403
404 break;
405 }
406
407 case ucb::OpenMode::DOCUMENTS:
408 {
409 bool bDocument = false;
410
411 const uno::Any & rValue
412 = pContentProperties->getValue( "IsDocument" );
413 rValue >>= bDocument;
414
415 if ( !bDocument )
416 continue;
417
418 break;
419 }
420
421 case ucb::OpenMode::ALL:
422 default:
423 break;
424 }
425
426 m_Results.push_back(
427 std::make_unique<ResultListEntry>(std::move(pContentProperties)));
428 }
429 }
430 catch ( DAVException const & )
431 {
432 }
433 }
434
435 m_bCountFinal = true;
436
437 // Callback possible, because listeners may be informed!
438 aGuard.clear();
439 getResultSet()->rowCountFinal();
440 }
441 return !m_bThrowException;
442}
443
444/* 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
::rtl::Reference< OContentHelper > xContent
Reference< XRow > xRow
Reference< XContentIdentifier > xId
OUString aId
css::uno::Environment getEnvironment(OUString const &name, std::u16string_view implementation)
OUString DecodeURI(OUString const &rURI)
Definition: CurlUri.cxx:297
dictionary props
static constexpr OUStringLiteral RESOURCETYPE