1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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>
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
45 auto DumpResources(std::vector
<DAVResource
> const& rResources
) -> OUString
48 for (auto const& rResource
: rResources
)
50 buf
.append("resource URL: <" + rResource
.uri
);
52 CurlUri
const uri(rResource
.uri
);
53 buf
.append("> parsed URL: <"
54 + DecodeURI(uri
.GetRelativeReference())
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
+ "\" ");
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
,
83 : m_xContent( rContent
), m_xContext( rxContext
), m_nOpenMode( nOpenMode
),
84 m_bCountFinal( false ), m_bThrowException( false )
90 DataSupplier::~DataSupplier()
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() )
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() )
118 aId
+= props
.getEscapedTitle();
120 if ( props
.isTrailingSlash() )
123 m_Results
[ nIndex
]->aId
= aId
;
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
;
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
;
155 return uno::Reference
< ucb::XContentIdentifier
>();
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
;
176 uno::Reference
< ucb::XContentIdentifier
> xId
177 = queryContentIdentifier( nIndex
);
182 uno::Reference
< ucb::XContent
> xContent
183 = m_xContent
->getProvider()->queryContent( xId
);
184 m_Results
[ nIndex
]->xContent
= xContent
;
188 catch ( ucb::IllegalIdentifierException
& )
192 return uno::Reference
< ucb::XContent
>();
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.
210 if (nIndex
< m_Results
.size())
212 // Result already present.
222 sal_uInt32
DataSupplier::totalCount()
227 return m_Results
.size();
232 sal_uInt32
DataSupplier::currentCount()
234 return m_Results
.size();
239 bool DataSupplier::isCountFinal()
241 return m_bCountFinal
;
246 uno::Reference
< sdbc::XRow
> DataSupplier::queryPropertyValues(
249 osl::Guard
< osl::Mutex
> aGuard( m_aMutex
);
251 if (nIndex
< m_Results
.size())
253 uno::Reference
< sdbc::XRow
> xRow
= m_Results
[ nIndex
]->xRow
;
261 if ( getResult( nIndex
) )
263 uno::Reference
< sdbc::XRow
> xRow
264 = Content::getPropertyValues(
266 getResultSet()->getProperties(),
267 *(m_Results
[ nIndex
]->pData
),
268 m_xContent
->getProvider(),
269 queryContentIdentifierString( nIndex
) );
270 m_Results
[ nIndex
]->xRow
= xRow
;
274 return uno::Reference
< sdbc::XRow
>();
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();
289 void DataSupplier::close()
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
326 m_xContent
->getResourceAccess()
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
)
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
363 CurlUri
const aCurrURI( rRes
.uri
);
364 OUString aCurrPath
= aCurrURI
.GetPath();
365 if ( aCurrPath
.endsWith("/") )
369 aCurrPath
.getLength() - 1 );
371 aCurrPath
= DecodeURI(aCurrPath
);
372 if ( aPath
== aCurrPath
)
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" );
404 case ucb::OpenMode::DOCUMENTS
:
406 bool bDocument
= false;
408 const uno::Any
& rValue
409 = pContentProperties
->getValue( "IsDocument" );
410 rValue
>>= bDocument
;
418 case ucb::OpenMode::ALL
:
424 std::make_unique
<ResultListEntry
>(std::move(pContentProperties
)));
427 catch ( DAVException
const & )
432 m_bCountFinal
= true;
434 // Callback possible, because listeners may be informed!
436 getResultSet()->rowCountFinal();
438 return !m_bThrowException
;
441 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */