LibreOffice Module ucb (master) 1
webdavcontentcaps.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <memory>
21#include <set>
22#include <com/sun/star/beans/Property.hpp>
23#include <com/sun/star/beans/PropertyAttribute.hpp>
24#include <com/sun/star/beans/PropertyValue.hpp>
25#include <com/sun/star/ucb/CommandInfo.hpp>
26#include <com/sun/star/ucb/ContentInfo.hpp>
27#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
28#include <com/sun/star/ucb/InsertCommandArgument.hpp>
29#include <com/sun/star/ucb/PostCommandArgument2.hpp>
30#include <com/sun/star/ucb/PropertyCommandArgument.hpp>
31#include <com/sun/star/ucb/TransferInfo.hpp>
32#include <com/sun/star/uno/Sequence.hxx>
33#include <com/sun/star/util/DateTime.hpp>
34#include <com/sun/star/ucb/Lock.hpp>
35#include <com/sun/star/ucb/LockEntry.hpp>
36#include "webdavcontent.hxx"
37#include "webdavprovider.hxx"
38#include "DAVProperties.hxx"
39#include "ContentProperties.hxx"
40#include "PropfindCache.hxx"
41
42using namespace com::sun::star;
43using namespace http_dav_ucp;
44
45
46// ContentProvider implementation.
47
48
49bool ContentProvider::getProperty(
50 const OUString & rPropName, beans::Property & rProp )
51{
52 if ( !m_pProps )
53 {
54 osl::MutexGuard aGuard( m_aMutex );
55 if ( !m_pProps )
56 {
57 m_pProps = std::make_unique<PropertyMap>();
58
59
60 // Fill map of known properties...
61
62
63 // Mandatory UCB properties.
64 m_pProps->insert(
65 beans::Property(
66 "ContentType",
67 -1,
69 beans::PropertyAttribute::BOUND
70 | beans::PropertyAttribute::READONLY ) );
71
72 m_pProps->insert(
73 beans::Property(
74 "IsDocument",
75 -1,
77 beans::PropertyAttribute::BOUND
78 | beans::PropertyAttribute::READONLY ) );
79
80 m_pProps->insert(
81 beans::Property(
82 "IsFolder",
83 -1,
85 beans::PropertyAttribute::BOUND
86 | beans::PropertyAttribute::READONLY ) );
87
88 m_pProps->insert(
89 beans::Property(
90 "Title",
91 -1,
93 beans::PropertyAttribute::BOUND ) );
94
95 // Optional UCB properties.
96
97 m_pProps->insert(
98 beans::Property(
99 "DateCreated",
100 -1,
102 beans::PropertyAttribute::BOUND
103 | beans::PropertyAttribute::READONLY ) );
104
105 m_pProps->insert(
106 beans::Property(
107 "DateModified",
108 -1,
110 beans::PropertyAttribute::BOUND
111 | beans::PropertyAttribute::READONLY ) );
112
113 m_pProps->insert(
114 beans::Property(
115 "MediaType",
116 -1,
118 beans::PropertyAttribute::BOUND
119 | beans::PropertyAttribute::READONLY ) );
120
121 m_pProps->insert(
122 beans::Property(
123 "Size",
124 -1,
126 beans::PropertyAttribute::BOUND
127 | beans::PropertyAttribute::READONLY ) );
128
129 m_pProps->insert(
130 beans::Property(
131 "BaseURI",
132 -1,
134 beans::PropertyAttribute::BOUND
135 | beans::PropertyAttribute::READONLY ) );
136
137 m_pProps->insert(
138 beans::Property(
139 "CreatableContentsInfo",
140 -1,
141 cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
142 beans::PropertyAttribute::BOUND
143 | beans::PropertyAttribute::READONLY ) );
144
145 // Standard DAV properties.
146
147 m_pProps->insert(
148 beans::Property(
150 -1,
152 beans::PropertyAttribute::BOUND
153 | beans::PropertyAttribute::READONLY ) );
154
155 m_pProps->insert(
156 beans::Property(
158 -1,
160 beans::PropertyAttribute::BOUND ) );
161
162 m_pProps->insert(
163 beans::Property(
165 -1,
167 beans::PropertyAttribute::BOUND
168 | beans::PropertyAttribute::READONLY ) );
169
170 m_pProps->insert(
171 beans::Property(
173 -1,
175 beans::PropertyAttribute::BOUND
176 | beans::PropertyAttribute::READONLY ) );
177
178 m_pProps->insert(
179 beans::Property(
181 -1,
183 beans::PropertyAttribute::BOUND
184 | beans::PropertyAttribute::READONLY ) );
185
186 m_pProps->insert(
187 beans::Property(
189 -1,
191 beans::PropertyAttribute::BOUND
192 | beans::PropertyAttribute::READONLY ) );
193
194 m_pProps->insert(
195 beans::Property(
197 -1,
199 beans::PropertyAttribute::BOUND
200 | beans::PropertyAttribute::READONLY ) );
201
202 m_pProps->insert(
203 beans::Property(
205 -1,
206 cppu::UnoType<uno::Sequence< ucb::Lock >>::get(),
207 beans::PropertyAttribute::BOUND
208 | beans::PropertyAttribute::READONLY ) );
209
210 m_pProps->insert(
211 beans::Property(
213 -1,
215 beans::PropertyAttribute::BOUND
216 | beans::PropertyAttribute::READONLY ) );
217
218 m_pProps->insert(
219 beans::Property(
221 -1,
222 cppu::UnoType<uno::Sequence< ucb::LockEntry >>::get(),
223 beans::PropertyAttribute::BOUND
224 | beans::PropertyAttribute::READONLY ) );
225
226 m_pProps->insert(
227 beans::Property(
229 -1,
231 beans::PropertyAttribute::BOUND ) );
232 }
233 }
234
235
236 // Lookup property.
237
238
239 beans::Property aProp;
240 aProp.Name = rPropName;
241 const PropertyMap::const_iterator it = m_pProps->find( aProp );
242 if ( it != m_pProps->end() )
243 {
244 rProp = *it;
245 }
246 else
247 {
248 // All unknown props are treated as:
249 rProp = beans::Property(
250 rPropName,
251 - 1,
253 beans::PropertyAttribute::BOUND );
254 }
255
256 return true;
257}
258
259
261
262// static
263void Content::removeCachedPropertyNames( const OUString & rURL )
264{
266}
267
268// Content implementation.
269
270
271// virtual
272uno::Sequence< beans::Property > Content::getProperties(
273 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
274{
275 bool bTransient;
276 std::unique_ptr< DAVResourceAccess > xResAccess;
277 std::unique_ptr< ContentProperties > xCachedProps;
279
280 {
281 osl::Guard< osl::Mutex > aGuard( m_aMutex );
282
283 bTransient = m_bTransient;
284 xResAccess.reset( new DAVResourceAccess( *m_xResAccess ) );
285 if (m_xCachedProps)
286 xCachedProps.reset(
288 xProvider.set( m_pProvider );
289 }
290
291 std::set< OUString > aPropSet;
292
293 // No server access for just created (not yet committed) objects.
294 // Only a minimal set of properties supported at this stage.
295 if ( !bTransient )
296 {
297 // Obtain all properties supported for this resource from server.
298 DAVOptions aDAVOptions;
299 getResourceOptions( xEnv, aDAVOptions, xResAccess );
300 // only Class 1 is needed for PROPFIND
301 if ( aDAVOptions.isClass1() )
302 {
303 try
304 {
305 std::vector< DAVResourceInfo > props;
306 OUString aTheURL( xResAccess->getURL() );
307 PropertyNames aPropsNames( aTheURL );
308
309 if( !aStaticPropertyNamesCache.getCachedPropertyNames( aTheURL, aPropsNames ) )
310 {
311
312 xResAccess->PROPFIND( DAVZERO, props, xEnv );
313 aPropsNames.setPropertiesNames( props );
314
316 }
317 else
318 {
319 props = aPropsNames.getPropertiesNames();
320 }
321
322 // Note: vector should contain exactly one resource info, because
323 // we used a depth of DAVZERO for PROPFIND.
324 if (props.size() == 1)
325 {
326 aPropSet.insert( (*props.begin()).properties.begin(),
327 (*props.begin()).properties.end() );
328 }
329 }
330 catch ( DAVException const & )
331 {
332 }
333 }
334 }
335
336 // Add DAV properties, map DAV properties to UCB properties.
337 bool bHasCreationDate = false; // creationdate <-> DateCreated
338 bool bHasGetLastModified = false; // getlastmodified <-> DateModified
339 bool bHasGetContentType = false; // getcontenttype <-> MediaType
340 bool bHasGetContentLength = false; // getcontentlength <-> Size
341
342 bool bHasContentType = false;
343 bool bHasIsDocument = false;
344 bool bHasIsFolder = false;
345 bool bHasTitle = false;
346 bool bHasBaseURI = false;
347 bool bHasDateCreated = false;
348 bool bHasDateModified = false;
349 bool bHasMediaType = false;
350 bool bHasSize = false;
351 bool bHasCreatableInfos = false;
352
353 {
354 for ( const auto& rProp : aPropSet )
355 {
356 if ( !bHasCreationDate &&
357 ( rProp == DAVProperties::CREATIONDATE ) )
358 {
359 bHasCreationDate = true;
360 }
361 else if ( !bHasGetLastModified &&
362 ( rProp == DAVProperties::GETLASTMODIFIED ) )
363 {
364 bHasGetLastModified = true;
365 }
366 else if ( !bHasGetContentType &&
367 ( rProp == DAVProperties::GETCONTENTTYPE ) )
368 {
369 bHasGetContentType = true;
370 }
371 else if ( !bHasGetContentLength &&
373 {
374 bHasGetContentLength = true;
375 }
376 else if ( !bHasContentType && rProp == "ContentType" )
377 {
378 bHasContentType = true;
379 }
380 else if ( !bHasIsDocument && rProp == "IsDocument" )
381 {
382 bHasIsDocument = true;
383 }
384 else if ( !bHasIsFolder && rProp == "IsFolder" )
385 {
386 bHasIsFolder = true;
387 }
388 else if ( !bHasTitle && rProp == "Title" )
389 {
390 bHasTitle = true;
391 }
392 else if ( !bHasBaseURI && rProp == "BaseURI" )
393 {
394 bHasBaseURI = true;
395 }
396 else if ( !bHasDateCreated && rProp == "DateCreated" )
397 {
398 bHasDateCreated = true;
399 }
400 else if ( !bHasDateModified && rProp == "DateModified" )
401 {
402 bHasDateModified = true;
403 }
404 else if ( !bHasMediaType && rProp == "MediaType" )
405 {
406 bHasMediaType = true;
407 }
408 else if ( !bHasSize && rProp == "Size" )
409 {
410 bHasSize = true;
411 }
412 else if ( !bHasCreatableInfos && rProp == "CreatableContentsInfo" )
413 {
414 bHasCreatableInfos = true;
415 }
416 }
417 }
418
419 // Add mandatory properties.
420 if ( !bHasContentType )
421 aPropSet.insert(
422 OUString( "ContentType" ) );
423
424 if ( !bHasIsDocument )
425 aPropSet.insert(
426 OUString( "IsDocument" ) );
427
428 if ( !bHasIsFolder )
429 aPropSet.insert(
430 OUString( "IsFolder" ) );
431
432 if ( !bHasTitle )
433 {
434 // Always present since it can be calculated from content's URI.
435 aPropSet.insert(
436 OUString( "Title" ) );
437 }
438
439 // Add optional properties.
440
441 if ( !bHasBaseURI )
442 {
443 // Always present since it can be calculated from content's URI.
444 aPropSet.insert(
445 OUString( "BaseURI" ) );
446 }
447
448 if ( !bHasDateCreated && bHasCreationDate )
449 aPropSet.insert(
450 OUString( "DateCreated" ) );
451
452 if ( !bHasDateModified && bHasGetLastModified )
453 aPropSet.insert(
454 OUString( "DateModified" ) );
455
456 if ( !bHasMediaType && bHasGetContentType )
457 aPropSet.insert(
458 OUString( "MediaType" ) );
459
460 if ( !bHasSize && bHasGetContentLength )
461 aPropSet.insert(
462 OUString( "Size" ) );
463
464 if ( !bHasCreatableInfos )
465 aPropSet.insert(
466 OUString(
467 "CreatableContentsInfo" ) );
468
469 // Add cached properties, if present and still missing.
470 if (xCachedProps)
471 {
472 const std::unique_ptr< PropertyValueMap > & xProps
473 = xCachedProps->getProperties();
474
475 for ( const auto& rEntry : *xProps )
476 aPropSet.insert( rEntry.first );
477 }
478
479 // std::set -> uno::Sequence
480 sal_Int32 nCount = aPropSet.size();
481 uno::Sequence< beans::Property > aProperties( nCount );
482 auto aPropertiesRange = asNonConstRange(aProperties);
483
484 beans::Property aProp;
485 sal_Int32 n = 0;
486
487 for ( const auto& rProp : aPropSet )
488 {
489 xProvider->getProperty( rProp, aProp );
490 aPropertiesRange[ n++ ] = aProp;
491 }
492
493 return aProperties;
494}
495
496
497// virtual
498uno::Sequence< ucb::CommandInfo > Content::getCommands(
499 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
500{
501 osl::Guard< osl::Mutex > aGuard( m_aMutex );
502
503 uno::Sequence< ucb::CommandInfo > aCmdInfo( 10 );
504 auto pCmdInfo = aCmdInfo.getArray();
505
506
507 // Mandatory commands
508
509
510 pCmdInfo[ 0 ] =
511 ucb::CommandInfo(
512 "getCommandInfo",
513 -1,
515 pCmdInfo[ 1 ] =
516 ucb::CommandInfo(
517 "getPropertySetInfo",
518 -1,
520 pCmdInfo[ 2 ] =
521 ucb::CommandInfo(
522 "getPropertyValues",
523 -1,
524 cppu::UnoType<uno::Sequence< beans::Property >>::get());
525 pCmdInfo[ 3 ] =
526 ucb::CommandInfo(
527 "setPropertyValues",
528 -1,
529 cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get());
530
531
532 // Optional standard commands
533
534
535 pCmdInfo[ 4 ] =
536 ucb::CommandInfo(
537 "delete",
538 -1,
540 pCmdInfo[ 5 ] =
541 ucb::CommandInfo(
542 "insert",
543 -1,
545 pCmdInfo[ 6 ] =
546 ucb::CommandInfo(
547 "open",
548 -1,
550
551
552 // New commands
553
554
555 pCmdInfo[ 7 ] =
556 ucb::CommandInfo(
557 "post",
558 -1,
560 pCmdInfo[ 8 ] =
561 ucb::CommandInfo(
562 "addProperty",
563 -1,
565 pCmdInfo[ 9 ] =
566 ucb::CommandInfo(
567 "removeProperty",
568 -1,
570
571 bool bFolder = false;
572
573 try
574 {
575 bFolder = isFolder( xEnv );
576 }
577 catch ( uno::Exception const & )
578 {
579 return aCmdInfo;
580 }
581
583 bool bSupportsLocking = ( eType == NOT_FOUND || eType == DAV );
584
585 sal_Int32 nPos = aCmdInfo.getLength();
586 sal_Int32 nMoreCmds = ( bFolder ? 2 : 0 ) + ( bSupportsLocking ? 2 : 0 );
587 if ( nMoreCmds )
588 aCmdInfo.realloc( nPos + nMoreCmds );
589 else
590 return aCmdInfo;
591
592 pCmdInfo = aCmdInfo.getArray();
593
594 if ( bFolder )
595 {
596
597 // Optional standard commands
598
599
600 pCmdInfo[ nPos ] =
601 ucb::CommandInfo(
602 "transfer",
603 -1,
605 nPos++;
606 pCmdInfo[ nPos ] =
607 ucb::CommandInfo(
608 "createNewContent",
609 -1,
611 nPos++;
612 }
613 else
614 {
615 // no document-only commands at the moment.
616 }
617
618 if ( bSupportsLocking )
619 {
620 pCmdInfo[ nPos ] =
621 ucb::CommandInfo(
622 "lock",
623 -1,
625 nPos++;
626 pCmdInfo[ nPos ] =
627 ucb::CommandInfo(
628 "unlock",
629 -1,
631 nPos++;
632 }
633 return aCmdInfo;
634}
635
636/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
PropertiesInfo aProperties
std::unique_ptr< PropertyMap > m_pProps
bool isFolder(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv)
virtual css::uno::Sequence< css::ucb::CommandInfo > getCommands(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv) override
static void removeCachedPropertyNames(const OUString &rURL)
virtual css::uno::Sequence< css::beans::Property > getProperties(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv) override
void getResourceOptions(const css::uno::Reference< css::ucb::XCommandEnvironment > &xEnv, DAVOptions &rDAVOptions, const std::unique_ptr< DAVResourceAccess > &rResAccess, bool *networkAccessAllowed=nullptr)
Use OPTIONS method to retrieve the type of the Web resource.
ResourceType resourceTypeForLocks(const css::uno::Reference< css::ucb::XCommandEnvironment > &rEnvironment, const std::unique_ptr< DAVResourceAccess > &rResAccess)
std::unique_ptr< DAVResourceAccess > m_xResAccess
std::unique_ptr< CachableContentProperties > m_xCachedProps
ContentProvider * m_pProvider
bool isClass1() const
Definition: DAVTypes.hxx:96
void removeCachedPropertyNames(const OUString &URL)
void addCachePropertyNames(PropertyNames &rCacheElement, const sal_uInt32 nLifeTime)
bool getCachedPropertyNames(const OUString &URL, PropertyNames &rCacheElement)
int nCount
DocumentType eType
sal_Int64 n
sal_uInt16 nPos
dictionary props
ResourceType
static constexpr OUStringLiteral GETCONTENTTYPE
static constexpr OUStringLiteral SUPPORTEDLOCK
static constexpr OUStringLiteral CREATIONDATE
static constexpr OUStringLiteral DISPLAYNAME
static constexpr OUStringLiteral EXECUTABLE
static constexpr OUStringLiteral GETETAG
static constexpr OUStringLiteral LOCKDISCOVERY
static constexpr OUStringLiteral RESOURCETYPE
static constexpr OUStringLiteral GETCONTENTLENGTH
static constexpr OUStringLiteral GETLASTMODIFIED
static constexpr OUStringLiteral GETCONTENTLANGUAGE
static PropertyNamesCache aStaticPropertyNamesCache