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