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 "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 =============================================================================
39 =============================================================================
40 HTTP (entity header) WebDAV (property) UCB (property)
41 =============================================================================
45 Content-Language getcontentlanguage
46 Content-Length getcontentlength Size
50 Content-Type getcontenttype MediaType
52 Last-Modified getlastmodified DateModified
53 creationdate DateCreated
54 resourcetype IsFolder,IsDocument,ContentType
56 ETag (actually getetag
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.
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!" );
86 SerfUri
aURI( rResource
.uri
);
87 m_aEscapedTitle
= aURI
.GetPathBaseName();
89 (*m_xProps
)[ OUString( "Title" ) ]
91 uno::makeAny( aURI
.GetPathBaseNameUnescaped() ), true );
93 catch ( DAVException
const & )
95 (*m_xProps
)[ OUString( "Title" ) ]
98 OUString( "*** unknown ***" ) ),
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
161 const uno::Any
& ContentProperties::getValue(
162 const OUString
& rName
) const
164 const PropertyValue
* pProp
= get( rName
);
166 return pProp
->value();
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();
180 it
= std::find_if(m_xProps
->cbegin(), end
,
181 [&rName
](const PropertyValueMap::value_type
& rEntry
) {
182 return rEntry
.first
.equalsIgnoreAsciiCase( rName
);
185 return &(*it
).second
;
190 return &(*it
).second
;
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.
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.
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
) )
253 propertyNames
.push_back(
254 DAVProperties::GETCONTENTTYPE
);
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;
281 if ( bIncludeUnmatched
)
282 propertyNames
.push_back( rProp
.Name
);
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.
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" ) );
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
) )
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
);
363 addProperty( rName
, pProp
->value(), pProp
->isCaseSensitive() );
367 addProperty( rName
, uno::Any(), false );
374 void ContentProperties::addProperties( const ContentProperties
& rProps
)
376 for ( const auto& rProp
: *rProps
.m_xProps
)
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
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 ) )
418 // else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) )
421 else if ( rName
== DAVProperties::GETCONTENTLENGTH
)
423 // Map DAV:getcontentlength to UCP:Size
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
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 ) )
460 else if ( rName
== DAVProperties::GETLASTMODIFIED
)
462 // Map the DAV:getlastmodified entity header to UCP:DateModified
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
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 ) )
488 else if ( rName
== DAVProperties::RESOURCETYPE
)
493 // Map DAV:resourcetype to UCP:IsFolder, UCP:IsDocument, UCP:ContentType
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 ) )
511 (*m_xProps
)[ rName
] = PropertyValue( rValue
, bIsCaseSensitive
);
515 // CachableContentProperties Implementation.
520 bool isCachable( OUString
const & rName
,
521 bool isCaseSensitive
)
523 const OUString aNonCachableProps
[] =
525 DAVProperties::LOCKDISCOVERY
,
527 DAVProperties::GETETAG
,
530 OUString( "DateModified" ),
531 OUString( "Last-Modified" ),
532 DAVProperties::GETLASTMODIFIED
,
535 OUString( "Content-Length" ),
536 DAVProperties::GETCONTENTLENGTH
,
541 for ( sal_uInt32 n
= 0;
542 n
< ( sizeof( aNonCachableProps
)
543 / sizeof( aNonCachableProps
[ 0 ] ) );
546 if ( isCaseSensitive
)
548 if ( rName
.equals( aNonCachableProps
[ n
] ) )
552 if ( rName
.equalsIgnoreAsciiCase( aNonCachableProps
[ n
] ) )
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: */