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 
41 using namespace com::sun::star;
42 using namespace http_dav_ucp;
43 
44 
45 // ContentProvider implementation.
46 
47 
48 bool ContentProvider::getProperty(
49  const OUString & rPropName, beans::Property & rProp, bool bStrict )
50 {
51  if ( !m_pProps )
52  {
53  osl::MutexGuard aGuard( m_aMutex );
54  if ( !m_pProps )
55  {
56  m_pProps = std::make_unique<PropertyMap>();
57 
58 
59  // Fill map of known properties...
60 
61 
62  // Mandatory UCB properties.
63  m_pProps->insert(
64  beans::Property(
65  "ContentType",
66  -1,
68  beans::PropertyAttribute::BOUND
69  | beans::PropertyAttribute::READONLY ) );
70 
71  m_pProps->insert(
72  beans::Property(
73  "IsDocument",
74  -1,
76  beans::PropertyAttribute::BOUND
77  | beans::PropertyAttribute::READONLY ) );
78 
79  m_pProps->insert(
80  beans::Property(
81  "IsFolder",
82  -1,
84  beans::PropertyAttribute::BOUND
85  | beans::PropertyAttribute::READONLY ) );
86 
87  m_pProps->insert(
88  beans::Property(
89  "Title",
90  -1,
92  beans::PropertyAttribute::BOUND ) );
93 
94  // Optional UCB properties.
95 
96  m_pProps->insert(
97  beans::Property(
98  "DateCreated",
99  -1,
101  beans::PropertyAttribute::BOUND
102  | beans::PropertyAttribute::READONLY ) );
103 
104  m_pProps->insert(
105  beans::Property(
106  "DateModified",
107  -1,
109  beans::PropertyAttribute::BOUND
110  | beans::PropertyAttribute::READONLY ) );
111 
112  m_pProps->insert(
113  beans::Property(
114  "MediaType",
115  -1,
117  beans::PropertyAttribute::BOUND
118  | beans::PropertyAttribute::READONLY ) );
119 
120  m_pProps->insert(
121  beans::Property(
122  "Size",
123  -1,
125  beans::PropertyAttribute::BOUND
126  | beans::PropertyAttribute::READONLY ) );
127 
128  m_pProps->insert(
129  beans::Property(
130  "BaseURI",
131  -1,
133  beans::PropertyAttribute::BOUND
134  | beans::PropertyAttribute::READONLY ) );
135 
136  m_pProps->insert(
137  beans::Property(
138  "CreatableContentsInfo",
139  -1,
140  cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
141  beans::PropertyAttribute::BOUND
142  | beans::PropertyAttribute::READONLY ) );
143 
144  // Standard DAV properties.
145 
146  m_pProps->insert(
147  beans::Property(
148  DAVProperties::CREATIONDATE,
149  -1,
151  beans::PropertyAttribute::BOUND
152  | beans::PropertyAttribute::READONLY ) );
153 
154  m_pProps->insert(
155  beans::Property(
156  DAVProperties::DISPLAYNAME,
157  -1,
159  beans::PropertyAttribute::BOUND ) );
160 
161  m_pProps->insert(
162  beans::Property(
163  DAVProperties::GETCONTENTLANGUAGE,
164  -1,
166  beans::PropertyAttribute::BOUND
167  | beans::PropertyAttribute::READONLY ) );
168 
169  m_pProps->insert(
170  beans::Property(
171  DAVProperties::GETCONTENTLENGTH,
172  -1,
174  beans::PropertyAttribute::BOUND
175  | beans::PropertyAttribute::READONLY ) );
176 
177  m_pProps->insert(
178  beans::Property(
179  DAVProperties::GETCONTENTTYPE ,
180  -1,
182  beans::PropertyAttribute::BOUND
183  | beans::PropertyAttribute::READONLY ) );
184 
185  m_pProps->insert(
186  beans::Property(
187  DAVProperties::GETETAG,
188  -1,
190  beans::PropertyAttribute::BOUND
191  | beans::PropertyAttribute::READONLY ) );
192 
193  m_pProps->insert(
194  beans::Property(
195  DAVProperties::GETLASTMODIFIED,
196  -1,
198  beans::PropertyAttribute::BOUND
199  | beans::PropertyAttribute::READONLY ) );
200 
201  m_pProps->insert(
202  beans::Property(
203  DAVProperties::LOCKDISCOVERY,
204  -1,
205  cppu::UnoType<uno::Sequence< ucb::Lock >>::get(),
206  beans::PropertyAttribute::BOUND
207  | beans::PropertyAttribute::READONLY ) );
208 
209  m_pProps->insert(
210  beans::Property(
211  DAVProperties::RESOURCETYPE,
212  -1,
214  beans::PropertyAttribute::BOUND
215  | beans::PropertyAttribute::READONLY ) );
216 
217  m_pProps->insert(
218  beans::Property(
219  DAVProperties::SUPPORTEDLOCK,
220  -1,
221  cppu::UnoType<uno::Sequence< ucb::LockEntry >>::get(),
222  beans::PropertyAttribute::BOUND
223  | beans::PropertyAttribute::READONLY ) );
224 
225  m_pProps->insert(
226  beans::Property(
227  DAVProperties::EXECUTABLE,
228  -1,
230  beans::PropertyAttribute::BOUND ) );
231  }
232  }
233 
234 
235  // Lookup property.
236 
237 
238  beans::Property aProp;
239  aProp.Name = rPropName;
240  const PropertyMap::const_iterator it = m_pProps->find( aProp );
241  if ( it != m_pProps->end() )
242  {
243  rProp = *it;
244  }
245  else
246  {
247  if ( bStrict )
248  return false;
249 
250  // All unknown props are treated as:
251  rProp = beans::Property(
252  rPropName,
253  - 1,
255  beans::PropertyAttribute::BOUND );
256  }
257 
258  return true;
259 }
260 
261 
262 // Content implementation.
263 
264 
265 // virtual
266 uno::Sequence< beans::Property > Content::getProperties(
267  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
268 {
269  bool bTransient;
270  std::unique_ptr< DAVResourceAccess > xResAccess;
271  std::unique_ptr< ContentProperties > xCachedProps;
273 
274  {
275  osl::Guard< osl::Mutex > aGuard( m_aMutex );
276 
277  bTransient = m_bTransient;
278  xResAccess.reset( new DAVResourceAccess( *m_xResAccess.get() ) );
279  if ( m_xCachedProps.get() )
280  xCachedProps.reset(
281  new ContentProperties( *m_xCachedProps.get() ) );
282  xProvider.set( m_pProvider );
283  }
284 
285  std::set< OUString > aPropSet;
286 
287  // No server access for just created (not yet committed) objects.
288  // Only a minimal set of properties supported at this stage.
289  if ( !bTransient )
290  {
291  // Obtain all properties supported for this resource from server.
292  try
293  {
294  std::vector< DAVResourceInfo > props;
295  xResAccess->PROPFIND( DAVZERO, props, xEnv );
296 
297  // Note: vector always contains exactly one resource info, because
298  // we used a depth of DAVZERO for PROPFIND.
299  aPropSet.insert( (*props.begin()).properties.begin(),
300  (*props.begin()).properties.end() );
301  }
302  catch ( DAVException const & )
303  {
304  }
305  }
306 
307  // Add DAV properties, map DAV properties to UCB properties.
308  bool bHasCreationDate = false; // creationdate <-> DateCreated
309  bool bHasGetLastModified = false; // getlastmodified <-> DateModified
310  bool bHasGetContentType = false; // getcontenttype <-> MediaType
311  bool bHasGetContentLength = false; // getcontentlength <-> Size
312 
313  bool bHasContentType = false;
314  bool bHasIsDocument = false;
315  bool bHasIsFolder = false;
316  bool bHasTitle = false;
317  bool bHasBaseURI = false;
318  bool bHasDateCreated = false;
319  bool bHasDateModified = false;
320  bool bHasMediaType = false;
321  bool bHasSize = false;
322  bool bHasCreatableInfos = false;
323 
324  {
325  for ( const auto& rProp : aPropSet )
326  {
327  if ( !bHasCreationDate &&
328  ( rProp == DAVProperties::CREATIONDATE ) )
329  {
330  bHasCreationDate = true;
331  }
332  else if ( !bHasGetLastModified &&
333  ( rProp == DAVProperties::GETLASTMODIFIED ) )
334  {
335  bHasGetLastModified = true;
336  }
337  else if ( !bHasGetContentType &&
338  ( rProp == DAVProperties::GETCONTENTTYPE ) )
339  {
340  bHasGetContentType = true;
341  }
342  else if ( !bHasGetContentLength &&
343  ( rProp == DAVProperties::GETCONTENTLENGTH ) )
344  {
345  bHasGetContentLength = true;
346  }
347  else if ( !bHasContentType && rProp == "ContentType" )
348  {
349  bHasContentType = true;
350  }
351  else if ( !bHasIsDocument && rProp == "IsDocument" )
352  {
353  bHasIsDocument = true;
354  }
355  else if ( !bHasIsFolder && rProp == "IsFolder" )
356  {
357  bHasIsFolder = true;
358  }
359  else if ( !bHasTitle && rProp == "Title" )
360  {
361  bHasTitle = true;
362  }
363  else if ( !bHasBaseURI && rProp == "BaseURI" )
364  {
365  bHasBaseURI = true;
366  }
367  else if ( !bHasDateCreated && rProp == "DateCreated" )
368  {
369  bHasDateCreated = true;
370  }
371  else if ( !bHasDateModified && rProp == "DateModified" )
372  {
373  bHasDateModified = true;
374  }
375  else if ( !bHasMediaType && rProp == "MediaType" )
376  {
377  bHasMediaType = true;
378  }
379  else if ( !bHasSize && rProp == "Size" )
380  {
381  bHasSize = true;
382  }
383  else if ( !bHasCreatableInfos && rProp == "CreatableContentsInfo" )
384  {
385  bHasCreatableInfos = true;
386  }
387  }
388  }
389 
390  // Add mandatory properties.
391  if ( !bHasContentType )
392  aPropSet.insert(
393  OUString( "ContentType" ) );
394 
395  if ( !bHasIsDocument )
396  aPropSet.insert(
397  OUString( "IsDocument" ) );
398 
399  if ( !bHasIsFolder )
400  aPropSet.insert(
401  OUString( "IsFolder" ) );
402 
403  if ( !bHasTitle )
404  {
405  // Always present since it can be calculated from content's URI.
406  aPropSet.insert(
407  OUString( "Title" ) );
408  }
409 
410  // Add optional properties.
411 
412  if ( !bHasBaseURI )
413  {
414  // Always present since it can be calculated from content's URI.
415  aPropSet.insert(
416  OUString( "BaseURI" ) );
417  }
418 
419  if ( !bHasDateCreated && bHasCreationDate )
420  aPropSet.insert(
421  OUString( "DateCreated" ) );
422 
423  if ( !bHasDateModified && bHasGetLastModified )
424  aPropSet.insert(
425  OUString( "DateModified" ) );
426 
427  if ( !bHasMediaType && bHasGetContentType )
428  aPropSet.insert(
429  OUString( "MediaType" ) );
430 
431  if ( !bHasSize && bHasGetContentLength )
432  aPropSet.insert(
433  OUString( "Size" ) );
434 
435  if ( !bHasCreatableInfos )
436  aPropSet.insert(
437  OUString(
438  "CreatableContentsInfo" ) );
439 
440  // Add cached properties, if present and still missing.
441  if ( xCachedProps.get() )
442  {
443  const std::unique_ptr< PropertyValueMap > & xProps
444  = xCachedProps->getProperties();
445 
446  for ( const auto& rEntry : *xProps )
447  aPropSet.insert( rEntry.first );
448  }
449 
450  // std::set -> uno::Sequence
451  sal_Int32 nCount = aPropSet.size();
452  uno::Sequence< beans::Property > aProperties( nCount );
453 
454  beans::Property aProp;
455  sal_Int32 n = 0;
456 
457  for ( const auto& rProp : aPropSet )
458  {
459  xProvider->getProperty( rProp, aProp );
460  aProperties[ n++ ] = aProp;
461  }
462 
463  return aProperties;
464 }
465 
466 
467 // virtual
468 uno::Sequence< ucb::CommandInfo > Content::getCommands(
469  const uno::Reference< ucb::XCommandEnvironment > & xEnv )
470 {
471  osl::Guard< osl::Mutex > aGuard( m_aMutex );
472 
473  uno::Sequence< ucb::CommandInfo > aCmdInfo( 10 );
474 
475 
476  // Mandatory commands
477 
478 
479  aCmdInfo[ 0 ] =
480  ucb::CommandInfo(
481  "getCommandInfo",
482  -1,
484  aCmdInfo[ 1 ] =
485  ucb::CommandInfo(
486  "getPropertySetInfo",
487  -1,
489  aCmdInfo[ 2 ] =
490  ucb::CommandInfo(
491  "getPropertyValues",
492  -1,
493  cppu::UnoType<uno::Sequence< beans::Property >>::get());
494  aCmdInfo[ 3 ] =
495  ucb::CommandInfo(
496  "setPropertyValues",
497  -1,
498  cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get());
499 
500 
501  // Optional standard commands
502 
503 
504  aCmdInfo[ 4 ] =
505  ucb::CommandInfo(
506  "delete",
507  -1,
509  aCmdInfo[ 5 ] =
510  ucb::CommandInfo(
511  "insert",
512  -1,
514  aCmdInfo[ 6 ] =
515  ucb::CommandInfo(
516  "open",
517  -1,
519 
520 
521  // New commands
522 
523 
524  aCmdInfo[ 7 ] =
525  ucb::CommandInfo(
526  "post",
527  -1,
529  aCmdInfo[ 8 ] =
530  ucb::CommandInfo(
531  "addProperty",
532  -1,
534  aCmdInfo[ 9 ] =
535  ucb::CommandInfo(
536  "removeProperty",
537  -1,
539 
540  bool bFolder = false;
541 
542  try
543  {
544  bFolder = isFolder( xEnv );
545  }
546  catch ( uno::Exception const & )
547  {
548  return aCmdInfo;
549  }
550 
551  bool bSupportsLocking = supportsExclusiveWriteLock( xEnv );
552 
553  sal_Int32 nPos = aCmdInfo.getLength();
554  sal_Int32 nMoreCmds = ( bFolder ? 2 : 0 ) + ( bSupportsLocking ? 2 : 0 );
555  if ( nMoreCmds )
556  aCmdInfo.realloc( nPos + nMoreCmds );
557  else
558  return aCmdInfo;
559 
560  if ( bFolder )
561  {
562 
563  // Optional standard commands
564 
565 
566  aCmdInfo[ nPos ] =
567  ucb::CommandInfo(
568  "transfer",
569  -1,
571  nPos++;
572  aCmdInfo[ nPos ] =
573  ucb::CommandInfo(
574  "createNewContent",
575  -1,
577  nPos++;
578  }
579  else
580  {
581  // no document-only commands at the moment.
582  }
583 
584  if ( bSupportsLocking )
585  {
586  aCmdInfo[ nPos ] =
587  ucb::CommandInfo(
588  "lock",
589  -1,
591  nPos++;
592  aCmdInfo[ nPos ] =
593  ucb::CommandInfo(
594  "unlock",
595  -1,
597  nPos++;
598  }
599  return aCmdInfo;
600 }
601 
602 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 nPos