1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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 =============================================================================
38 =============================================================================
39 HTTP (entity header) WebDAV (property) UCB (property)
40 =============================================================================
44 Content-Language getcontentlanguage
45 Content-Length getcontentlength Size
49 Content-Type getcontenttype MediaType
51 Last-Modified getlastmodified DateModified
52 creationdate DateCreated
53 resourcetype IsFolder,IsDocument,ContentType
55 ETag (actually getetag
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.
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!");
85 CurlUri
const aURI( rResource
.uri
);
86 m_aEscapedTitle
= aURI
.GetPathBaseName();
88 (*m_xProps
)[ OUString( "Title" ) ]
90 uno::Any( aURI
.GetPathBaseNameUnescaped() ), true );
92 catch ( DAVException
const & )
94 (*m_xProps
)[ OUString( "Title" ) ]
97 OUString( "*** unknown ***" ) ),
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
160 const uno::Any
& ContentProperties::getValue(
161 const OUString
& rName
) const
163 const PropertyValue
* pProp
= get( rName
);
165 return pProp
->value();
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();
179 it
= std::find_if(m_xProps
->cbegin(), end
,
180 [&rName
](const PropertyValueMap::value_type
& rEntry
) {
181 return rEntry
.first
.equalsIgnoreAsciiCase( rName
);
184 return &(*it
).second
;
189 return &(*it
).second
;
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.
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.
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
) )
251 propertyNames
.push_back(
252 DAVProperties::GETCONTENTTYPE
);
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;
279 propertyNames
.push_back( rProp
.Name
);
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.
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" ) );
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
) )
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
);
358 addProperty( rName
, pProp
->value(), pProp
->isCaseSensitive() );
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
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 ) )
392 // else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) )
395 else if ( rName
== DAVProperties::GETCONTENTLENGTH
)
397 // Map DAV:getcontentlength to UCP:Size
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
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 ) )
434 else if ( rName
== DAVProperties::GETLASTMODIFIED
)
436 // Map the DAV:getlastmodified entity header to UCP:DateModified
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
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 ) )
462 else if ( rName
== DAVProperties::RESOURCETYPE
)
467 // Map DAV:resourcetype to UCP:IsFolder, UCP:IsDocument, UCP:ContentType
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 ) )
485 (*m_xProps
)[ rName
] = PropertyValue( rValue
, bIsCaseSensitive
);
489 // CachableContentProperties Implementation.
494 bool isCachable( std::u16string_view rName
, bool isCaseSensitive
)
496 const OUString aNonCachableProps
[] =
498 DAVProperties::LOCKDISCOVERY
,
500 DAVProperties::GETETAG
,
503 OUString( "DateModified" ),
504 OUString( "Last-Modified" ),
505 DAVProperties::GETLASTMODIFIED
,
508 OUString( "Content-Length" ),
509 DAVProperties::GETCONTENTLENGTH
,
514 for ( sal_uInt32 n
= 0;
515 n
< ( sizeof( aNonCachableProps
)
516 / sizeof( aNonCachableProps
[ 0 ] ) );
519 if ( isCaseSensitive
)
521 if ( rName
== aNonCachableProps
[ n
] )
525 if ( o3tl::equalsIgnoreAsciiCase( rName
, aNonCachableProps
[ n
] ) )
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: */