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 .
20 #include <sal/config.h>
22 #include <rtl/uri.hxx>
26 #include <sys/types.h>
27 #include <sal/macros.h>
29 #include <sal/log.hxx>
31 #include <com/sun/star/beans/IllegalTypeException.hpp>
32 #include <com/sun/star/beans/PropertyValue.hpp>
33 #include <com/sun/star/beans/PropertyAttribute.hpp>
34 #include <com/sun/star/beans/XPropertySetInfo.hpp>
35 #include <com/sun/star/io/IOException.hpp>
36 #include <com/sun/star/io/XActiveDataSink.hpp>
37 #include <com/sun/star/io/XOutputStream.hpp>
38 #include <com/sun/star/lang/IllegalAccessException.hpp>
39 #include <com/sun/star/lang/IllegalArgumentException.hpp>
40 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
41 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
42 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
43 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
44 #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
45 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
46 #include <com/sun/star/ucb/NameClashException.hpp>
47 #include <com/sun/star/ucb/OpenMode.hpp>
48 #include <com/sun/star/ucb/XCommandInfo.hpp>
49 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
50 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
51 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
52 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
53 #include <com/sun/star/ucb/XDynamicResultSet.hpp>
54 #include <com/sun/star/ucb/XContentCreator.hpp>
56 #include <comphelper/seekableinput.hxx>
57 #include <cppuhelper/exc_hlp.hxx>
58 #include <cppuhelper/queryinterface.hxx>
59 #include <ucbhelper/contentidentifier.hxx>
60 #include <ucbhelper/propertyvalueset.hxx>
61 #include <ucbhelper/cancelcommandexecution.hxx>
62 #include <ucbhelper/macros.hxx>
63 #include <vcl/svapp.hxx>
65 #include "gio_content.hxx"
66 #include "gio_provider.hxx"
67 #include "gio_resultset.hxx"
68 #include "gio_inputstream.hxx"
69 #include "gio_outputstream.hxx"
70 #include "gio_mount.hxx"
76 const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
,
77 ContentProvider
* pProvider
,
78 const css::uno::Reference
< css::ucb::XContentIdentifier
>& Identifier
)
79 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
80 m_pProvider( pProvider
), mpFile (nullptr), mpInfo( nullptr ), mbTransient(false)
82 SAL_INFO("ucb.ucp.gio", "New Content ('" << m_xIdentifier
->getContentIdentifier() << "')");
86 const css::uno::Reference
< css::uno::XComponentContext
>& rxContext
,
87 ContentProvider
* pProvider
,
88 const css::uno::Reference
< css::ucb::XContentIdentifier
>& Identifier
,
90 : ContentImplHelper( rxContext
, pProvider
, Identifier
),
91 m_pProvider( pProvider
), mpFile (nullptr), mpInfo( nullptr ), mbTransient(true)
93 SAL_INFO("ucb.ucp.gio", "Create Content ('" << m_xIdentifier
->getContentIdentifier() << "')");
94 mpInfo
= g_file_info_new();
95 g_file_info_set_file_type(mpInfo
, bIsFolder
? G_FILE_TYPE_DIRECTORY
: G_FILE_TYPE_REGULAR
);
100 if (mpInfo
) g_object_unref(mpInfo
);
101 if (mpFile
) g_object_unref(mpFile
);
104 OUString
Content::getParentURL()
107 if (GFile
* pFile
= g_file_get_parent(getGFile()))
109 char* pPath
= g_file_get_uri(pFile
);
110 g_object_unref(pFile
);
111 sURL
= OUString::createFromAscii(pPath
);
117 void SAL_CALL
Content::abort( sal_Int32
/*CommandId*/ )
120 //stick a map from each CommandId to a new GCancellable and propagate
121 //it throughout the g_file_* calls
124 OUString SAL_CALL
Content::getContentType()
126 return isFolder(css::uno::Reference
< css::ucb::XCommandEnvironment
>())
131 #define EXCEPT(aExcept) \
133 if (bThrow) throw aExcept;\
137 css::uno::Any
convertToException(GError
*pError
, const css::uno::Reference
< css::uno::XInterface
>& rContext
, bool bThrow
)
141 gint eCode
= pError
->code
;
142 OUString
sMessage(pError
->message
, strlen(pError
->message
), RTL_TEXTENCODING_UTF8
);
143 g_error_free(pError
);
147 css::uno::Sequence
< css::uno::Any
> aArgs
{ css::uno::Any(sName
) };
151 case G_IO_ERROR_FAILED
:
152 { css::io::IOException
aExcept(sMessage
, rContext
);
155 case G_IO_ERROR_NOT_MOUNTED
:
156 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
157 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_NOT_EXISTING_PATH
, aArgs
);
160 case G_IO_ERROR_NOT_FOUND
:
161 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
162 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_NOT_EXISTING
, aArgs
);
165 case G_IO_ERROR_EXISTS
:
166 { css::ucb::NameClashException
aExcept(sMessage
, rContext
,
167 css::task::InteractionClassification_ERROR
, sName
);
170 case G_IO_ERROR_INVALID_ARGUMENT
:
171 { css::lang::IllegalArgumentException
aExcept(sMessage
, rContext
, -1 );
174 case G_IO_ERROR_PERMISSION_DENIED
:
175 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
176 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_ACCESS_DENIED
, aArgs
);
179 case G_IO_ERROR_IS_DIRECTORY
:
180 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
181 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_NO_FILE
, aArgs
);
184 case G_IO_ERROR_NOT_REGULAR_FILE
:
185 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
186 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_NO_FILE
, aArgs
);
189 case G_IO_ERROR_NOT_DIRECTORY
:
190 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
191 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_NO_DIRECTORY
, aArgs
);
194 case G_IO_ERROR_FILENAME_TOO_LONG
:
195 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
196 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_NAME_TOO_LONG
, aArgs
);
199 case G_IO_ERROR_FAILED_HANDLED
: /* Operation failed and a helper program
200 has already interacted with the user. Do not display any error
202 case G_IO_ERROR_PENDING
:
203 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
204 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_PENDING
, aArgs
);
207 case G_IO_ERROR_CLOSED
:
208 case G_IO_ERROR_CANCELLED
:
209 case G_IO_ERROR_TOO_MANY_LINKS
:
210 case G_IO_ERROR_WRONG_ETAG
:
211 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
212 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_GENERAL
, aArgs
);
215 case G_IO_ERROR_NOT_SUPPORTED
:
216 case G_IO_ERROR_CANT_CREATE_BACKUP
:
217 case G_IO_ERROR_WOULD_MERGE
:
218 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
219 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_NOT_SUPPORTED
, aArgs
);
222 case G_IO_ERROR_NO_SPACE
:
223 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
224 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_OUT_OF_DISK_SPACE
, aArgs
);
227 case G_IO_ERROR_INVALID_FILENAME
:
228 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
229 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_INVALID_CHARACTER
, aArgs
);
232 case G_IO_ERROR_READ_ONLY
:
233 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
234 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_WRITE_PROTECTED
, aArgs
);
237 case G_IO_ERROR_TIMED_OUT
:
238 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
239 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_DEVICE_NOT_READY
, aArgs
);
242 case G_IO_ERROR_WOULD_RECURSE
:
243 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
244 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_RECURSIVE
, aArgs
);
247 case G_IO_ERROR_BUSY
:
248 case G_IO_ERROR_WOULD_BLOCK
:
249 { css::ucb::InteractiveAugmentedIOException
aExcept(sMessage
, rContext
,
250 css::task::InteractionClassification_ERROR
, css::ucb::IOErrorCode_LOCKING_VIOLATION
, aArgs
);
253 case G_IO_ERROR_HOST_NOT_FOUND
:
254 { css::ucb::InteractiveNetworkResolveNameException
aExcept(sMessage
, rContext
,
255 css::task::InteractionClassification_ERROR
, OUString());
259 case G_IO_ERROR_ALREADY_MOUNTED
:
260 case G_IO_ERROR_NOT_EMPTY
:
261 case G_IO_ERROR_NOT_SYMBOLIC_LINK
:
262 case G_IO_ERROR_NOT_MOUNTABLE_FILE
:
263 { css::ucb::InteractiveNetworkGeneralException
aExcept(sMessage
, rContext
,
264 css::task::InteractionClassification_ERROR
);
271 void convertToIOException(GError
*pError
, const css::uno::Reference
< css::uno::XInterface
>& rContext
)
275 convertToException(pError
, rContext
);
277 catch (const css::io::IOException
&)
281 catch (const css::uno::RuntimeException
&)
285 catch (const css::uno::Exception
& e
)
287 css::uno::Any
a(cppu::getCaughtException());
288 throw css::lang::WrappedTargetRuntimeException(
289 "wrapped Exception " + e
.Message
,
290 css::uno::Reference
<css::uno::XInterface
>(), a
);
294 css::uno::Any
Content::mapGIOError( GError
*pError
)
297 return getBadArgExcept();
299 return convertToException(pError
, getXWeak(), false);
302 css::uno::Any
Content::getBadArgExcept()
304 return css::uno::Any( css::lang::IllegalArgumentException(
305 u
"Wrong argument type!"_ustr
,
313 ucb::ucp::gio::glib::MainContextRef mContext
;
315 GMountOperation
*mpAuthentication
;
317 static void Completed(GObject
*source
, GAsyncResult
*res
, gpointer user_data
);
319 explicit MountOperation(const css::uno::Reference
< css::ucb::XCommandEnvironment
>& xEnv
);
321 GError
*Mount(GFile
*pFile
);
326 MountOperation::MountOperation(const css::uno::Reference
< css::ucb::XCommandEnvironment
>& xEnv
) : mpError(nullptr)
328 ucb::ucp::gio::glib::MainContextRef
oldContext(g_main_context_ref_thread_default());
329 mContext
.reset(g_main_context_new());
330 mpLoop
= g_main_loop_new(mContext
.get(), FALSE
);
331 g_main_context_push_thread_default(mContext
.get());
332 mpAuthentication
= ooo_mount_operation_new(std::move(oldContext
), xEnv
);
335 void MountOperation::Completed(GObject
*source
, GAsyncResult
*res
, gpointer user_data
)
337 MountOperation
*pThis
= static_cast<MountOperation
*>(user_data
);
338 g_file_mount_enclosing_volume_finish(G_FILE(source
), res
, &(pThis
->mpError
));
339 g_main_loop_quit(pThis
->mpLoop
);
342 GError
*MountOperation::Mount(GFile
*pFile
)
344 g_file_mount_enclosing_volume(pFile
, G_MOUNT_MOUNT_NONE
, mpAuthentication
, nullptr, MountOperation::Completed
, this);
346 //HACK: At least the gdk_threads_set_lock_functions(GdkThreadsEnter,
347 // GdkThreadsLeave) call in vcl/unx/gtk/app/gtkinst.cxx will lead to
348 // GdkThreadsLeave unlock the SolarMutex down to zero at the end of
349 // g_main_loop_run, so we need ~SolarMutexReleaser to raise it back to
350 // the original value again:
351 if (comphelper::SolarMutex::get()->IsCurrentThread())
353 SolarMutexReleaser rel
;
354 g_main_loop_run(mpLoop
);
358 g_main_loop_run(mpLoop
);
364 MountOperation::~MountOperation()
366 g_object_unref(mpAuthentication
);
367 g_main_context_pop_thread_default(mContext
.get());
368 g_main_loop_unref(mpLoop
);
371 GFileInfo
* Content::getGFileInfo(const css::uno::Reference
< css::ucb::XCommandEnvironment
>& xEnv
, GError
**ppError
)
373 GError
* err
= nullptr;
374 if (mpInfo
== nullptr && !mbTransient
) {
375 for (bool retried
= false;; retried
= true) {
376 mpInfo
= g_file_query_info(
377 getGFile(), "*", G_FILE_QUERY_INFO_NONE
, nullptr, &err
);
378 if (mpInfo
!= nullptr) {
381 assert(err
!= nullptr);
382 if (err
->code
!= G_IO_ERROR_NOT_MOUNTED
|| retried
) {
387 "G_IO_ERROR_NOT_MOUNTED \"" << err
->message
388 << "\", trying to mount");
390 err
= MountOperation(xEnv
).Mount(getGFile());
391 if (err
!= nullptr) {
396 if (ppError
!= nullptr) {
398 } else if (err
!= nullptr) {
401 "ignoring GError \"" << err
->message
<< "\" for <"
402 << m_xIdentifier
->getContentIdentifier() << ">");
408 GFile
* Content::getGFile()
411 mpFile
= g_file_new_for_uri(OUStringToOString(m_xIdentifier
->getContentIdentifier(), RTL_TEXTENCODING_UTF8
).getStr());
415 bool Content::isFolder(const css::uno::Reference
< css::ucb::XCommandEnvironment
>& xEnv
)
417 GFileInfo
*pInfo
= getGFileInfo(xEnv
);
418 return pInfo
&& (g_file_info_get_file_type(pInfo
) == G_FILE_TYPE_DIRECTORY
);
421 static css::util::DateTime
getDateFromUnix (time_t t
)
425 // coverity[store_truncates_time_t] - TODO: sal_uInt32 TimeValue::Seconds is only large enough
426 // for integer time_t values < 2^32 representing dates until year 2106:
430 if ( osl_getDateTimeFromTimeValue( &tv
, &dt
) )
431 return css::util::DateTime( 0, dt
.Seconds
, dt
.Minutes
, dt
.Hours
,
432 dt
.Day
, dt
.Month
, dt
.Year
, false);
434 return css::util::DateTime();
437 css::uno::Reference
< css::sdbc::XRow
> Content::getPropertyValues(
438 const css::uno::Sequence
< css::beans::Property
>& rProperties
,
439 const css::uno::Reference
< css::ucb::XCommandEnvironment
>& xEnv
)
441 rtl::Reference
< ::ucbhelper::PropertyValueSet
> xRow
= new ::ucbhelper::PropertyValueSet( m_xContext
);
443 GFileInfo
*pInfo
= nullptr;
444 for( const css::beans::Property
& rProp
: rProperties
)
446 if ( rProp
.Name
== "IsDocument" )
448 getFileInfo(xEnv
, &pInfo
, true);
449 if (pInfo
!= nullptr && g_file_info_has_attribute(pInfo
, G_FILE_ATTRIBUTE_STANDARD_TYPE
))
450 xRow
->appendBoolean( rProp
, ( g_file_info_get_file_type( pInfo
) == G_FILE_TYPE_REGULAR
||
451 g_file_info_get_file_type( pInfo
) == G_FILE_TYPE_UNKNOWN
) );
453 xRow
->appendVoid( rProp
);
455 else if ( rProp
.Name
== "IsFolder" )
457 getFileInfo(xEnv
, &pInfo
, true);
458 if (pInfo
!= nullptr && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_STANDARD_TYPE
) )
459 xRow
->appendBoolean( rProp
, ( g_file_info_get_file_type( pInfo
) == G_FILE_TYPE_DIRECTORY
));
461 xRow
->appendVoid( rProp
);
463 else if ( rProp
.Name
== "Title" )
465 getFileInfo(xEnv
, &pInfo
, false);
466 if (pInfo
!= nullptr && g_file_info_has_attribute(pInfo
, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME
))
468 const char *pName
= g_file_info_get_display_name(pInfo
);
469 xRow
->appendString( rProp
, OUString(pName
, strlen(pName
), RTL_TEXTENCODING_UTF8
) );
472 xRow
->appendVoid(rProp
);
474 else if ( rProp
.Name
== "IsReadOnly" )
476 getFileInfo(xEnv
, &pInfo
, true);
477 if (pInfo
!= nullptr && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
) )
478 xRow
->appendBoolean( rProp
, !g_file_info_get_attribute_boolean( pInfo
, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
) );
480 xRow
->appendVoid( rProp
);
482 else if ( rProp
.Name
== "DateCreated" )
484 getFileInfo(xEnv
, &pInfo
, true);
485 if (pInfo
!= nullptr && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_TIME_CREATED
) )
486 xRow
->appendTimestamp( rProp
, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo
, G_FILE_ATTRIBUTE_TIME_CREATED
)) );
488 xRow
->appendVoid( rProp
);
490 else if ( rProp
.Name
== "DateModified" )
492 getFileInfo(xEnv
, &pInfo
, true);
493 if (pInfo
!= nullptr && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_TIME_CHANGED
) )
494 xRow
->appendTimestamp( rProp
, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo
, G_FILE_ATTRIBUTE_TIME_CHANGED
)) );
496 xRow
->appendVoid( rProp
);
498 else if ( rProp
.Name
== "Size" )
500 getFileInfo(xEnv
, &pInfo
, true);
501 if (pInfo
!= nullptr && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_STANDARD_SIZE
) )
502 xRow
->appendLong( rProp
, ( g_file_info_get_size( pInfo
) ));
504 xRow
->appendVoid( rProp
);
506 else if ( rProp
.Name
== "IsVolume" )
508 //What do we use this for ?
509 xRow
->appendBoolean( rProp
, false );
511 else if ( rProp
.Name
== "IsCompactDisc" )
513 getFileInfo(xEnv
, &pInfo
, true);
514 if (pInfo
!= nullptr && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT
) )
515 xRow
->appendBoolean( rProp
, g_file_info_get_attribute_boolean(pInfo
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT
) );
517 xRow
->appendVoid( rProp
);
519 else if ( rProp
.Name
== "IsRemoveable" )
521 getFileInfo(xEnv
, &pInfo
, true);
522 if (pInfo
!= nullptr && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT
) )
523 xRow
->appendBoolean( rProp
, g_file_info_get_attribute_boolean(pInfo
, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT
) );
525 xRow
->appendVoid( rProp
);
527 else if ( rProp
.Name
== "IsFloppy" )
529 xRow
->appendBoolean( rProp
, false );
531 else if ( rProp
.Name
== "IsHidden" )
533 getFileInfo(xEnv
, &pInfo
, true);
534 if (pInfo
!= nullptr && g_file_info_has_attribute( pInfo
, G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN
) )
535 xRow
->appendBoolean( rProp
, ( g_file_info_get_is_hidden ( pInfo
) ) );
537 xRow
->appendVoid( rProp
);
539 else if ( rProp
.Name
== "CreatableContentsInfo" )
541 xRow
->appendObject( rProp
, css::uno::Any( queryCreatableContentsInfo( xEnv
) ) );
547 "Looking for unsupported property " << rProp
.Name
);
548 xRow
->appendVoid(rProp
);
555 static css::lang::IllegalAccessException
556 getReadOnlyException( const css::uno::Reference
< css::uno::XInterface
>& rContext
)
558 return css::lang::IllegalAccessException (u
"Property is read-only!"_ustr
, rContext
);
561 void Content::queryChildren( ContentRefList
& rChildren
)
563 // Obtain a list with a snapshot of all currently instantiated contents
564 // from provider and extract the contents which are direct children
567 ucbhelper::ContentRefList aAllContents
;
568 m_xProvider
->queryExistingContents( aAllContents
);
570 OUString aURL
= m_xIdentifier
->getContentIdentifier();
571 sal_Int32 nURLPos
= aURL
.lastIndexOf( '/' );
573 if ( nURLPos
!= ( aURL
.getLength() - 1 ) )
576 sal_Int32 nLen
= aURL
.getLength();
578 for ( const auto& rContent
: aAllContents
)
580 ucbhelper::ContentImplHelperRef xChild
= rContent
;
581 OUString aChildURL
= xChild
->getIdentifier()->getContentIdentifier();
583 // Is aURL a prefix of aChildURL?
584 if ( ( aChildURL
.getLength() > nLen
) && aChildURL
.startsWith( aURL
) )
586 sal_Int32 nPos
= aChildURL
.indexOf( '/', nLen
);
588 if ( ( nPos
== -1 ) || ( nPos
== ( aChildURL
.getLength() - 1 ) ) )
590 // No further slashes / only a final slash. It's a child!
591 rChildren
.emplace_back(static_cast< ::gio::Content
* >(xChild
.get() ) );
597 bool Content::exchangeIdentity( const css::uno::Reference
< css::ucb::XContentIdentifier
>& xNewId
)
602 css::uno::Reference
< css::ucb::XContent
> xThis
= this;
606 m_xIdentifier
= xNewId
;
610 OUString aOldURL
= m_xIdentifier
->getContentIdentifier();
612 // Exchange own identity.
613 if ( exchange( xNewId
) )
615 // Process instantiated children...
616 ContentRefList aChildren
;
617 queryChildren( aChildren
);
619 for ( const auto& rChild
: aChildren
)
621 ContentRef xChild
= rChild
;
623 // Create new content identifier for the child...
624 css::uno::Reference
< css::ucb::XContentIdentifier
> xOldChildId
= xChild
->getIdentifier();
625 OUString aOldChildURL
= xOldChildId
->getContentIdentifier();
626 OUString aNewChildURL
= aOldChildURL
.replaceAt(
627 0, aOldURL
.getLength(), xNewId
->getContentIdentifier() );
629 css::uno::Reference
< css::ucb::XContentIdentifier
> xNewChildId
630 = new ::ucbhelper::ContentIdentifier( aNewChildURL
);
632 if ( !xChild
->exchangeIdentity( xNewChildId
) )
641 void Content::getFileInfo(
642 css::uno::Reference
<css::ucb::XCommandEnvironment
> const & env
, GFileInfo
** info
, bool fail
)
644 assert(info
!= nullptr);
645 if (*info
!= nullptr)
648 GError
* err
= nullptr;
649 *info
= getGFileInfo(env
, &err
);
650 if (*info
== nullptr && !mbTransient
&& fail
)
652 ucbhelper::cancelCommandExecution(mapGIOError(err
), env
);
654 else if (err
!= nullptr)
660 css::uno::Sequence
< css::uno::Any
> Content::setPropertyValues(
661 const css::uno::Sequence
< css::beans::PropertyValue
>& rValues
,
662 const css::uno::Reference
< css::ucb::XCommandEnvironment
>& xEnv
)
664 GError
*pError
=nullptr;
665 GFileInfo
*pNewInfo
=nullptr;
666 GFileInfo
*pInfo
= getGFileInfo(xEnv
, &pError
);
668 pNewInfo
= g_file_info_dup(pInfo
);
672 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
676 g_error_free(pError
);
677 pNewInfo
= g_file_info_new();
681 sal_Int32 nCount
= rValues
.getLength();
683 css::beans::PropertyChangeEvent aEvent
;
684 aEvent
.Source
= getXWeak();
685 aEvent
.Further
= false;
686 aEvent
.PropertyHandle
= -1;
688 sal_Int32 nChanged
= 0, nTitlePos
= -1;
690 css::uno::Sequence
< css::beans::PropertyChangeEvent
> aChanges(nCount
);
691 auto aChangesRange
= asNonConstRange(aChanges
);
693 css::uno::Sequence
< css::uno::Any
> aRet( nCount
);
694 auto aRetRange
= asNonConstRange(aRet
);
695 const css::beans::PropertyValue
* pValues
= rValues
.getConstArray();
696 for ( sal_Int32 n
= 0; n
< nCount
; ++n
)
698 const css::beans::PropertyValue
& rValue
= pValues
[ n
];
699 SAL_INFO("ucb.ucp.gio", "Set prop '" << rValue
.Name
<< "'");
700 if ( rValue
.Name
== "ContentType" ||
701 rValue
.Name
== "MediaType" ||
702 rValue
.Name
== "IsDocument" ||
703 rValue
.Name
== "IsFolder" ||
704 rValue
.Name
== "Size" ||
705 rValue
.Name
== "CreatableContentsInfo" )
707 aRetRange
[ n
] <<= getReadOnlyException( getXWeak() );
709 else if ( rValue
.Name
== "Title" )
711 if (!( rValue
.Value
>>= aNewTitle
))
713 aRetRange
[ n
] <<= css::beans::IllegalTypeException
714 ( u
"Property value has wrong type!"_ustr
,
719 if ( aNewTitle
.isEmpty() )
721 aRetRange
[ n
] <<= css::lang::IllegalArgumentException
722 ( u
"Empty title not allowed!"_ustr
,
728 OString sNewTitle
= OUStringToOString(aNewTitle
, RTL_TEXTENCODING_UTF8
);
729 const char *newName
= sNewTitle
.getStr();
730 const char *oldName
= g_file_info_get_name( pInfo
);
732 if (!newName
|| !oldName
|| strcmp(newName
, oldName
))
734 SAL_INFO("ucb.ucp.gio", "Set new name to '" << newName
<< "'");
736 aEvent
.PropertyName
= "Title";
738 aEvent
.OldValue
<<= OUString(oldName
, strlen(oldName
), RTL_TEXTENCODING_UTF8
);
739 aEvent
.NewValue
<<= aNewTitle
;
740 aChangesRange
[ nChanged
] = aEvent
;
741 nTitlePos
= nChanged
++;
743 g_file_info_set_name(pNewInfo
, newName
);
748 SAL_WARN("ucb.ucp.gio", "Unknown property " << rValue
.Name
);
749 aRetRange
[ n
] <<= getReadOnlyException( getXWeak() );
758 if ((bOk
= doSetFileInfo(pNewInfo
)))
760 for (sal_Int32 i
= 0; i
< nChanged
; ++i
)
761 aRetRange
[ i
] = getBadArgExcept();
769 OUString aNewURL
= getParentURL();
770 if (!aNewURL
.isEmpty() && aNewURL
[aNewURL
.getLength() - 1] != '/')
772 aNewURL
+= aNewTitle
;
774 css::uno::Reference
< css::ucb::XContentIdentifier
> xNewId
775 = new ::ucbhelper::ContentIdentifier( aNewURL
);
777 if (!exchangeIdentity( xNewId
) )
779 aRetRange
[ nTitlePos
] <<= css::uno::Exception
780 ( u
"Exchange failed!"_ustr
,
785 if (!mbTransient
) //Discard and refetch
787 g_object_unref(mpInfo
);
793 g_file_info_copy_into(pNewInfo
, mpInfo
);
794 g_object_unref(pNewInfo
);
801 if (mpFile
) //Discard and refetch
803 g_object_unref(mpFile
);
808 aChanges
.realloc( nChanged
);
809 notifyPropertiesChange( aChanges
);
813 g_object_unref(pNewInfo
);
818 bool Content::doSetFileInfo(GFileInfo
*pNewInfo
)
820 g_assert (!mbTransient
);
823 GFile
*pFile
= getGFile();
824 if(!g_file_set_attributes_from_info(pFile
, pNewInfo
, G_FILE_QUERY_INFO_NONE
, nullptr, nullptr))
829 const int TRANSFER_BUFFER_SIZE
= 65536;
831 void Content::copyData( const css::uno::Reference
< css::io::XInputStream
>& xIn
,
832 const css::uno::Reference
< css::io::XOutputStream
>& xOut
)
834 css::uno::Sequence
< sal_Int8
> theData( TRANSFER_BUFFER_SIZE
);
836 g_return_if_fail( xIn
.is() && xOut
.is() );
838 while ( xIn
->readBytes( theData
, TRANSFER_BUFFER_SIZE
) > 0 )
839 xOut
->writeBytes( theData
);
844 bool Content::feedSink( const css::uno::Reference
< css::uno::XInterface
>& xSink
)
849 css::uno::Reference
< css::io::XOutputStream
> xOut(xSink
, css::uno::UNO_QUERY
);
850 css::uno::Reference
< css::io::XActiveDataSink
> xDataSink(xSink
, css::uno::UNO_QUERY
);
852 if ( !xOut
.is() && !xDataSink
.is() )
855 GError
*pError
=nullptr;
856 GFileInputStream
*pStream
= g_file_read(getGFile(), nullptr, &pError
);
858 convertToException(pError
, getXWeak());
860 css::uno::Reference
< css::io::XInputStream
> xIn(
861 new comphelper::OSeekableInputWrapper(
862 new ::gio::InputStream(pStream
), m_xContext
));
865 copyData( xIn
, xOut
);
867 if ( xDataSink
.is() )
868 xDataSink
->setInputStream( xIn
);
873 css::uno::Any
Content::open(const css::ucb::OpenCommandArgument2
& rOpenCommand
,
874 const css::uno::Reference
< css::ucb::XCommandEnvironment
> & xEnv
)
876 bool bIsFolder
= isFolder(xEnv
);
878 if (!g_file_query_exists(getGFile(), nullptr))
880 css::uno::Sequence
< css::uno::Any
> aArgs
{ css::uno::Any(
881 m_xIdentifier
->getContentIdentifier()) };
883 css::ucb::InteractiveAugmentedIOException(OUString(), getXWeak(),
884 css::task::InteractionClassification_ERROR
,
885 bIsFolder
? css::ucb::IOErrorCode_NOT_EXISTING_PATH
: css::ucb::IOErrorCode_NOT_EXISTING
, aArgs
)
888 ucbhelper::cancelCommandExecution(aErr
, xEnv
);
894 ( rOpenCommand
.Mode
== css::ucb::OpenMode::ALL
) ||
895 ( rOpenCommand
.Mode
== css::ucb::OpenMode::FOLDERS
) ||
896 ( rOpenCommand
.Mode
== css::ucb::OpenMode::DOCUMENTS
)
899 if ( bOpenFolder
&& bIsFolder
)
901 css::uno::Reference
< css::ucb::XDynamicResultSet
> xSet
902 = new DynamicResultSet( m_xContext
, this, rOpenCommand
, xEnv
);
905 else if ( rOpenCommand
.Sink
.is() )
908 ( rOpenCommand
.Mode
== css::ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE
) ||
909 ( rOpenCommand
.Mode
== css::ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE
)
912 ucbhelper::cancelCommandExecution(
913 css::uno::Any ( css::ucb::UnsupportedOpenModeException
914 ( OUString(), getXWeak(),
915 sal_Int16( rOpenCommand
.Mode
) ) ),
919 if ( !feedSink( rOpenCommand
.Sink
) )
921 // Note: rOpenCommand.Sink may contain an XStream
922 // implementation. Support for this type of
923 // sink is optional...
924 SAL_WARN("ucb.ucp.gio", "Failed to load data from '" << m_xIdentifier
->getContentIdentifier() << "'");
926 ucbhelper::cancelCommandExecution(
927 css::uno::Any (css::ucb::UnsupportedDataSinkException
928 ( OUString(), getXWeak(),
929 rOpenCommand
.Sink
) ),
934 SAL_INFO("ucb.ucp.gio", "Open falling through ...");
938 css::uno::Any SAL_CALL
Content::execute(
939 const css::ucb::Command
& aCommand
,
940 sal_Int32
/*CommandId*/,
941 const css::uno::Reference
< css::ucb::XCommandEnvironment
>& xEnv
)
943 SAL_INFO("ucb.ucp.gio", "Content::execute " << aCommand
.Name
);
946 if ( aCommand
.Name
== "getPropertyValues" )
948 css::uno::Sequence
< css::beans::Property
> Properties
;
949 if ( !( aCommand
.Argument
>>= Properties
) )
950 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
951 aRet
<<= getPropertyValues( Properties
, xEnv
);
953 else if ( aCommand
.Name
== "getPropertySetInfo" )
954 aRet
<<= getPropertySetInfo( xEnv
, false );
955 else if ( aCommand
.Name
== "getCommandInfo" )
956 aRet
<<= getCommandInfo( xEnv
, false );
957 else if ( aCommand
.Name
== "open" )
959 css::ucb::OpenCommandArgument2 aOpenCommand
;
960 if ( !( aCommand
.Argument
>>= aOpenCommand
) )
961 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
962 aRet
= open( aOpenCommand
, xEnv
);
964 else if ( aCommand
.Name
== "transfer" )
966 css::ucb::TransferInfo transferArgs
;
967 if ( !( aCommand
.Argument
>>= transferArgs
) )
968 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
969 transfer( transferArgs
, xEnv
);
971 else if ( aCommand
.Name
== "setPropertyValues" )
973 css::uno::Sequence
< css::beans::PropertyValue
> aProperties
;
974 if ( !( aCommand
.Argument
>>= aProperties
) || !aProperties
.hasElements() )
975 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
976 aRet
<<= setPropertyValues( aProperties
, xEnv
);
978 else if (aCommand
.Name
== "createNewContent"
979 && isFolder( xEnv
) )
981 css::ucb::ContentInfo arg
;
982 if ( !( aCommand
.Argument
>>= arg
) )
983 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
984 aRet
<<= createNewContent( arg
);
986 else if ( aCommand
.Name
== "insert" )
988 css::ucb::InsertCommandArgument arg
;
989 if ( !( aCommand
.Argument
>>= arg
) )
990 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv
);
991 insert( arg
.Data
, arg
.ReplaceExisting
, xEnv
);
993 else if ( aCommand
.Name
== "delete" )
995 bool bDeletePhysical
= false;
996 aCommand
.Argument
>>= bDeletePhysical
;
998 //If no delete physical, try and trashcan it, if that doesn't work go
999 //ahead and try and delete it anyway
1000 if (!bDeletePhysical
&& !g_file_trash(getGFile(), nullptr, nullptr))
1001 bDeletePhysical
= true;
1003 if (bDeletePhysical
)
1005 GError
*pError
= nullptr;
1006 if (!g_file_delete( getGFile(), nullptr, &pError
))
1007 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1010 destroy( bDeletePhysical
);
1014 SAL_WARN("ucb.ucp.gio", "Unknown command " << aCommand
.Name
);
1016 ucbhelper::cancelCommandExecution
1017 ( css::uno::Any( css::ucb::UnsupportedCommandException
1026 void Content::destroy( bool bDeletePhysical
)
1028 css::uno::Reference
< css::ucb::XContent
> xThis
= this;
1032 ::gio::Content::ContentRefList aChildren
;
1033 queryChildren( aChildren
);
1035 for ( auto& rChild
: aChildren
)
1037 rChild
->destroy( bDeletePhysical
);
1041 void Content::insert(const css::uno::Reference
< css::io::XInputStream
> &xInputStream
,
1042 bool bReplaceExisting
, const css::uno::Reference
< css::ucb::XCommandEnvironment
> &xEnv
)
1044 GError
*pError
= nullptr;
1045 GFileInfo
*pInfo
= getGFileInfo(xEnv
);
1048 g_file_info_has_attribute(pInfo
, G_FILE_ATTRIBUTE_STANDARD_TYPE
) &&
1049 g_file_info_get_file_type(pInfo
) == G_FILE_TYPE_DIRECTORY
)
1051 SAL_INFO("ucb.ucp.gio", "Make directory");
1052 if( !g_file_make_directory( getGFile(), nullptr, &pError
))
1053 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1057 if ( !xInputStream
.is() )
1059 ucbhelper::cancelCommandExecution( css::uno::Any
1060 ( css::ucb::MissingInputStreamException
1061 ( OUString(), getXWeak() ) ),
1065 GFileOutputStream
* pOutStream
= nullptr;
1066 if ( bReplaceExisting
)
1068 if (!(pOutStream
= g_file_replace(getGFile(), nullptr, false, G_FILE_CREATE_PRIVATE
, nullptr, &pError
)))
1069 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1073 if (!(pOutStream
= g_file_create (getGFile(), G_FILE_CREATE_PRIVATE
, nullptr, &pError
)))
1074 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1077 css::uno::Reference
< css::io::XOutputStream
> xOutput
= new ::gio::OutputStream(pOutStream
);
1078 copyData( xInputStream
, xOutput
);
1082 mbTransient
= false;
1087 const GFileCopyFlags DEFAULT_COPYDATA_FLAGS
=
1088 static_cast<GFileCopyFlags
>(G_FILE_COPY_OVERWRITE
|G_FILE_COPY_TARGET_DEFAULT_PERMS
);
1090 void Content::transfer( const css::ucb::TransferInfo
& aTransferInfo
, const css::uno::Reference
< css::ucb::XCommandEnvironment
>& xEnv
)
1092 OUString sDest
= m_xIdentifier
->getContentIdentifier();
1093 if (!sDest
.endsWith("/")) {
1096 if (!aTransferInfo
.NewTitle
.isEmpty())
1098 sDest
+= rtl::Uri::encode( aTransferInfo
.NewTitle
,
1099 rtl_UriCharClassPchar
,
1100 rtl_UriEncodeIgnoreEscapes
,
1101 RTL_TEXTENCODING_UTF8
);
1104 sDest
+= OUString::createFromAscii(g_file_get_basename(getGFile()));
1106 GFile
*pDest
= g_file_new_for_uri(OUStringToOString(sDest
, RTL_TEXTENCODING_UTF8
).getStr());
1107 GFile
*pSource
= g_file_new_for_uri(OUStringToOString(aTransferInfo
.SourceURL
, RTL_TEXTENCODING_UTF8
).getStr());
1109 bool bSuccess
= false;
1110 GError
*pError
= nullptr;
1111 if (aTransferInfo
.MoveData
)
1112 bSuccess
= g_file_move(pSource
, pDest
, G_FILE_COPY_OVERWRITE
, nullptr, nullptr, nullptr, &pError
);
1114 bSuccess
= g_file_copy(pSource
, pDest
, DEFAULT_COPYDATA_FLAGS
, nullptr, nullptr, nullptr, &pError
);
1115 g_object_unref(pSource
);
1116 g_object_unref(pDest
);
1120 "transfer <" << aTransferInfo
.SourceURL
<< "> to <" << sDest
<< "> (MoveData = "
1121 << int(aTransferInfo
.MoveData
) << ") failed with \"" << pError
->message
<< "\"");
1122 ucbhelper::cancelCommandExecution(mapGIOError(pError
), xEnv
);
1126 css::uno::Sequence
< css::ucb::ContentInfo
> Content::queryCreatableContentsInfo(
1127 const css::uno::Reference
< css::ucb::XCommandEnvironment
>& xEnv
)
1129 if ( isFolder( xEnv
) )
1132 // Minimum set of props we really need
1133 css::uno::Sequence
< css::beans::Property
> props
1135 { u
"Title"_ustr
, -1, cppu::UnoType
<OUString
>::get(), css::beans::PropertyAttribute::MAYBEVOID
| css::beans::PropertyAttribute::BOUND
}
1140 { GIO_FILE_TYPE
, ( css::ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM
| css::ucb::ContentInfoAttribute::KIND_DOCUMENT
), props
},
1141 { GIO_FOLDER_TYPE
, css::ucb::ContentInfoAttribute::KIND_FOLDER
, props
}
1150 css::uno::Sequence
< css::ucb::ContentInfo
> SAL_CALL
Content::queryCreatableContentsInfo()
1152 return queryCreatableContentsInfo( css::uno::Reference
< css::ucb::XCommandEnvironment
>() );
1155 css::uno::Reference
< css::ucb::XContent
>
1156 SAL_CALL
Content::createNewContent( const css::ucb::ContentInfo
& Info
)
1158 bool create_document
;
1161 if ( Info
.Type
== GIO_FILE_TYPE
)
1162 create_document
= true;
1163 else if ( Info
.Type
== GIO_FOLDER_TYPE
)
1164 create_document
= false;
1167 SAL_WARN("ucb.ucp.gio", "Failed to create new content '" << Info
.Type
<< "'");
1168 return css::uno::Reference
< css::ucb::XContent
>();
1171 SAL_INFO("ucb.ucp.gio", "createNewContent (" << create_document
<< ")");
1172 OUString aURL
= m_xIdentifier
->getContentIdentifier();
1174 if ( ( aURL
.lastIndexOf( '/' ) + 1 ) != aURL
.getLength() )
1177 name
= create_document
? "[New_Content]" : "[New_Collection]";
1178 aURL
+= OUString::createFromAscii( name
);
1180 css::uno::Reference
< css::ucb::XContentIdentifier
> xId(new ::ucbhelper::ContentIdentifier(aURL
));
1184 return new ::gio::Content( m_xContext
, m_pProvider
, xId
, !create_document
);
1185 } catch ( css::ucb::ContentCreationException
& )
1187 return css::uno::Reference
< css::ucb::XContent
>();
1191 css::uno::Sequence
< css::uno::Type
> SAL_CALL
Content::getTypes()
1193 if ( isFolder( css::uno::Reference
< css::ucb::XCommandEnvironment
>() ) )
1195 static cppu::OTypeCollection s_aFolderCollection
1196 (CPPU_TYPE_REF( css::lang::XTypeProvider
),
1197 CPPU_TYPE_REF( css::lang::XServiceInfo
),
1198 CPPU_TYPE_REF( css::lang::XComponent
),
1199 CPPU_TYPE_REF( css::ucb::XContent
),
1200 CPPU_TYPE_REF( css::ucb::XCommandProcessor
),
1201 CPPU_TYPE_REF( css::beans::XPropertiesChangeNotifier
),
1202 CPPU_TYPE_REF( css::ucb::XCommandInfoChangeNotifier
),
1203 CPPU_TYPE_REF( css::beans::XPropertyContainer
),
1204 CPPU_TYPE_REF( css::beans::XPropertySetInfoChangeNotifier
),
1205 CPPU_TYPE_REF( css::container::XChild
),
1206 CPPU_TYPE_REF( css::ucb::XContentCreator
) );
1207 return s_aFolderCollection
.getTypes();
1211 static cppu::OTypeCollection s_aFileCollection
1212 (CPPU_TYPE_REF( css::lang::XTypeProvider
),
1213 CPPU_TYPE_REF( css::lang::XServiceInfo
),
1214 CPPU_TYPE_REF( css::lang::XComponent
),
1215 CPPU_TYPE_REF( css::ucb::XContent
),
1216 CPPU_TYPE_REF( css::ucb::XCommandProcessor
),
1217 CPPU_TYPE_REF( css::beans::XPropertiesChangeNotifier
),
1218 CPPU_TYPE_REF( css::ucb::XCommandInfoChangeNotifier
),
1219 CPPU_TYPE_REF( css::beans::XPropertyContainer
),
1220 CPPU_TYPE_REF( css::beans::XPropertySetInfoChangeNotifier
),
1221 CPPU_TYPE_REF( css::container::XChild
) );
1223 return s_aFileCollection
.getTypes();
1227 css::uno::Sequence
< css::beans::Property
> Content::getProperties(
1228 const css::uno::Reference
< css::ucb::XCommandEnvironment
> & /*xEnv*/ )
1230 static const css::beans::Property aGenericProperties
[] =
1232 css::beans::Property( u
"IsDocument"_ustr
,
1233 -1, cppu::UnoType
<bool>::get(),
1234 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1235 css::beans::Property( u
"IsFolder"_ustr
,
1236 -1, cppu::UnoType
<bool>::get(),
1237 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1238 css::beans::Property( u
"Title"_ustr
,
1239 -1, cppu::UnoType
<OUString
>::get(),
1240 css::beans::PropertyAttribute::BOUND
),
1241 css::beans::Property( u
"IsReadOnly"_ustr
,
1242 -1, cppu::UnoType
<bool>::get(),
1243 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1244 css::beans::Property( u
"DateCreated"_ustr
,
1245 -1, cppu::UnoType
<css::util::DateTime
>::get(),
1246 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1247 css::beans::Property( u
"DateModified"_ustr
,
1248 -1, cppu::UnoType
<css::util::DateTime
>::get(),
1249 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1250 css::beans::Property( u
"Size"_ustr
,
1251 -1, cppu::UnoType
<sal_Int64
>::get(),
1252 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1253 css::beans::Property( u
"IsVolume"_ustr
,
1254 1, cppu::UnoType
<bool>::get(),
1255 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1256 css::beans::Property( u
"IsCompactDisc"_ustr
,
1257 -1, cppu::UnoType
<bool>::get(),
1258 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1259 css::beans::Property( u
"IsRemoveable"_ustr
,
1260 -1, cppu::UnoType
<bool>::get(),
1261 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1262 css::beans::Property( u
"IsHidden"_ustr
,
1263 -1, cppu::UnoType
<bool>::get(),
1264 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
),
1265 css::beans::Property( u
"CreatableContentsInfo"_ustr
,
1266 -1, cppu::UnoType
<css::uno::Sequence
< css::ucb::ContentInfo
>>::get(),
1267 css::beans::PropertyAttribute::BOUND
| css::beans::PropertyAttribute::READONLY
)
1270 const int nProps
= SAL_N_ELEMENTS(aGenericProperties
);
1271 return css::uno::Sequence
< css::beans::Property
> ( aGenericProperties
, nProps
);
1274 css::uno::Sequence
< css::ucb::CommandInfo
> Content::getCommands( const css::uno::Reference
< css::ucb::XCommandEnvironment
> & xEnv
)
1276 static const css::ucb::CommandInfo aCommandInfoTable
[] =
1278 // Required commands
1279 css::ucb::CommandInfo
1280 ( u
"getCommandInfo"_ustr
,
1281 -1, cppu::UnoType
<void>::get() ),
1282 css::ucb::CommandInfo
1283 ( u
"getPropertySetInfo"_ustr
,
1284 -1, cppu::UnoType
<void>::get() ),
1285 css::ucb::CommandInfo
1286 ( u
"getPropertyValues"_ustr
,
1287 -1, cppu::UnoType
<css::uno::Sequence
< css::beans::Property
>>::get() ),
1288 css::ucb::CommandInfo
1289 ( u
"setPropertyValues"_ustr
,
1290 -1, cppu::UnoType
<css::uno::Sequence
< css::beans::PropertyValue
>>::get() ),
1292 // Optional standard commands
1293 css::ucb::CommandInfo
1295 -1, cppu::UnoType
<bool>::get() ),
1296 css::ucb::CommandInfo
1298 -1, cppu::UnoType
<css::ucb::InsertCommandArgument
>::get() ),
1299 css::ucb::CommandInfo
1301 -1, cppu::UnoType
<css::ucb::OpenCommandArgument2
>::get() ),
1303 // Folder Only, omitted if not a folder
1304 css::ucb::CommandInfo
1306 -1, cppu::UnoType
<css::ucb::TransferInfo
>::get() ),
1307 css::ucb::CommandInfo
1308 ( u
"createNewContent"_ustr
,
1309 -1, cppu::UnoType
<css::ucb::ContentInfo
>::get() )
1312 const int nProps
= SAL_N_ELEMENTS(aCommandInfoTable
);
1313 return css::uno::Sequence
< css::ucb::CommandInfo
>(aCommandInfoTable
, isFolder(xEnv
) ? nProps
: nProps
- 2);
1316 XTYPEPROVIDER_COMMON_IMPL( Content
);
1318 void SAL_CALL
Content::acquire() noexcept
1320 ContentImplHelper::acquire();
1323 void SAL_CALL
Content::release() noexcept
1325 ContentImplHelper::release();
1328 css::uno::Any SAL_CALL
Content::queryInterface( const css::uno::Type
& rType
)
1330 css::uno::Any aRet
= cppu::queryInterface( rType
, static_cast< css::ucb::XContentCreator
* >( this ) );
1331 return aRet
.hasValue() ? aRet
: ContentImplHelper::queryInterface(rType
);
1334 OUString SAL_CALL
Content::getImplementationName()
1336 return u
"com.sun.star.comp.GIOContent"_ustr
;
1339 css::uno::Sequence
< OUString
> SAL_CALL
Content::getSupportedServiceNames()
1341 css::uno::Sequence
<OUString
> aSNS
{ u
"com.sun.star.ucb.GIOContent"_ustr
};
1347 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */