LibreOffice Module ucb (master) 1
ContentProperties.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 <memory>
21#include <com/sun/star/util/DateTime.hpp>
22#include "CurlUri.hxx"
23#include "DAVResource.hxx"
24#include "DAVProperties.hxx"
25#include "DateTimeHelper.hxx"
26#include "webdavprovider.hxx"
27#include "ContentProperties.hxx"
28
29using namespace com::sun::star;
30using namespace http_dav_ucp;
31
32/*
33=============================================================================
34
35 Property Mapping
36
37=============================================================================
38HTTP (entity header) WebDAV (property) UCB (property)
39=============================================================================
40
41Allow
42Content-Encoding
43Content-Language getcontentlanguage
44Content-Length getcontentlength Size
45Content-Location
46Content-MD5
47Content-Range
48Content-Type getcontenttype MediaType
49Expires
50Last-Modified getlastmodified DateModified
51 creationdate DateCreated
52 resourcetype IsFolder,IsDocument,ContentType
53 displayname
54ETag (actually getetag
55a response header )
56 lockdiscovery
57 supportedlock
58 source
59 Title (always taken from URI)
60
61=============================================================================
62
63Important: HTTP headers will not be mapped to DAV properties; only to UCB
64 properties. (Content-Length,Content-Type,Last-Modified)
65*/
66
67
68// ContentProperties Implementation.
69
70
71// static member!
72uno::Any ContentProperties::m_aEmptyAny;
73
74ContentProperties::ContentProperties( const DAVResource& rResource )
76 m_bTrailingSlash( false )
77{
78 assert(!rResource.uri.isEmpty() &&
79 "ContentProperties ctor - Empty resource URI!");
80
81 // Title
82 try
83 {
84 CurlUri const aURI( rResource.uri );
86
87 (*m_xProps)[ OUString( "Title" ) ]
89 uno::Any( aURI.GetPathBaseNameUnescaped() ), true );
90 }
91 catch ( DAVException const & )
92 {
93 (*m_xProps)[ OUString( "Title" ) ]
96 OUString( "*** unknown ***" ) ),
97 true );
98 }
99
100 for ( const auto& rProp : rResource.properties )
101 {
102 addProperty( rProp );
103 }
104
105 if ( rResource.uri.endsWith("/") )
106 m_bTrailingSlash = true;
107}
108
109
111 const OUString & rTitle, bool bFolder )
113 m_bTrailingSlash( false )
114{
115 (*m_xProps)[ OUString( "Title" ) ]
116 = PropertyValue( uno::Any( rTitle ), true );
117 (*m_xProps)[ OUString( "IsFolder" ) ]
118 = PropertyValue( uno::Any( bFolder ), true );
119 (*m_xProps)[ OUString( "IsDocument" ) ]
120 = PropertyValue( uno::Any( bool( !bFolder ) ), true );
121}
122
123
124ContentProperties::ContentProperties( const OUString & rTitle )
126 m_bTrailingSlash( false )
127{
128 (*m_xProps)[ OUString( "Title" ) ]
129 = PropertyValue( uno::Any( rTitle ), true );
130}
131
132
135 m_bTrailingSlash( false )
136{
137}
138
139
141: m_aEscapedTitle( rOther.m_aEscapedTitle ),
142 m_xProps( rOther.m_xProps
143 ? new PropertyValueMap( *rOther.m_xProps )
144 : new PropertyValueMap ),
145 m_bTrailingSlash( rOther.m_bTrailingSlash )
146{
147}
148
149
150bool ContentProperties::contains( const OUString & rName ) const
151{
152 if ( get( rName ) )
153 return true;
154 else
155 return false;
156}
157
158
160 const OUString & rName ) const
161{
162 const PropertyValue * pProp = get( rName );
163 if ( pProp )
164 return pProp->value();
165 else
166 return m_aEmptyAny;
167}
168
169
171 const OUString & rName ) const
172{
173 PropertyValueMap::const_iterator it = m_xProps->find( rName );
174 const PropertyValueMap::const_iterator end = m_xProps->end();
175
176 if ( it == end )
177 {
178 it = std::find_if(m_xProps->cbegin(), end,
179 [&rName](const PropertyValueMap::value_type& rEntry) {
180 return rEntry.first.equalsIgnoreAsciiCase( rName );
181 });
182 if ( it != end )
183 return &(*it).second;
184
185 return nullptr;
186 }
187 else
188 return &(*it).second;
189}
190
191
192// static
194 const uno::Sequence< beans::Property > & rProps,
195 std::vector< OUString > & propertyNames )
196{
197
198 // Assemble list of DAV properties to obtain from server.
199 // Append DAV properties needed to obtain requested UCB props.
200
201
202 // DAV UCB
203 // creationdate <- DateCreated
204 // getlastmodified <- DateModified
205 // getcontenttype <- MediaType
206 // getcontentlength <- Size
207 // resourcetype <- IsFolder, IsDocument, ContentType
208 // (taken from URI) <- Title
209
210 bool bCreationDate = false;
211 bool bLastModified = false;
212 bool bContentType = false;
213 bool bContentLength = false;
214 bool bResourceType = false;
215
216 sal_Int32 nCount = rProps.getLength();
217 for ( sal_Int32 n = 0; n < nCount; ++n )
218 {
219 const beans::Property & rProp = rProps[ n ];
220
221 if ( rProp.Name == "Title" )
222 {
223 // Title is always obtained from resource's URI.
224 continue;
225 }
226 else if ( rProp.Name == "DateCreated" ||
227 ( rProp.Name == DAVProperties::CREATIONDATE ) )
228 {
229 if ( !bCreationDate )
230 {
231 propertyNames.push_back( DAVProperties::CREATIONDATE );
232 bCreationDate = true;
233 }
234 }
235 else if ( rProp.Name == "DateModified" ||
236 ( rProp.Name == DAVProperties::GETLASTMODIFIED ) )
237 {
238 if ( !bLastModified )
239 {
240 propertyNames.push_back(
242 bLastModified = true;
243 }
244 }
245 else if ( rProp.Name == "MediaType" ||
246 ( rProp.Name == DAVProperties::GETCONTENTTYPE ) )
247 {
248 if ( !bContentType )
249 {
250 propertyNames.push_back(
252 bContentType = true;
253 }
254 }
255 else if ( rProp.Name == "Size" ||
256 ( rProp.Name == DAVProperties::GETCONTENTLENGTH ) )
257 {
258 if ( !bContentLength )
259 {
260 propertyNames.push_back(
262 bContentLength = true;
263 }
264 }
265 else if ( rProp.Name == "ContentType" ||
266 rProp.Name == "IsDocument" ||
267 rProp.Name == "IsFolder" ||
268 ( rProp.Name == DAVProperties::RESOURCETYPE ) )
269 {
270 if ( !bResourceType )
271 {
272 propertyNames.push_back( DAVProperties::RESOURCETYPE );
273 bResourceType = true;
274 }
275 }
276 else
277 {
278 propertyNames.push_back( rProp.Name );
279 }
280 }
281}
282
283
284// static
286 const uno::Sequence< beans::Property > & rProps,
287 std::vector< OUString > & propertyNames )
288{
289
290 // Assemble list of HTTP header names to obtain from server.
291 // Append HTTP headers needed to obtain requested UCB props.
292
293
294 // HTTP UCB
295 // Last-Modified <- DateModified
296 // Content-Type <- MediaType
297 // Content-Length <- Size
298
299 sal_Int32 nCount = rProps.getLength();
300 for ( sal_Int32 n = 0; n < nCount; ++n )
301 {
302 const beans::Property & rProp = rProps[ n ];
303
304 if ( rProp.Name == "DateModified" )
305 {
306 propertyNames.push_back( OUString( "Last-Modified" ) );
307 }
308 else if ( rProp.Name == "MediaType" )
309 {
310 propertyNames.push_back( OUString( "Content-Type" ) );
311 }
312 else if ( rProp.Name == "Size" )
313 {
314 propertyNames.push_back( OUString( "Content-Length" ) );
315 }
316 else
317 {
318 propertyNames.push_back( rProp.Name );
319 }
320 }
321}
322
323
325 const uno::Sequence< beans::Property >& rProps,
326 std::vector< OUString > & rNamesNotContained ) const
327{
328 rNamesNotContained.clear();
329
330 sal_Int32 nCount = rProps.getLength();
331 for ( sal_Int32 n = 0; n < nCount; ++n )
332 {
333 const OUString & rName = rProps[ n ].Name;
334 if ( !contains( rName ) )
335 {
336 // Not found.
337 rNamesNotContained.push_back( rName );
338 }
339 }
340
341 return ( rNamesNotContained.size() == 0 );
342}
343
344
346 const std::vector< OUString > & rProps,
347 const ContentProperties & rContentProps )
348{
349 for ( const OUString & rName : rProps )
350 {
351 if ( !contains( rName ) ) // ignore duplicates
352 {
353 const PropertyValue * pProp = rContentProps.get( rName );
354 if ( pProp )
355 {
356 // Add it.
357 addProperty( rName, pProp->value(), pProp->isCaseSensitive() );
358 }
359 else
360 {
361 addProperty( rName, uno::Any(), false );
362 }
363 }
364 }
365}
366
368{
369 addProperty( rProp.Name, rProp.Value, rProp.IsCaseSensitive );
370}
371
372
373void ContentProperties::addProperty( const OUString & rName,
374 const css::uno::Any & rValue,
375 bool bIsCaseSensitive )
376{
377 if ( rName == DAVProperties::CREATIONDATE )
378 {
379 // Map DAV:creationdate to UCP:DateCreated
380 OUString aValue;
381 rValue >>= aValue;
382 util::DateTime aDate;
383 DateTimeHelper::convert( aValue, aDate );
384
385 (*m_xProps)[ OUString( "DateCreated" ) ]
386 = PropertyValue( uno::Any( aDate ), true );
387 }
388 // else if ( rName.equals( DAVProperties::DISPLAYNAME ) )
389 // {
390 // }
391 // else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) )
392 // {
393 // }
394 else if ( rName == DAVProperties::GETCONTENTLENGTH )
395 {
396 // Map DAV:getcontentlength to UCP:Size
397 OUString aValue;
398 rValue >>= aValue;
399
400 (*m_xProps)[ OUString( "Size" ) ]
401 = PropertyValue( uno::Any( aValue.toInt64() ), true );
402 }
403 else if ( rName.equalsIgnoreAsciiCase( "Content-Length" ) )
404 {
405 // Do NOT map Content-Length entity header to DAV:getcontentlength!
406 // Only DAV resources have this property.
407
408 // Map Content-Length entity header to UCP:Size
409 OUString aValue;
410 rValue >>= aValue;
411
412 (*m_xProps)[ OUString( "Size" ) ]
413 = PropertyValue( uno::Any( aValue.toInt64() ), true );
414 }
415 else if ( rName == DAVProperties::GETCONTENTTYPE )
416 {
417 // Map DAV:getcontenttype to UCP:MediaType (1:1)
418 (*m_xProps)[ OUString( "MediaType" ) ]
419 = PropertyValue( rValue, true );
420 }
421 else if ( rName.equalsIgnoreAsciiCase( "Content-Type" ) )
422 {
423 // Do NOT map Content-Type entity header to DAV:getcontenttype!
424 // Only DAV resources have this property.
425
426 // Map DAV:getcontenttype to UCP:MediaType (1:1)
427 (*m_xProps)[ OUString( "MediaType" ) ]
428 = PropertyValue( rValue, true );
429 }
430 // else if ( rName.equals( DAVProperties::GETETAG ) )
431 // {
432 // }
433 else if ( rName == DAVProperties::GETLASTMODIFIED )
434 {
435 // Map the DAV:getlastmodified entity header to UCP:DateModified
436 OUString aValue;
437 rValue >>= aValue;
438 util::DateTime aDate;
439 DateTimeHelper::convert( aValue, aDate );
440
441 (*m_xProps)[ OUString( "DateModified" ) ]
442 = PropertyValue( uno::Any( aDate ), true );
443 }
444 else if ( rName.equalsIgnoreAsciiCase( "Last-Modified" ) )
445 {
446 // Do not map Last-Modified entity header to DAV:getlastmodified!
447 // Only DAV resources have this property.
448
449 // Map the Last-Modified entity header to UCP:DateModified
450 OUString aValue;
451 rValue >>= aValue;
452 util::DateTime aDate;
453 DateTimeHelper::convert( aValue, aDate );
454
455 (*m_xProps)[ OUString( "DateModified" ) ]
456 = PropertyValue( uno::Any( aDate ), true );
457 }
458 // else if ( rName.equals( DAVProperties::LOCKDISCOVERY ) )
459 // {
460 // }
461 else if ( rName == DAVProperties::RESOURCETYPE )
462 {
463 OUString aValue;
464 rValue >>= aValue;
465
466 // Map DAV:resourcetype to UCP:IsFolder, UCP:IsDocument, UCP:ContentType
467 bool bFolder =
468 aValue.equalsIgnoreAsciiCase( "collection" );
469
470 (*m_xProps)[ OUString( "IsFolder" ) ]
471 = PropertyValue( uno::Any( bFolder ), true );
472 (*m_xProps)[ OUString( "IsDocument" ) ]
473 = PropertyValue( uno::Any( bool( !bFolder ) ), true );
474 (*m_xProps)[ OUString( "ContentType" ) ]
475 = PropertyValue( uno::Any( bFolder
476 ? OUString( WEBDAV_COLLECTION_TYPE )
477 : OUString( WEBDAV_CONTENT_TYPE ) ), true );
478 }
479 // else if ( rName.equals( DAVProperties::SUPPORTEDLOCK ) )
480 // {
481 // }
482
483 // Save property.
484 (*m_xProps)[ rName ] = PropertyValue( rValue, bIsCaseSensitive );
485}
486
487
488// CachableContentProperties Implementation.
489
490
491namespace
492{
493 bool isCachable( OUString const & rName,
494 bool isCaseSensitive )
495 {
496 const OUString aNonCachableProps [] =
497 {
499
501 OUString( "ETag" ),
502
503 OUString( "DateModified" ),
504 OUString( "Last-Modified" ),
506
507 OUString( "Size" ),
508 OUString( "Content-Length" ),
510
511 OUString( "Date" )
512 };
513
514 for ( sal_uInt32 n = 0;
515 n < ( sizeof( aNonCachableProps )
516 / sizeof( aNonCachableProps[ 0 ] ) );
517 ++n )
518 {
519 if ( isCaseSensitive )
520 {
521 if ( rName.equals( aNonCachableProps[ n ] ) )
522 return false;
523 }
524 else
525 if ( rName.equalsIgnoreAsciiCase( aNonCachableProps[ n ] ) )
526 return false;
527 }
528 return true;
529 }
530
531} // namespace
532
533
535 const ContentProperties & rProps )
536{
537 addProperties( rProps );
538}
539
540
542 const ContentProperties & rProps )
543{
544 const std::unique_ptr< PropertyValueMap > & props = rProps.getProperties();
545
546 for ( const auto& rProp : *props )
547 {
548 if ( isCachable( rProp.first, rProp.second.isCaseSensitive() ) )
549 m_aProps.addProperty( rProp.first,
550 rProp.second.value(),
551 rProp.second.isCaseSensitive() );
552 }
553}
554
555
557 const std::vector< DAVPropertyValue > & rProps )
558{
559 for ( const auto& rProp : rProps )
560 {
561 if ( isCachable( rProp.Name, rProp.IsCaseSensitive ) )
562 m_aProps.addProperty( rProp );
563 }
564}
565
566/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< XPropertySet > m_xProps
CachableContentProperties(const CachableContentProperties &)
void addProperties(const ContentProperties &rProps)
void addProperty(const OUString &rName, const css::uno::Any &rValue, bool bIsCaseSensitive)
bool contains(const OUString &rName) const
const std::unique_ptr< PropertyValueMap > & getProperties() const
const PropertyValue * get(const OUString &rName) const
void addProperties(const std::vector< OUString > &rProps, const ContentProperties &rContentProps)
std::unique_ptr< PropertyValueMap > m_xProps
bool containsAllNames(const css::uno::Sequence< css::beans::Property > &rProps, std::vector< OUString > &rNamesNotContained) const
static void UCBNamesToDAVNames(const css::uno::Sequence< css::beans::Property > &rProps, std::vector< OUString > &resources)
const css::uno::Any & getValue(const OUString &rName) const
static void UCBNamesToHTTPNames(const css::uno::Sequence< css::beans::Property > &rProps, std::vector< OUString > &resources)
OUString GetPathBaseName() const
Definition: CurlUri.cxx:178
OUString GetPathBaseNameUnescaped() const
Definition: CurlUri.cxx:195
static bool convert(const OUString &, css::util::DateTime &)
const css::uno::Any & value() const
int nCount
sal_Int64 n
std::unordered_map< OUString, PropertyValue > PropertyValueMap
constexpr OUStringLiteral WEBDAV_COLLECTION_TYPE
end
dictionary props
static constexpr OUStringLiteral GETCONTENTTYPE
static constexpr OUStringLiteral CREATIONDATE
static constexpr OUStringLiteral GETETAG
static constexpr OUStringLiteral LOCKDISCOVERY
static constexpr OUStringLiteral RESOURCETYPE
static constexpr OUStringLiteral GETCONTENTLENGTH
static constexpr OUStringLiteral GETLASTMODIFIED
std::vector< DAVPropertyValue > properties
Definition: DAVResource.hxx:43
#define WEBDAV_CONTENT_TYPE