bump product version to 7.2.5.1
[LibreOffice.git] / ucb / source / ucp / webdav / ContentProperties.cxx
blob85406e680972c90e8181843c5e5948cf5204ea2d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <memory>
21 #include <com/sun/star/util/DateTime.hpp>
22 #include "SerfUri.hxx"
23 #include "DAVResource.hxx"
24 #include "DAVProperties.hxx"
25 #include "DateTimeHelper.hxx"
26 #include "webdavprovider.hxx"
27 #include "ContentProperties.hxx"
29 #include <sal/log.hxx>
31 using namespace com::sun::star;
32 using namespace http_dav_ucp;
35 =============================================================================
37 Property Mapping
39 =============================================================================
40 HTTP (entity header) WebDAV (property) UCB (property)
41 =============================================================================
43 Allow
44 Content-Encoding
45 Content-Language getcontentlanguage
46 Content-Length getcontentlength Size
47 Content-Location
48 Content-MD5
49 Content-Range
50 Content-Type getcontenttype MediaType
51 Expires
52 Last-Modified getlastmodified DateModified
53 creationdate DateCreated
54 resourcetype IsFolder,IsDocument,ContentType
55 displayname
56 ETag (actually getetag
57 a response header )
58 lockdiscovery
59 supportedlock
60 source
61 Title (always taken from URI)
63 =============================================================================
65 Important: HTTP headers will not be mapped to DAV properties; only to UCB
66 properties. (Content-Length,Content-Type,Last-Modified)
70 // ContentProperties Implementation.
73 // static member!
74 uno::Any ContentProperties::m_aEmptyAny;
76 ContentProperties::ContentProperties( const DAVResource& rResource )
77 : m_xProps( new PropertyValueMap ),
78 m_bTrailingSlash( false )
80 SAL_WARN_IF( !rResource.uri.getLength(), "ucb.ucp.webdav",
81 "ContentProperties ctor - Empty resource URI!" );
83 // Title
84 try
86 SerfUri aURI( rResource.uri );
87 m_aEscapedTitle = aURI.GetPathBaseName();
89 (*m_xProps)[ OUString( "Title" ) ]
90 = PropertyValue(
91 uno::makeAny( aURI.GetPathBaseNameUnescaped() ), true );
93 catch ( DAVException const & )
95 (*m_xProps)[ OUString( "Title" ) ]
96 = PropertyValue(
97 uno::makeAny(
98 OUString( "*** unknown ***" ) ),
99 true );
102 for ( const auto& rProp : rResource.properties )
104 addProperty( rProp );
107 if ( rResource.uri.endsWith("/") )
108 m_bTrailingSlash = true;
112 ContentProperties::ContentProperties(
113 const OUString & rTitle, bool bFolder )
114 : m_xProps( new PropertyValueMap ),
115 m_bTrailingSlash( false )
117 (*m_xProps)[ OUString( "Title" ) ]
118 = PropertyValue( uno::makeAny( rTitle ), true );
119 (*m_xProps)[ OUString( "IsFolder" ) ]
120 = PropertyValue( uno::makeAny( bFolder ), true );
121 (*m_xProps)[ OUString( "IsDocument" ) ]
122 = PropertyValue( uno::makeAny( bool( !bFolder ) ), true );
126 ContentProperties::ContentProperties( const OUString & rTitle )
127 : m_xProps( new PropertyValueMap ),
128 m_bTrailingSlash( false )
130 (*m_xProps)[ OUString( "Title" ) ]
131 = PropertyValue( uno::makeAny( rTitle ), true );
135 ContentProperties::ContentProperties()
136 : m_xProps( new PropertyValueMap ),
137 m_bTrailingSlash( false )
142 ContentProperties::ContentProperties( const ContentProperties & rOther )
143 : m_aEscapedTitle( rOther.m_aEscapedTitle ),
144 m_xProps( rOther.m_xProps.get()
145 ? new PropertyValueMap( *rOther.m_xProps )
146 : new PropertyValueMap ),
147 m_bTrailingSlash( rOther.m_bTrailingSlash )
152 bool ContentProperties::contains( const OUString & rName ) const
154 if ( get( rName ) )
155 return true;
156 else
157 return false;
161 const uno::Any & ContentProperties::getValue(
162 const OUString & rName ) const
164 const PropertyValue * pProp = get( rName );
165 if ( pProp )
166 return pProp->value();
167 else
168 return m_aEmptyAny;
172 const PropertyValue * ContentProperties::get(
173 const OUString & rName ) const
175 PropertyValueMap::const_iterator it = m_xProps->find( rName );
176 const PropertyValueMap::const_iterator end = m_xProps->end();
178 if ( it == end )
180 it = std::find_if(m_xProps->cbegin(), end,
181 [&rName](const PropertyValueMap::value_type& rEntry) {
182 return rEntry.first.equalsIgnoreAsciiCase( rName );
184 if ( it != end )
185 return &(*it).second;
187 return nullptr;
189 else
190 return &(*it).second;
194 // static
195 void ContentProperties::UCBNamesToDAVNames(
196 const uno::Sequence< beans::Property > & rProps,
197 std::vector< OUString > & propertyNames,
198 bool bIncludeUnmatched /* = true */ )
201 // Assemble list of DAV properties to obtain from server.
202 // Append DAV properties needed to obtain requested UCB props.
205 // DAV UCB
206 // creationdate <- DateCreated
207 // getlastmodified <- DateModified
208 // getcontenttype <- MediaType
209 // getcontentlength <- Size
210 // resourcetype <- IsFolder, IsDocument, ContentType
211 // (taken from URI) <- Title
213 bool bCreationDate = false;
214 bool bLastModified = false;
215 bool bContentType = false;
216 bool bContentLength = false;
217 bool bResourceType = false;
219 sal_Int32 nCount = rProps.getLength();
220 for ( sal_Int32 n = 0; n < nCount; ++n )
222 const beans::Property & rProp = rProps[ n ];
224 if ( rProp.Name == "Title" )
226 // Title is always obtained from resource's URI.
227 continue;
229 else if ( rProp.Name == "DateCreated" ||
230 ( rProp.Name == DAVProperties::CREATIONDATE ) )
232 if ( !bCreationDate )
234 propertyNames.push_back( DAVProperties::CREATIONDATE );
235 bCreationDate = true;
238 else if ( rProp.Name == "DateModified" ||
239 ( rProp.Name == DAVProperties::GETLASTMODIFIED ) )
241 if ( !bLastModified )
243 propertyNames.push_back(
244 DAVProperties::GETLASTMODIFIED );
245 bLastModified = true;
248 else if ( rProp.Name == "MediaType" ||
249 ( rProp.Name == DAVProperties::GETCONTENTTYPE ) )
251 if ( !bContentType )
253 propertyNames.push_back(
254 DAVProperties::GETCONTENTTYPE );
255 bContentType = true;
258 else if ( rProp.Name == "Size" ||
259 ( rProp.Name == DAVProperties::GETCONTENTLENGTH ) )
261 if ( !bContentLength )
263 propertyNames.push_back(
264 DAVProperties::GETCONTENTLENGTH );
265 bContentLength = true;
268 else if ( rProp.Name == "ContentType" ||
269 rProp.Name == "IsDocument" ||
270 rProp.Name == "IsFolder" ||
271 ( rProp.Name == DAVProperties::RESOURCETYPE ) )
273 if ( !bResourceType )
275 propertyNames.push_back( DAVProperties::RESOURCETYPE );
276 bResourceType = true;
279 else
281 if ( bIncludeUnmatched )
282 propertyNames.push_back( rProp.Name );
288 // static
289 void ContentProperties::UCBNamesToHTTPNames(
290 const uno::Sequence< beans::Property > & rProps,
291 std::vector< OUString > & propertyNames,
292 bool bIncludeUnmatched /* = true */ )
295 // Assemble list of HTTP header names to obtain from server.
296 // Append HTTP headers needed to obtain requested UCB props.
299 // HTTP UCB
300 // Last-Modified <- DateModified
301 // Content-Type <- MediaType
302 // Content-Length <- Size
304 sal_Int32 nCount = rProps.getLength();
305 for ( sal_Int32 n = 0; n < nCount; ++n )
307 const beans::Property & rProp = rProps[ n ];
309 if ( rProp.Name == "DateModified" )
311 propertyNames.push_back( OUString( "Last-Modified" ) );
313 else if ( rProp.Name == "MediaType" )
315 propertyNames.push_back( OUString( "Content-Type" ) );
317 else if ( rProp.Name == "Size" )
319 propertyNames.push_back( OUString( "Content-Length" ) );
321 else
323 if ( bIncludeUnmatched )
324 propertyNames.push_back( rProp.Name );
330 bool ContentProperties::containsAllNames(
331 const uno::Sequence< beans::Property >& rProps,
332 std::vector< OUString > & rNamesNotContained ) const
334 rNamesNotContained.clear();
336 sal_Int32 nCount = rProps.getLength();
337 for ( sal_Int32 n = 0; n < nCount; ++n )
339 const OUString & rName = rProps[ n ].Name;
340 if ( !contains( rName ) )
342 // Not found.
343 rNamesNotContained.push_back( rName );
347 return ( rNamesNotContained.size() == 0 );
351 void ContentProperties::addProperties(
352 const std::vector< OUString > & rProps,
353 const ContentProperties & rContentProps )
355 for ( const OUString & rName : rProps )
357 if ( !contains( rName ) ) // ignore duplicates
359 const PropertyValue * pProp = rContentProps.get( rName );
360 if ( pProp )
362 // Add it.
363 addProperty( rName, pProp->value(), pProp->isCaseSensitive() );
365 else
367 addProperty( rName, uno::Any(), false );
374 void ContentProperties::addProperties( const ContentProperties & rProps )
376 for ( const auto& rProp : *rProps.m_xProps )
378 addProperty(
379 rProp.first, rProp.second.value(), rProp.second.isCaseSensitive() );
384 void ContentProperties::addProperties(
385 const std::vector< DAVPropertyValue > & rProps )
387 for ( const auto& rProp : rProps )
389 addProperty( rProp );
394 void ContentProperties::addProperty( const DAVPropertyValue & rProp )
396 addProperty( rProp.Name, rProp.Value, rProp.IsCaseSensitive );
400 void ContentProperties::addProperty( const OUString & rName,
401 const css::uno::Any & rValue,
402 bool bIsCaseSensitive )
404 if ( rName == DAVProperties::CREATIONDATE )
406 // Map DAV:creationdate to UCP:DateCreated
407 OUString aValue;
408 rValue >>= aValue;
409 util::DateTime aDate;
410 DateTimeHelper::convert( aValue, aDate );
412 (*m_xProps)[ OUString( "DateCreated" ) ]
413 = PropertyValue( uno::makeAny( aDate ), true );
415 // else if ( rName.equals( DAVProperties::DISPLAYNAME ) )
416 // {
417 // }
418 // else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) )
419 // {
420 // }
421 else if ( rName == DAVProperties::GETCONTENTLENGTH )
423 // Map DAV:getcontentlength to UCP:Size
424 OUString aValue;
425 rValue >>= aValue;
427 (*m_xProps)[ OUString( "Size" ) ]
428 = PropertyValue( uno::makeAny( aValue.toInt64() ), true );
430 else if ( rName == "Content-Length" )
432 // Do NOT map Content-Length entity header to DAV:getcontentlength!
433 // Only DAV resources have this property.
435 // Map Content-Length entity header to UCP:Size
436 OUString aValue;
437 rValue >>= aValue;
439 (*m_xProps)[ OUString( "Size" ) ]
440 = PropertyValue( uno::makeAny( aValue.toInt64() ), true );
442 else if ( rName == DAVProperties::GETCONTENTTYPE )
444 // Map DAV:getcontenttype to UCP:MediaType (1:1)
445 (*m_xProps)[ OUString( "MediaType" ) ]
446 = PropertyValue( rValue, true );
448 else if ( rName == "Content-Type" )
450 // Do NOT map Content-Type entity header to DAV:getcontenttype!
451 // Only DAV resources have this property.
453 // Map DAV:getcontenttype to UCP:MediaType (1:1)
454 (*m_xProps)[ OUString( "MediaType" ) ]
455 = PropertyValue( rValue, true );
457 // else if ( rName.equals( DAVProperties::GETETAG ) )
458 // {
459 // }
460 else if ( rName == DAVProperties::GETLASTMODIFIED )
462 // Map the DAV:getlastmodified entity header to UCP:DateModified
463 OUString aValue;
464 rValue >>= aValue;
465 util::DateTime aDate;
466 DateTimeHelper::convert( aValue, aDate );
468 (*m_xProps)[ OUString( "DateModified" ) ]
469 = PropertyValue( uno::makeAny( aDate ), true );
471 else if ( rName == "Last-Modified" )
473 // Do not map Last-Modified entity header to DAV:getlastmodified!
474 // Only DAV resources have this property.
476 // Map the Last-Modified entity header to UCP:DateModified
477 OUString aValue;
478 rValue >>= aValue;
479 util::DateTime aDate;
480 DateTimeHelper::convert( aValue, aDate );
482 (*m_xProps)[ OUString( "DateModified" ) ]
483 = PropertyValue( uno::makeAny( aDate ), true );
485 // else if ( rName.equals( DAVProperties::LOCKDISCOVERY ) )
486 // {
487 // }
488 else if ( rName == DAVProperties::RESOURCETYPE )
490 OUString aValue;
491 rValue >>= aValue;
493 // Map DAV:resourcetype to UCP:IsFolder, UCP:IsDocument, UCP:ContentType
494 bool bFolder =
495 aValue.equalsIgnoreAsciiCase( "collection" );
497 (*m_xProps)[ OUString( "IsFolder" ) ]
498 = PropertyValue( uno::makeAny( bFolder ), true );
499 (*m_xProps)[ OUString( "IsDocument" ) ]
500 = PropertyValue( uno::makeAny( bool( !bFolder ) ), true );
501 (*m_xProps)[ OUString( "ContentType" ) ]
502 = PropertyValue( uno::makeAny( bFolder
503 ? OUString( WEBDAV_COLLECTION_TYPE )
504 : OUString( WEBDAV_CONTENT_TYPE ) ), true );
506 // else if ( rName.equals( DAVProperties::SUPPORTEDLOCK ) )
507 // {
508 // }
510 // Save property.
511 (*m_xProps)[ rName ] = PropertyValue( rValue, bIsCaseSensitive );
515 // CachableContentProperties Implementation.
518 namespace
520 bool isCachable( OUString const & rName,
521 bool isCaseSensitive )
523 const OUString aNonCachableProps [] =
525 DAVProperties::LOCKDISCOVERY,
527 DAVProperties::GETETAG,
528 OUString( "ETag" ),
530 OUString( "DateModified" ),
531 OUString( "Last-Modified" ),
532 DAVProperties::GETLASTMODIFIED,
534 OUString( "Size" ),
535 OUString( "Content-Length" ),
536 DAVProperties::GETCONTENTLENGTH,
538 OUString( "Date" )
541 for ( sal_uInt32 n = 0;
542 n < ( sizeof( aNonCachableProps )
543 / sizeof( aNonCachableProps[ 0 ] ) );
544 ++n )
546 if ( isCaseSensitive )
548 if ( rName.equals( aNonCachableProps[ n ] ) )
549 return false;
551 else
552 if ( rName.equalsIgnoreAsciiCase( aNonCachableProps[ n ] ) )
553 return false;
555 return true;
558 } // namespace
561 CachableContentProperties::CachableContentProperties(
562 const ContentProperties & rProps )
564 addProperties( rProps );
568 void CachableContentProperties::addProperties(
569 const ContentProperties & rProps )
571 const std::unique_ptr< PropertyValueMap > & props = rProps.getProperties();
573 for ( const auto& rProp : *props )
575 if ( isCachable( rProp.first, rProp.second.isCaseSensitive() ) )
576 m_aProps.addProperty( rProp.first,
577 rProp.second.value(),
578 rProp.second.isCaseSensitive() );
583 void CachableContentProperties::addProperties(
584 const std::vector< DAVPropertyValue > & rProps )
586 for ( const auto& rProp : rProps )
588 if ( isCachable( rProp.Name, rProp.IsCaseSensitive ) )
589 m_aProps.addProperty( rProp );
593 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */