Line data Source code
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 <osl/diagnose.h>
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 :
84 :
85 : // ContentProperties Implementation.
86 :
87 :
88 :
89 :
90 : // static member!
91 2 : uno::Any ContentProperties::m_aEmptyAny;
92 :
93 0 : ContentProperties::ContentProperties( const DAVResource& rResource )
94 0 : : m_xProps( new PropertyValueMap ),
95 0 : m_bTrailingSlash( false )
96 : {
97 : OSL_ENSURE( !rResource.uri.isEmpty(),
98 : "ContentProperties ctor - Empty resource URI!" );
99 :
100 : // Title
101 : try
102 : {
103 0 : NeonUri aURI( rResource.uri );
104 0 : m_aEscapedTitle = aURI.GetPathBaseName();
105 :
106 0 : (*m_xProps)[ OUString("Title") ]
107 0 : = PropertyValue(
108 0 : uno::makeAny( aURI.GetPathBaseNameUnescaped() ), true );
109 : }
110 0 : catch ( DAVException const & )
111 : {
112 0 : (*m_xProps)[ OUString("Title") ]
113 0 : = PropertyValue(
114 : uno::makeAny(
115 : OUString(
116 : "*** unknown ***" ) ),
117 0 : true );
118 : }
119 :
120 : std::vector< DAVPropertyValue >::const_iterator it
121 0 : = rResource.properties.begin();
122 : std::vector< DAVPropertyValue >::const_iterator end
123 0 : = rResource.properties.end();
124 :
125 0 : while ( it != end )
126 : {
127 0 : addProperty( (*it) );
128 0 : ++it;
129 : }
130 :
131 0 : if ( rResource.uri.endsWith("/") )
132 0 : m_bTrailingSlash = true;
133 0 : }
134 :
135 :
136 0 : ContentProperties::ContentProperties(
137 : const OUString & rTitle, bool bFolder )
138 0 : : m_xProps( new PropertyValueMap ),
139 0 : m_bTrailingSlash( false )
140 : {
141 0 : (*m_xProps)[ OUString("Title") ]
142 0 : = PropertyValue( uno::makeAny( rTitle ), true );
143 0 : (*m_xProps)[ OUString("IsFolder") ]
144 0 : = PropertyValue( uno::makeAny( bFolder ), true );
145 0 : (*m_xProps)[ OUString("IsDocument") ]
146 0 : = PropertyValue( uno::makeAny( !bFolder ), true );
147 0 : }
148 :
149 :
150 0 : ContentProperties::ContentProperties( const OUString & rTitle )
151 0 : : m_xProps( new PropertyValueMap ),
152 0 : m_bTrailingSlash( false )
153 : {
154 0 : (*m_xProps)[ OUString("Title") ]
155 0 : = PropertyValue( uno::makeAny( rTitle ), true );
156 0 : }
157 :
158 :
159 0 : ContentProperties::ContentProperties()
160 0 : : m_xProps( new PropertyValueMap ),
161 0 : m_bTrailingSlash( false )
162 : {
163 0 : }
164 :
165 :
166 0 : ContentProperties::ContentProperties( const ContentProperties & rOther )
167 : : m_aEscapedTitle( rOther.m_aEscapedTitle ),
168 0 : m_xProps( rOther.m_xProps.get()
169 0 : ? new PropertyValueMap( *rOther.m_xProps )
170 0 : : new PropertyValueMap ),
171 0 : m_bTrailingSlash( rOther.m_bTrailingSlash )
172 : {
173 0 : }
174 :
175 :
176 0 : bool ContentProperties::contains( const OUString & rName ) const
177 : {
178 0 : if ( get( rName ) )
179 0 : return true;
180 : else
181 0 : return false;
182 : }
183 :
184 :
185 0 : const uno::Any & ContentProperties::getValue(
186 : const OUString & rName ) const
187 : {
188 0 : const PropertyValue * pProp = get( rName );
189 0 : if ( pProp )
190 0 : return pProp->value();
191 : else
192 0 : return m_aEmptyAny;
193 : }
194 :
195 :
196 0 : const PropertyValue * ContentProperties::get(
197 : const OUString & rName ) const
198 : {
199 0 : PropertyValueMap::const_iterator it = m_xProps->find( rName );
200 0 : const PropertyValueMap::const_iterator end = m_xProps->end();
201 :
202 0 : if ( it == end )
203 : {
204 0 : it = m_xProps->begin();
205 0 : while ( it != end )
206 : {
207 0 : if ( (*it).first.equalsIgnoreAsciiCase( rName ) )
208 0 : return &(*it).second;
209 :
210 0 : ++it;
211 : }
212 0 : return 0;
213 : }
214 : else
215 0 : return &(*it).second;
216 : }
217 :
218 :
219 : // static
220 0 : void ContentProperties::UCBNamesToDAVNames(
221 : const uno::Sequence< beans::Property > & rProps,
222 : std::vector< OUString > & propertyNames,
223 : bool bIncludeUnmatched /* = true */ )
224 : {
225 :
226 : // Assemble list of DAV properties to obtain from server.
227 : // Append DAV properties needed to obtain requested UCB props.
228 :
229 :
230 : // DAV UCB
231 : // creationdate <- DateCreated
232 : // getlastmodified <- DateModified
233 : // getcontenttype <- MediaType
234 : // getcontentlength <- Size
235 : // resourcetype <- IsFolder, IsDocument, ContentType
236 : // (taken from URI) <- Title
237 :
238 0 : bool bCreationDate = false;
239 0 : bool bLastModified = false;
240 0 : bool bContentType = false;
241 0 : bool bContentLength = false;
242 0 : bool bResourceType = false;
243 :
244 0 : sal_Int32 nCount = rProps.getLength();
245 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
246 : {
247 0 : const beans::Property & rProp = rProps[ n ];
248 :
249 0 : if ( rProp.Name == "Title" )
250 : {
251 : // Title is always obtained from resource's URI.
252 0 : continue;
253 : }
254 0 : else if ( rProp.Name == "DateCreated" || rProp.Name == DAVProperties::CREATIONDATE )
255 : {
256 0 : if ( !bCreationDate )
257 : {
258 0 : propertyNames.push_back( DAVProperties::CREATIONDATE );
259 0 : bCreationDate = true;
260 : }
261 : }
262 0 : else if ( rProp.Name == "DateModified" || rProp.Name == DAVProperties::GETLASTMODIFIED )
263 : {
264 0 : if ( !bLastModified )
265 : {
266 : propertyNames.push_back(
267 0 : DAVProperties::GETLASTMODIFIED );
268 0 : bLastModified = true;
269 : }
270 : }
271 0 : else if ( rProp.Name == "MediaType" || rProp.Name == DAVProperties::GETCONTENTTYPE )
272 : {
273 0 : if ( !bContentType )
274 : {
275 : propertyNames.push_back(
276 0 : DAVProperties::GETCONTENTTYPE );
277 0 : bContentType = true;
278 : }
279 : }
280 0 : else if ( rProp.Name == "Size" || rProp.Name == DAVProperties::GETCONTENTLENGTH )
281 : {
282 0 : if ( !bContentLength )
283 : {
284 : propertyNames.push_back(
285 0 : DAVProperties::GETCONTENTLENGTH );
286 0 : bContentLength = true;
287 : }
288 : }
289 0 : else if ( rProp.Name == "ContentType" || rProp.Name == "IsDocument" || rProp.Name == "IsFolder" || rProp.Name == DAVProperties::RESOURCETYPE )
290 : {
291 0 : if ( !bResourceType )
292 : {
293 0 : propertyNames.push_back( DAVProperties::RESOURCETYPE );
294 0 : bResourceType = true;
295 : }
296 : }
297 : else
298 : {
299 0 : if ( bIncludeUnmatched )
300 0 : propertyNames.push_back( rProp.Name );
301 : }
302 : }
303 0 : }
304 :
305 :
306 : // static
307 0 : void ContentProperties::UCBNamesToHTTPNames(
308 : const uno::Sequence< beans::Property > & rProps,
309 : std::vector< OUString > & propertyNames,
310 : bool bIncludeUnmatched /* = true */ )
311 : {
312 :
313 : // Assemble list of HTTP header names to obtain from server.
314 : // Append HTTP headers needed to obtain requested UCB props.
315 :
316 :
317 : // HTTP UCB
318 : // Last-Modified <- DateModified
319 : // Content-Type <- MediaType
320 : // Content-Length <- Size
321 :
322 0 : sal_Int32 nCount = rProps.getLength();
323 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
324 : {
325 0 : const beans::Property & rProp = rProps[ n ];
326 :
327 0 : if ( rProp.Name == "DateModified" )
328 : {
329 : propertyNames.push_back(
330 0 : OUString("Last-Modified") );
331 : }
332 0 : else if ( rProp.Name == "MediaType" )
333 : {
334 : propertyNames.push_back(
335 0 : OUString("Content-Type") );
336 : }
337 0 : else if ( rProp.Name == "Size" )
338 : {
339 : propertyNames.push_back(
340 0 : OUString("Content-Length") );
341 : }
342 : else
343 : {
344 0 : if ( bIncludeUnmatched )
345 0 : propertyNames.push_back( rProp.Name );
346 : }
347 : }
348 0 : }
349 :
350 :
351 0 : bool ContentProperties::containsAllNames(
352 : const uno::Sequence< beans::Property >& rProps,
353 : std::vector< OUString > & rNamesNotContained ) const
354 : {
355 0 : rNamesNotContained.clear();
356 :
357 0 : sal_Int32 nCount = rProps.getLength();
358 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
359 : {
360 0 : const OUString & rName = rProps[ n ].Name;
361 0 : if ( !contains( rName ) )
362 : {
363 : // Not found.
364 0 : rNamesNotContained.push_back( rName );
365 : }
366 : }
367 :
368 0 : return ( rNamesNotContained.empty() );
369 : }
370 :
371 :
372 0 : void ContentProperties::addProperties(
373 : const std::vector< OUString > & rProps,
374 : const ContentProperties & rContentProps )
375 : {
376 0 : std::vector< OUString >::const_iterator it = rProps.begin();
377 0 : std::vector< OUString >::const_iterator end = rProps.end();
378 :
379 0 : while ( it != end )
380 : {
381 0 : const OUString & rName = (*it);
382 :
383 0 : if ( !contains( rName ) ) // ignore duplicates
384 : {
385 0 : const PropertyValue * pProp = rContentProps.get( rName );
386 0 : if ( pProp )
387 : {
388 : // Add it.
389 0 : addProperty( rName, pProp->value(), pProp->isCaseSensitive() );
390 : }
391 : else
392 : {
393 0 : addProperty( rName, uno::Any(), false );
394 : }
395 : }
396 0 : ++it;
397 : }
398 0 : }
399 :
400 :
401 0 : void ContentProperties::addProperty( const DAVPropertyValue & rProp )
402 : {
403 0 : addProperty( rProp.Name, rProp.Value, rProp.IsCaseSensitive );
404 0 : }
405 :
406 :
407 0 : void ContentProperties::addProperty( const OUString & rName,
408 : const com::sun::star::uno::Any & rValue,
409 : bool bIsCaseSensitive )
410 : {
411 0 : if ( rName.equals( DAVProperties::CREATIONDATE ) )
412 : {
413 : // Map DAV:creationdate to UCP:DateCreated
414 0 : OUString aValue;
415 0 : rValue >>= aValue;
416 0 : util::DateTime aDate;
417 0 : DateTimeHelper::convert( aValue, aDate );
418 :
419 0 : (*m_xProps)[ OUString("DateCreated") ]
420 0 : = PropertyValue( uno::makeAny( aDate ), true );
421 : }
422 : // else if ( rName.equals( DAVProperties::DISPLAYNAME ) )
423 : // {
424 : // }
425 : // else if ( rName.equals( DAVProperties::GETCONTENTLANGUAGE ) )
426 : // {
427 : // }
428 0 : else if ( rName.equals( DAVProperties::GETCONTENTLENGTH ) )
429 : {
430 : // Map DAV:getcontentlength to UCP:Size
431 0 : OUString aValue;
432 0 : rValue >>= aValue;
433 :
434 0 : (*m_xProps)[ OUString("Size") ]
435 0 : = PropertyValue( uno::makeAny( aValue.toInt64() ), true );
436 : }
437 0 : else if ( rName == "Content-Length" )
438 : {
439 : // Do NOT map Content-length entity header to DAV:getcontentlength!
440 : // Only DAV resources have this property.
441 :
442 : // Map Content-Length entity header to UCP:Size
443 0 : OUString aValue;
444 0 : rValue >>= aValue;
445 :
446 0 : (*m_xProps)[ OUString("Size") ]
447 0 : = PropertyValue( uno::makeAny( aValue.toInt64() ), true );
448 : }
449 0 : else if ( rName.equals( DAVProperties::GETCONTENTTYPE ) )
450 : {
451 : // Map DAV:getcontenttype to UCP:MediaType (1:1)
452 0 : (*m_xProps)[ OUString("MediaType") ]
453 0 : = PropertyValue( rValue, true );
454 : }
455 0 : else if ( rName == "Content-Type" )
456 : {
457 : // Do NOT map Content-Type entity header to DAV:getcontenttype!
458 : // Only DAV resources have this property.
459 :
460 : // Map DAV:getcontenttype to UCP:MediaType (1:1)
461 0 : (*m_xProps)[ OUString("MediaType") ]
462 0 : = PropertyValue( rValue, true );
463 : }
464 : // else if ( rName.equals( DAVProperties::GETETAG ) )
465 : // {
466 : // }
467 0 : else if ( rName.equals( DAVProperties::GETLASTMODIFIED ) )
468 : {
469 : // Map the DAV:getlastmodified entity header to UCP:DateModified
470 0 : OUString aValue;
471 0 : rValue >>= aValue;
472 0 : util::DateTime aDate;
473 0 : DateTimeHelper::convert( aValue, aDate );
474 :
475 0 : (*m_xProps)[ OUString("DateModified") ]
476 0 : = PropertyValue( uno::makeAny( aDate ), true );
477 : }
478 0 : else if ( rName == "Last-Modified" )
479 : {
480 : // Do not map Last-Modified entity header to DAV:getlastmodified!
481 : // Only DAV resources have this property.
482 :
483 : // Map the Last-Modified entity header to UCP:DateModified
484 0 : OUString aValue;
485 0 : rValue >>= aValue;
486 0 : util::DateTime aDate;
487 0 : DateTimeHelper::convert( aValue, aDate );
488 :
489 0 : (*m_xProps)[ OUString("DateModified") ]
490 0 : = PropertyValue( uno::makeAny( aDate ), true );
491 : }
492 : // else if ( rName.equals( DAVProperties::LOCKDISCOVERY ) )
493 : // {
494 : // }
495 0 : else if ( rName.equals( DAVProperties::RESOURCETYPE ) )
496 : {
497 0 : OUString aValue;
498 0 : rValue >>= aValue;
499 :
500 : // Map DAV:resourceype to UCP:IsFolder, UCP:IsDocument, UCP:ContentType
501 0 : bool bFolder = aValue.equalsIgnoreAsciiCase( "collection" );
502 :
503 0 : (*m_xProps)[ OUString("IsFolder") ]
504 0 : = PropertyValue( uno::makeAny( bFolder ), true );
505 0 : (*m_xProps)[ OUString("IsDocument") ]
506 0 : = PropertyValue( uno::makeAny( !bFolder ), true );
507 0 : (*m_xProps)[ OUString("ContentType") ]
508 0 : = PropertyValue( uno::makeAny( bFolder
509 : ? OUString( WEBDAV_COLLECTION_TYPE )
510 0 : : OUString( WEBDAV_CONTENT_TYPE ) ), true );
511 : }
512 : // else if ( rName.equals( DAVProperties::SOURCE ) )
513 : // {
514 : // }
515 : // else if ( rName.equals( DAVProperties::SUPPORTEDLOCK ) )
516 : // {
517 : // }
518 :
519 : // Save property.
520 0 : (*m_xProps)[ rName ] = PropertyValue( rValue, bIsCaseSensitive );
521 0 : }
522 :
523 :
524 :
525 :
526 : // CachableContentProperties Implementation.
527 :
528 :
529 :
530 :
531 : namespace
532 : {
533 0 : bool isCachable( OUString const & rName,
534 : bool isCaseSensitive )
535 : {
536 : static const OUString aNonCachableProps [] =
537 : {
538 : DAVProperties::LOCKDISCOVERY,
539 :
540 : DAVProperties::GETETAG,
541 : OUString( "ETag" ),
542 :
543 : OUString( "DateModified" ),
544 : OUString( "Last-Modified" ),
545 : DAVProperties::GETLASTMODIFIED,
546 :
547 : OUString( "Size" ),
548 : OUString( "Content-Length" ),
549 : DAVProperties::GETCONTENTLENGTH,
550 :
551 : OUString( "Date" )
552 0 : };
553 :
554 0 : for ( sal_uInt32 n = 0;
555 0 : n < ( sizeof( aNonCachableProps )
556 0 : / sizeof( aNonCachableProps[ 0 ] ) );
557 : ++n )
558 : {
559 0 : if ( isCaseSensitive )
560 : {
561 0 : if ( rName.equals( aNonCachableProps[ n ] ) )
562 0 : return false;
563 : }
564 : else
565 0 : if ( rName.equalsIgnoreAsciiCase( aNonCachableProps[ n ] ) )
566 0 : return false;
567 : }
568 0 : return true;
569 : }
570 :
571 : } // namespace
572 :
573 :
574 0 : CachableContentProperties::CachableContentProperties(
575 0 : const ContentProperties & rProps )
576 : {
577 0 : addProperties( rProps );
578 0 : }
579 :
580 :
581 0 : void CachableContentProperties::addProperties(
582 : const ContentProperties & rProps )
583 : {
584 0 : const std::unique_ptr< PropertyValueMap > & props = rProps.getProperties();
585 :
586 0 : PropertyValueMap::const_iterator it = props->begin();
587 0 : const PropertyValueMap::const_iterator end = props->end();
588 :
589 0 : while ( it != end )
590 : {
591 0 : if ( isCachable( (*it).first, (*it).second.isCaseSensitive() ) )
592 0 : m_aProps.addProperty( (*it).first,
593 0 : (*it).second.value(),
594 0 : (*it).second.isCaseSensitive() );
595 :
596 0 : ++it;
597 : }
598 0 : }
599 :
600 :
601 0 : void CachableContentProperties::addProperties(
602 : const std::vector< DAVPropertyValue > & rProps )
603 : {
604 0 : std::vector< DAVPropertyValue >::const_iterator it = rProps.begin();
605 0 : const std::vector< DAVPropertyValue >::const_iterator end = rProps.end();
606 :
607 0 : while ( it != end )
608 : {
609 0 : if ( isCachable( (*it).Name, (*it).IsCaseSensitive ) )
610 0 : m_aProps.addProperty( (*it) );
611 :
612 0 : ++it;
613 : }
614 6 : }
615 :
616 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|