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