Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / ucb / source / ucp / webdav-curl / ContentProperties.cxx
blobd76c03d7589dc0a487d879c32704fab31c52c243
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 "CurlUri.hxx"
23 #include "DAVResource.hxx"
24 #include "DAVProperties.hxx"
25 #include "DateTimeHelper.hxx"
26 #include "webdavprovider.hxx"
27 #include "ContentProperties.hxx"
28 #include <o3tl/string_view.hxx>
30 using namespace com::sun::star;
31 using namespace http_dav_ucp;
34 =============================================================================
36 Property Mapping
38 =============================================================================
39 HTTP (entity header) WebDAV (property) UCB (property)
40 =============================================================================
42 Allow
43 Content-Encoding
44 Content-Language getcontentlanguage
45 Content-Length getcontentlength Size
46 Content-Location
47 Content-MD5
48 Content-Range
49 Content-Type getcontenttype MediaType
50 Expires
51 Last-Modified getlastmodified DateModified
52 creationdate DateCreated
53 resourcetype IsFolder,IsDocument,ContentType
54 displayname
55 ETag (actually getetag
56 a response header )
57 lockdiscovery
58 supportedlock
59 source
60 Title (always taken from URI)
62 =============================================================================
64 Important: HTTP headers will not be mapped to DAV properties; only to UCB
65 properties. (Content-Length,Content-Type,Last-Modified)
69 // ContentProperties Implementation.
72 // static member!
73 uno::Any ContentProperties::m_aEmptyAny;
75 ContentProperties::ContentProperties( const DAVResource& rResource )
76 : m_xProps( new PropertyValueMap ),
77 m_bTrailingSlash( false )
79 assert(!rResource.uri.isEmpty() &&
80 "ContentProperties ctor - Empty resource URI!");
82 // Title
83 try
85 CurlUri const aURI( rResource.uri );
86 m_aEscapedTitle = aURI.GetPathBaseName();
88 (*m_xProps)[ OUString( "Title" ) ]
89 = PropertyValue(
90 uno::Any( aURI.GetPathBaseNameUnescaped() ), true );
92 catch ( DAVException const & )
94 (*m_xProps)[ OUString( "Title" ) ]
95 = PropertyValue(
96 uno::Any(
97 OUString( "*** unknown ***" ) ),
98 true );
101 for ( const auto& rProp : rResource.properties )
103 addProperty( rProp );
106 if ( rResource.uri.endsWith("/") )
107 m_bTrailingSlash = true;
111 ContentProperties::ContentProperties(
112 const OUString & rTitle, bool bFolder )
113 : m_xProps( new PropertyValueMap ),
114 m_bTrailingSlash( false )
116 (*m_xProps)[ OUString( "Title" ) ]
117 = PropertyValue( uno::Any( rTitle ), true );
118 (*m_xProps)[ OUString( "IsFolder" ) ]
119 = PropertyValue( uno::Any( bFolder ), true );
120 (*m_xProps)[ OUString( "IsDocument" ) ]
121 = PropertyValue( uno::Any( bool( !bFolder ) ), true );
125 ContentProperties::ContentProperties( const OUString & rTitle )
126 : m_xProps( new PropertyValueMap ),
127 m_bTrailingSlash( false )
129 (*m_xProps)[ OUString( "Title" ) ]
130 = PropertyValue( uno::Any( rTitle ), true );
134 ContentProperties::ContentProperties()
135 : m_xProps( new PropertyValueMap ),
136 m_bTrailingSlash( false )
141 ContentProperties::ContentProperties( const ContentProperties & rOther )
142 : m_aEscapedTitle( rOther.m_aEscapedTitle ),
143 m_xProps( rOther.m_xProps
144 ? new PropertyValueMap( *rOther.m_xProps )
145 : new PropertyValueMap ),
146 m_bTrailingSlash( rOther.m_bTrailingSlash )
151 bool ContentProperties::contains( const OUString & rName ) const
153 if ( get( rName ) )
154 return true;
155 else
156 return false;
160 const uno::Any & ContentProperties::getValue(
161 const OUString & rName ) const
163 const PropertyValue * pProp = get( rName );
164 if ( pProp )
165 return pProp->value();
166 else
167 return m_aEmptyAny;
171 const PropertyValue * ContentProperties::get(
172 const OUString & rName ) const
174 PropertyValueMap::const_iterator it = m_xProps->find( rName );
175 const PropertyValueMap::const_iterator end = m_xProps->end();
177 if ( it == end )
179 it = std::find_if(m_xProps->cbegin(), end,
180 [&rName](const PropertyValueMap::value_type& rEntry) {
181 return rEntry.first.equalsIgnoreAsciiCase( rName );
183 if ( it != end )
184 return &(*it).second;
186 return nullptr;
188 else
189 return &(*it).second;
193 // static
194 void ContentProperties::UCBNamesToDAVNames(
195 const uno::Sequence< beans::Property > & rProps,
196 std::vector< OUString > & propertyNames )
199 // Assemble list of DAV properties to obtain from server.
200 // Append DAV properties needed to obtain requested UCB props.
203 // DAV UCB
204 // creationdate <- DateCreated
205 // getlastmodified <- DateModified
206 // getcontenttype <- MediaType
207 // getcontentlength <- Size
208 // resourcetype <- IsFolder, IsDocument, ContentType
209 // (taken from URI) <- Title
211 bool bCreationDate = false;
212 bool bLastModified = false;
213 bool bContentType = false;
214 bool bContentLength = false;
215 bool bResourceType = false;
217 sal_Int32 nCount = rProps.getLength();
218 for ( sal_Int32 n = 0; n < nCount; ++n )
220 const beans::Property & rProp = rProps[ n ];
222 if ( rProp.Name == "Title" )
224 // Title is always obtained from resource's URI.
225 continue;
227 else if ( rProp.Name == "DateCreated" ||
228 ( rProp.Name == DAVProperties::CREATIONDATE ) )
230 if ( !bCreationDate )
232 propertyNames.push_back( DAVProperties::CREATIONDATE );
233 bCreationDate = true;
236 else if ( rProp.Name == "DateModified" ||
237 ( rProp.Name == DAVProperties::GETLASTMODIFIED ) )
239 if ( !bLastModified )
241 propertyNames.push_back(
242 DAVProperties::GETLASTMODIFIED );
243 bLastModified = true;
246 else if ( rProp.Name == "MediaType" ||
247 ( rProp.Name == DAVProperties::GETCONTENTTYPE ) )
249 if ( !bContentType )
251 propertyNames.push_back(
252 DAVProperties::GETCONTENTTYPE );
253 bContentType = true;
256 else if ( rProp.Name == "Size" ||
257 ( rProp.Name == DAVProperties::GETCONTENTLENGTH ) )
259 if ( !bContentLength )
261 propertyNames.push_back(
262 DAVProperties::GETCONTENTLENGTH );
263 bContentLength = true;
266 else if ( rProp.Name == "ContentType" ||
267 rProp.Name == "IsDocument" ||
268 rProp.Name == "IsFolder" ||
269 ( rProp.Name == DAVProperties::RESOURCETYPE ) )
271 if ( !bResourceType )
273 propertyNames.push_back( DAVProperties::RESOURCETYPE );
274 bResourceType = true;
277 else
279 propertyNames.push_back( rProp.Name );
285 // static
286 void ContentProperties::UCBNamesToHTTPNames(
287 const uno::Sequence< beans::Property > & rProps,
288 std::vector< OUString > & propertyNames )
291 // Assemble list of HTTP header names to obtain from server.
292 // Append HTTP headers needed to obtain requested UCB props.
295 // HTTP UCB
296 // Last-Modified <- DateModified
297 // Content-Type <- MediaType
298 // Content-Length <- Size
300 sal_Int32 nCount = rProps.getLength();
301 for ( sal_Int32 n = 0; n < nCount; ++n )
303 const beans::Property & rProp = rProps[ n ];
305 if ( rProp.Name == "DateModified" )
307 propertyNames.push_back( OUString( "Last-Modified" ) );
309 else if ( rProp.Name == "MediaType" )
311 propertyNames.push_back( OUString( "Content-Type" ) );
313 else if ( rProp.Name == "Size" )
315 propertyNames.push_back( OUString( "Content-Length" ) );
317 else
319 propertyNames.push_back( rProp.Name );
325 bool ContentProperties::containsAllNames(
326 const uno::Sequence< beans::Property >& rProps,
327 std::vector< OUString > & rNamesNotContained ) const
329 rNamesNotContained.clear();
331 sal_Int32 nCount = rProps.getLength();
332 for ( sal_Int32 n = 0; n < nCount; ++n )
334 const OUString & rName = rProps[ n ].Name;
335 if ( !contains( rName ) )
337 // Not found.
338 rNamesNotContained.push_back( rName );
342 return ( rNamesNotContained.size() == 0 );
346 void ContentProperties::addProperties(
347 const std::vector< OUString > & rProps,
348 const ContentProperties & rContentProps )
350 for ( const OUString & rName : rProps )
352 if ( !contains( rName ) ) // ignore duplicates
354 const PropertyValue * pProp = rContentProps.get( rName );
355 if ( pProp )
357 // Add it.
358 addProperty( rName, pProp->value(), pProp->isCaseSensitive() );
360 else
362 addProperty( rName, uno::Any(), false );
368 void ContentProperties::addProperty( const DAVPropertyValue & rProp )
370 addProperty( rProp.Name, rProp.Value, rProp.IsCaseSensitive );
374 void ContentProperties::addProperty( const OUString & rName,
375 const css::uno::Any & rValue,
376 bool bIsCaseSensitive )
378 if ( rName == DAVProperties::CREATIONDATE )
380 // Map DAV:creationdate to UCP:DateCreated
381 OUString aValue;
382 rValue >>= aValue;
383 util::DateTime aDate;
384 DateTimeHelper::convert( aValue, aDate );
386 (*m_xProps)[ OUString( "DateCreated" ) ]
387 = PropertyValue( uno::Any( aDate ), true );
389 // else if ( rName.equals( DAVProperties::DISPLAYNAME ) )
390 // {
391 // }
392 // else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) )
393 // {
394 // }
395 else if ( rName == DAVProperties::GETCONTENTLENGTH )
397 // Map DAV:getcontentlength to UCP:Size
398 OUString aValue;
399 rValue >>= aValue;
401 (*m_xProps)[ OUString( "Size" ) ]
402 = PropertyValue( uno::Any( aValue.toInt64() ), true );
404 else if ( rName.equalsIgnoreAsciiCase( "Content-Length" ) )
406 // Do NOT map Content-Length entity header to DAV:getcontentlength!
407 // Only DAV resources have this property.
409 // Map Content-Length entity header to UCP:Size
410 OUString aValue;
411 rValue >>= aValue;
413 (*m_xProps)[ OUString( "Size" ) ]
414 = PropertyValue( uno::Any( aValue.toInt64() ), true );
416 else if ( rName == DAVProperties::GETCONTENTTYPE )
418 // Map DAV:getcontenttype to UCP:MediaType (1:1)
419 (*m_xProps)[ OUString( "MediaType" ) ]
420 = PropertyValue( rValue, true );
422 else if ( rName.equalsIgnoreAsciiCase( "Content-Type" ) )
424 // Do NOT map Content-Type entity header to DAV:getcontenttype!
425 // Only DAV resources have this property.
427 // Map DAV:getcontenttype to UCP:MediaType (1:1)
428 (*m_xProps)[ OUString( "MediaType" ) ]
429 = PropertyValue( rValue, true );
431 // else if ( rName.equals( DAVProperties::GETETAG ) )
432 // {
433 // }
434 else if ( rName == DAVProperties::GETLASTMODIFIED )
436 // Map the DAV:getlastmodified entity header to UCP:DateModified
437 OUString aValue;
438 rValue >>= aValue;
439 util::DateTime aDate;
440 DateTimeHelper::convert( aValue, aDate );
442 (*m_xProps)[ OUString( "DateModified" ) ]
443 = PropertyValue( uno::Any( aDate ), true );
445 else if ( rName.equalsIgnoreAsciiCase( "Last-Modified" ) )
447 // Do not map Last-Modified entity header to DAV:getlastmodified!
448 // Only DAV resources have this property.
450 // Map the Last-Modified entity header to UCP:DateModified
451 OUString aValue;
452 rValue >>= aValue;
453 util::DateTime aDate;
454 DateTimeHelper::convert( aValue, aDate );
456 (*m_xProps)[ OUString( "DateModified" ) ]
457 = PropertyValue( uno::Any( aDate ), true );
459 // else if ( rName.equals( DAVProperties::LOCKDISCOVERY ) )
460 // {
461 // }
462 else if ( rName == DAVProperties::RESOURCETYPE )
464 OUString aValue;
465 rValue >>= aValue;
467 // Map DAV:resourcetype to UCP:IsFolder, UCP:IsDocument, UCP:ContentType
468 bool bFolder =
469 aValue.equalsIgnoreAsciiCase( "collection" );
471 (*m_xProps)[ OUString( "IsFolder" ) ]
472 = PropertyValue( uno::Any( bFolder ), true );
473 (*m_xProps)[ OUString( "IsDocument" ) ]
474 = PropertyValue( uno::Any( bool( !bFolder ) ), true );
475 (*m_xProps)[ OUString( "ContentType" ) ]
476 = PropertyValue( uno::Any( bFolder
477 ? OUString( WEBDAV_COLLECTION_TYPE )
478 : OUString( WEBDAV_CONTENT_TYPE ) ), true );
480 // else if ( rName.equals( DAVProperties::SUPPORTEDLOCK ) )
481 // {
482 // }
484 // Save property.
485 (*m_xProps)[ rName ] = PropertyValue( rValue, bIsCaseSensitive );
489 // CachableContentProperties Implementation.
492 namespace
494 bool isCachable( std::u16string_view rName, bool isCaseSensitive )
496 const OUString aNonCachableProps [] =
498 DAVProperties::LOCKDISCOVERY,
500 DAVProperties::GETETAG,
501 OUString( "ETag" ),
503 OUString( "DateModified" ),
504 OUString( "Last-Modified" ),
505 DAVProperties::GETLASTMODIFIED,
507 OUString( "Size" ),
508 OUString( "Content-Length" ),
509 DAVProperties::GETCONTENTLENGTH,
511 OUString( "Date" )
514 for ( sal_uInt32 n = 0;
515 n < ( sizeof( aNonCachableProps )
516 / sizeof( aNonCachableProps[ 0 ] ) );
517 ++n )
519 if ( isCaseSensitive )
521 if ( rName == aNonCachableProps[ n ] )
522 return false;
524 else
525 if ( o3tl::equalsIgnoreAsciiCase( rName, aNonCachableProps[ n ] ) )
526 return false;
528 return true;
531 } // namespace
534 CachableContentProperties::CachableContentProperties(
535 const ContentProperties & rProps )
537 addProperties( rProps );
541 void CachableContentProperties::addProperties(
542 const ContentProperties & rProps )
544 const std::unique_ptr< PropertyValueMap > & props = rProps.getProperties();
546 for ( const auto& rProp : *props )
548 if ( isCachable( rProp.first, rProp.second.isCaseSensitive() ) )
549 m_aProps.addProperty( rProp.first,
550 rProp.second.value(),
551 rProp.second.isCaseSensitive() );
556 void CachableContentProperties::addProperties(
557 const std::vector< DAVPropertyValue > & rProps )
559 for ( const auto& rProp : rProps )
561 if ( isCachable( rProp.Name, rProp.IsCaseSensitive ) )
562 m_aProps.addProperty( rProp );
566 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */