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 
29 using namespace com::sun::star;
30 using namespace http_dav_ucp;
31 
32 /*
33 =============================================================================
34 
35  Property Mapping
36 
37 =============================================================================
38 HTTP (entity header) WebDAV (property) UCB (property)
39 =============================================================================
40 
41 Allow
42 Content-Encoding
43 Content-Language getcontentlanguage
44 Content-Length getcontentlength Size
45 Content-Location
46 Content-MD5
47 Content-Range
48 Content-Type getcontenttype MediaType
49 Expires
50 Last-Modified getlastmodified DateModified
51  creationdate DateCreated
52  resourcetype IsFolder,IsDocument,ContentType
53  displayname
54 ETag (actually getetag
55 a response header )
56  lockdiscovery
57  supportedlock
58  source
59  Title (always taken from URI)
60 
61 =============================================================================
62 
63 Important: 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!
72 uno::Any ContentProperties::m_aEmptyAny;
73 
74 ContentProperties::ContentProperties( const DAVResource& rResource )
75 : m_xProps( new PropertyValueMap ),
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" ) ]
88  = PropertyValue(
89  uno::Any( aURI.GetPathBaseNameUnescaped() ), true );
90  }
91  catch ( DAVException const & )
92  {
93  (*m_xProps)[ OUString( "Title" ) ]
94  = PropertyValue(
95  uno::Any(
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 )
112 : m_xProps( new PropertyValueMap ),
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 
124 ContentProperties::ContentProperties( const OUString & rTitle )
125 : m_xProps( new PropertyValueMap ),
126  m_bTrailingSlash( false )
127 {
128  (*m_xProps)[ OUString( "Title" ) ]
129  = PropertyValue( uno::Any( rTitle ), true );
130 }
131 
132 
134 : m_xProps( new PropertyValueMap ),
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 
150 bool 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 
373 void 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 
491 namespace
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: */
CachableContentProperties(const CachableContentProperties &)
OUString GetPathBaseName() const
Definition: CurlUri.cxx:178
void addProperties(const ContentProperties &rProps)
void addProperty(const OUString &rName, const css::uno::Any &rValue, bool bIsCaseSensitive)
std::unordered_map< OUString, PropertyValue > PropertyValueMap
sal_Int64 n
void addProperties(const std::vector< OUString > &rProps, const ContentProperties &rContentProps)
static constexpr OUStringLiteral GETLASTMODIFIED
static void UCBNamesToDAVNames(const css::uno::Sequence< css::beans::Property > &rProps, std::vector< OUString > &resources)
#define WEBDAV_CONTENT_TYPE
std::unique_ptr< PropertyValueMap > m_xProps
const css::uno::Any & getValue(const OUString &rName) const
static void UCBNamesToHTTPNames(const css::uno::Sequence< css::beans::Property > &rProps, std::vector< OUString > &resources)
int nCount
constexpr OUStringLiteral WEBDAV_COLLECTION_TYPE
static bool convert(const OUString &, css::util::DateTime &)
static constexpr OUStringLiteral RESOURCETYPE
OUString GetPathBaseNameUnescaped() const
Definition: CurlUri.cxx:195
dictionary props
static constexpr OUStringLiteral CREATIONDATE
bool containsAllNames(const css::uno::Sequence< css::beans::Property > &rProps, std::vector< OUString > &rNamesNotContained) const
enumrange< T >::Iterator end(enumrange< T >)
static constexpr OUStringLiteral LOCKDISCOVERY
static constexpr OUStringLiteral GETCONTENTLENGTH
static constexpr OUStringLiteral GETCONTENTTYPE
const PropertyValue * get(const OUString &rName) const
Reference< XPropertySet > m_xProps
std::vector< DAVPropertyValue > properties
Definition: DAVResource.hxx:43
const std::unique_ptr< PropertyValueMap > & getProperties() const
static constexpr OUStringLiteral GETETAG
bool contains(const OUString &rName) const
const css::uno::Any & value() const
bool m_bDetectedRangeSegmentation false