Line data Source code
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 <string.h>
21 : #include <unistd.h>
22 : #include <sys/types.h>
23 : #include <sal/macros.h>
24 : #include <osl/time.h>
25 :
26 : #include <osl/diagnose.h>
27 : #include <osl/doublecheckedlocking.h>
28 :
29 : #include <com/sun/star/beans/PropertyValue.hpp>
30 : #include <com/sun/star/beans/PropertyAttribute.hpp>
31 : #include <com/sun/star/beans/PropertySetInfoChange.hpp>
32 : #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
33 : #include <com/sun/star/io/XActiveDataSink.hpp>
34 : #include <com/sun/star/io/XOutputStream.hpp>
35 : #include <com/sun/star/lang/IllegalAccessException.hpp>
36 : #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
37 : #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
38 : #include <com/sun/star/ucb/InsertCommandArgument.hpp>
39 : #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
40 : #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
41 : #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
42 : #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
43 : #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
44 : #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
45 : #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
46 : #include <com/sun/star/ucb/NameClash.hpp>
47 : #include <com/sun/star/ucb/NameClashException.hpp>
48 : #include <com/sun/star/ucb/OpenMode.hpp>
49 : #include <com/sun/star/ucb/PostCommandArgument2.hpp>
50 : #include <com/sun/star/ucb/XCommandInfo.hpp>
51 : #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
52 : #include <com/sun/star/ucb/MissingInputStreamException.hpp>
53 : #include <com/sun/star/ucb/MissingPropertiesException.hpp>
54 : #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
55 : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
56 : #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
57 : #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
58 : #include <com/sun/star/ucb/XDynamicResultSet.hpp>
59 : #include <com/sun/star/ucb/XContentCreator.hpp>
60 :
61 : #include <comphelper/processfactory.hxx>
62 : #include <cppuhelper/exc_hlp.hxx>
63 : #include <ucbhelper/contentidentifier.hxx>
64 : #include <ucbhelper/propertyvalueset.hxx>
65 : #include <ucbhelper/interactionrequest.hxx>
66 : #include <ucbhelper/cancelcommandexecution.hxx>
67 : #include <vcl/svapp.hxx>
68 :
69 : #include <osl/conditn.hxx>
70 :
71 : #include "gio_content.hxx"
72 : #include "gio_provider.hxx"
73 : #include "gio_resultset.hxx"
74 : #include "gio_inputstream.hxx"
75 : #include "gio_outputstream.hxx"
76 : #include "gio_mount.hxx"
77 :
78 : #include <stdio.h>
79 :
80 : using namespace com::sun::star;
81 :
82 : namespace gio
83 : {
84 :
85 3380 : Content::Content(
86 : const uno::Reference< uno::XComponentContext >& rxContext,
87 : ContentProvider* pProvider,
88 : const uno::Reference< ucb::XContentIdentifier >& Identifier)
89 : throw ( ucb::ContentCreationException )
90 : : ContentImplHelper( rxContext, pProvider, Identifier ),
91 3380 : m_pProvider( pProvider ), mpFile (NULL), mpInfo( NULL ), mbTransient(false)
92 : {
93 : SAL_INFO("ucb.ucp.gio", "New Content ('" << m_xIdentifier->getContentIdentifier() << "')\n");
94 3380 : }
95 :
96 0 : Content::Content(
97 : const uno::Reference< uno::XComponentContext >& rxContext,
98 : ContentProvider* pProvider,
99 : const uno::Reference< ucb::XContentIdentifier >& Identifier,
100 : bool bIsFolder)
101 : throw ( ucb::ContentCreationException )
102 : : ContentImplHelper( rxContext, pProvider, Identifier ),
103 0 : m_pProvider( pProvider ), mpFile (NULL), mpInfo( NULL ), mbTransient(true)
104 : {
105 : SAL_INFO("ucb.ucp.gio", "Create Content ('" << m_xIdentifier->getContentIdentifier() << "')\n");
106 0 : mpInfo = g_file_info_new();
107 0 : g_file_info_set_file_type(mpInfo, bIsFolder ? G_FILE_TYPE_DIRECTORY : G_FILE_TYPE_REGULAR);
108 0 : }
109 :
110 10140 : Content::~Content()
111 : {
112 3380 : if (mpInfo) g_object_unref(mpInfo);
113 3380 : if (mpFile) g_object_unref(mpFile);
114 6760 : }
115 :
116 0 : OUString Content::getParentURL()
117 : {
118 0 : OUString sURL;
119 0 : if (GFile* pFile = g_file_get_parent(getGFile()))
120 : {
121 0 : char* pPath = g_file_get_uri(pFile);
122 0 : g_object_unref(pFile);
123 0 : sURL = OUString::createFromAscii(pPath);
124 0 : g_free(pPath);
125 : }
126 0 : return sURL;
127 : }
128 :
129 0 : void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
130 : throw( uno::RuntimeException, std::exception )
131 : {
132 : //TODO
133 : //stick a map from each CommandId to a new GCancellable and propagate
134 : //it throughout the g_file_* calls
135 0 : }
136 :
137 0 : OUString SAL_CALL Content::getContentType() throw( uno::RuntimeException, std::exception )
138 : {
139 0 : return isFolder(uno::Reference< ucb::XCommandEnvironment >())
140 : ? OUString( GIO_FOLDER_TYPE )
141 0 : : OUString( GIO_FILE_TYPE );
142 : }
143 :
144 : #define EXCEPT(aExcept) \
145 : do { \
146 : if (bThrow) throw aExcept;\
147 : aRet = uno::makeAny( aExcept );\
148 : } while(false)
149 :
150 0 : uno::Any convertToException(GError *pError, const uno::Reference< uno::XInterface >& rContext, bool bThrow)
151 : {
152 0 : uno::Any aRet;
153 :
154 0 : gint eCode = pError->code;
155 0 : OUString sMessage(pError->message, strlen(pError->message), RTL_TEXTENCODING_UTF8);
156 0 : g_error_free(pError);
157 :
158 0 : OUString sName;
159 0 : OUString sHost;
160 :
161 0 : uno::Sequence< uno::Any > aArgs( 1 );
162 0 : aArgs[ 0 ] <<= sName;
163 :
164 0 : switch (eCode)
165 : {
166 : case G_IO_ERROR_FAILED:
167 0 : { io::IOException aExcept(sMessage, rContext);
168 0 : EXCEPT(aExcept); }
169 0 : break;
170 : case G_IO_ERROR_NOT_MOUNTED:
171 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
172 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_EXISTING_PATH, aArgs);
173 0 : EXCEPT(aExcept); }
174 0 : break;
175 : case G_IO_ERROR_NOT_FOUND:
176 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
177 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_EXISTING, aArgs);
178 0 : EXCEPT(aExcept); }
179 0 : break;
180 : case G_IO_ERROR_EXISTS:
181 : { ucb::NameClashException aExcept(sMessage, rContext,
182 0 : task::InteractionClassification_ERROR, sName);
183 0 : EXCEPT(aExcept); }
184 0 : break;
185 : case G_IO_ERROR_INVALID_ARGUMENT:
186 0 : { lang::IllegalArgumentException aExcept(sMessage, rContext, -1 );
187 0 : EXCEPT(aExcept); }
188 0 : break;
189 : case G_IO_ERROR_PERMISSION_DENIED:
190 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
191 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_ACCESS_DENIED, aArgs);
192 0 : EXCEPT(aExcept); }
193 0 : break;
194 : case G_IO_ERROR_IS_DIRECTORY:
195 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
196 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_FILE, aArgs);
197 0 : EXCEPT(aExcept); }
198 0 : break;
199 : case G_IO_ERROR_NOT_REGULAR_FILE:
200 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
201 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_FILE, aArgs);
202 0 : EXCEPT(aExcept); }
203 0 : break;
204 : case G_IO_ERROR_NOT_DIRECTORY:
205 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
206 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_NO_DIRECTORY, aArgs);
207 0 : EXCEPT(aExcept); }
208 0 : break;
209 : case G_IO_ERROR_FILENAME_TOO_LONG:
210 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
211 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_NAME_TOO_LONG, aArgs);
212 0 : EXCEPT(aExcept); }
213 0 : break;
214 : case G_IO_ERROR_PENDING:
215 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
216 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_PENDING, aArgs);
217 0 : EXCEPT(aExcept); }
218 0 : break;
219 : case G_IO_ERROR_CLOSED:
220 : case G_IO_ERROR_CANCELLED:
221 : case G_IO_ERROR_TOO_MANY_LINKS:
222 : case G_IO_ERROR_WRONG_ETAG:
223 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
224 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_GENERAL, aArgs);
225 0 : EXCEPT(aExcept); }
226 0 : break;
227 : case G_IO_ERROR_NOT_SUPPORTED:
228 : case G_IO_ERROR_CANT_CREATE_BACKUP:
229 : case G_IO_ERROR_WOULD_MERGE:
230 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
231 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_NOT_SUPPORTED, aArgs);
232 0 : EXCEPT(aExcept); }
233 0 : break;
234 : case G_IO_ERROR_NO_SPACE:
235 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
236 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_OUT_OF_DISK_SPACE, aArgs);
237 0 : EXCEPT(aExcept); }
238 0 : break;
239 : case G_IO_ERROR_INVALID_FILENAME:
240 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
241 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_INVALID_CHARACTER, aArgs);
242 0 : EXCEPT(aExcept); }
243 0 : break;
244 : case G_IO_ERROR_READ_ONLY:
245 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
246 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_WRITE_PROTECTED, aArgs);
247 0 : EXCEPT(aExcept); }
248 0 : break;
249 : case G_IO_ERROR_TIMED_OUT:
250 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
251 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_DEVICE_NOT_READY, aArgs);
252 0 : EXCEPT(aExcept); }
253 0 : break;
254 : case G_IO_ERROR_WOULD_RECURSE:
255 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
256 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_RECURSIVE, aArgs);
257 0 : EXCEPT(aExcept); }
258 0 : break;
259 : case G_IO_ERROR_BUSY:
260 : case G_IO_ERROR_WOULD_BLOCK:
261 : { ucb::InteractiveAugmentedIOException aExcept(sMessage, rContext,
262 0 : task::InteractionClassification_ERROR, ucb::IOErrorCode_LOCKING_VIOLATION, aArgs);
263 0 : EXCEPT(aExcept); }
264 0 : break;
265 : case G_IO_ERROR_HOST_NOT_FOUND:
266 : { ucb::InteractiveNetworkResolveNameException aExcept(sMessage, rContext,
267 0 : task::InteractionClassification_ERROR, sHost);
268 0 : EXCEPT(aExcept);}
269 0 : break;
270 : default:
271 : case G_IO_ERROR_ALREADY_MOUNTED:
272 : case G_IO_ERROR_NOT_EMPTY:
273 : case G_IO_ERROR_NOT_SYMBOLIC_LINK:
274 : case G_IO_ERROR_NOT_MOUNTABLE_FILE:
275 : case G_IO_ERROR_FAILED_HANDLED:
276 : { ucb::InteractiveNetworkGeneralException aExcept(sMessage, rContext,
277 0 : task::InteractionClassification_ERROR);
278 0 : EXCEPT(aExcept);}
279 0 : break;
280 : }
281 0 : return aRet;
282 : }
283 :
284 0 : void convertToIOException(GError *pError, const uno::Reference< uno::XInterface >& rContext)
285 : throw( io::IOException, uno::RuntimeException, std::exception )
286 : {
287 : try
288 : {
289 0 : convertToException(pError, rContext);
290 : }
291 0 : catch (const io::IOException&)
292 : {
293 0 : throw;
294 : }
295 0 : catch (const uno::RuntimeException&)
296 : {
297 0 : throw;
298 : }
299 0 : catch (const uno::Exception& e)
300 : {
301 0 : css::uno::Any a(cppu::getCaughtException());
302 : throw css::lang::WrappedTargetRuntimeException(
303 0 : "wrapped Exception " + e.Message,
304 0 : css::uno::Reference<css::uno::XInterface>(), a);
305 : }
306 0 : }
307 :
308 0 : uno::Any Content::mapGIOError( GError *pError )
309 : {
310 0 : if (!pError)
311 0 : return getBadArgExcept();
312 :
313 0 : return convertToException(pError, static_cast< cppu::OWeakObject * >(this), false);
314 : }
315 :
316 0 : uno::Any Content::getBadArgExcept()
317 : {
318 : return uno::makeAny( lang::IllegalArgumentException(
319 : OUString("Wrong argument type!"),
320 0 : static_cast< cppu::OWeakObject * >( this ), -1) );
321 : }
322 :
323 : class MountOperation
324 : {
325 : GMainLoop *mpLoop;
326 : GMountOperation *mpAuthentication;
327 : GError *mpError;
328 : static void Completed(GObject *source, GAsyncResult *res, gpointer user_data);
329 : public:
330 : explicit MountOperation(const uno::Reference< ucb::XCommandEnvironment >& xEnv);
331 : ~MountOperation();
332 : GError *Mount(GFile *pFile);
333 : };
334 :
335 0 : MountOperation::MountOperation(const uno::Reference< ucb::XCommandEnvironment >& xEnv) : mpError(NULL)
336 : {
337 0 : mpLoop = g_main_loop_new(NULL, FALSE);
338 0 : mpAuthentication = ooo_mount_operation_new(xEnv);
339 0 : }
340 :
341 0 : void MountOperation::Completed(GObject *source, GAsyncResult *res, gpointer user_data)
342 : {
343 0 : MountOperation *pThis = static_cast<MountOperation*>(user_data);
344 0 : g_file_mount_enclosing_volume_finish(G_FILE(source), res, &(pThis->mpError));
345 0 : g_main_loop_quit(pThis->mpLoop);
346 0 : }
347 :
348 0 : GError *MountOperation::Mount(GFile *pFile)
349 : {
350 0 : g_file_mount_enclosing_volume(pFile, G_MOUNT_MOUNT_NONE, mpAuthentication, NULL, MountOperation::Completed, this);
351 : {
352 : //HACK: At least the gdk_threads_set_lock_functions(GdkThreadsEnter,
353 : // GdkThreadsLeave) call in vcl/unx/gtk/app/gtkinst.cxx will lead to
354 : // GdkThreadsLeave unlock the SolarMutex down to zero at the end of
355 : // g_main_loop_run, so we need ~SolarMutexReleaser to raise it back to
356 : // the original value again:
357 0 : SolarMutexReleaser rel;
358 0 : g_main_loop_run(mpLoop);
359 : }
360 0 : return mpError;
361 : }
362 :
363 0 : MountOperation::~MountOperation()
364 : {
365 0 : g_object_unref(mpAuthentication);
366 0 : g_main_loop_unref(mpLoop);
367 0 : }
368 :
369 51 : GFileInfo* Content::getGFileInfo(const uno::Reference< ucb::XCommandEnvironment >& xEnv, GError **ppError)
370 : {
371 51 : GError * err = 0;
372 51 : if (mpInfo == 0 && !mbTransient) {
373 51 : for (bool retried = false;; retried = true) {
374 : mpInfo = g_file_query_info(
375 51 : getGFile(), "*", G_FILE_QUERY_INFO_NONE, 0, &err);
376 51 : if (mpInfo != 0) {
377 0 : break;
378 : }
379 : assert(err != 0);
380 51 : if (err->code != G_IO_ERROR_NOT_MOUNTED || retried) {
381 : break;
382 : }
383 : SAL_INFO(
384 : "ucb.ucp.gio",
385 : "G_IO_ERROR_NOT_MOUNTED \"" << err->message
386 : << "\", trying to mount");
387 0 : g_error_free(err);
388 0 : err = MountOperation(xEnv).Mount(getGFile());
389 0 : if (err != 0) {
390 0 : break;
391 : }
392 0 : }
393 : }
394 51 : if (ppError != 0) {
395 0 : *ppError = err;
396 51 : } else if (err != 0) {
397 : SAL_WARN(
398 : "ucb.ucp.gio",
399 : "ignoring GError \"" << err->message << "\" for <"
400 : << m_xIdentifier->getContentIdentifier() << ">");
401 51 : g_error_free(err);
402 : }
403 51 : return mpInfo;
404 : }
405 :
406 100 : GFile* Content::getGFile()
407 : {
408 100 : if (!mpFile)
409 51 : mpFile = g_file_new_for_uri(OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr());
410 100 : return mpFile;
411 : }
412 :
413 49 : bool Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv)
414 : {
415 49 : GFileInfo *pInfo = getGFileInfo(xEnv);
416 49 : return pInfo && (g_file_info_get_file_type(pInfo) == G_FILE_TYPE_DIRECTORY);
417 : }
418 :
419 0 : static util::DateTime getDateFromUnix (time_t t)
420 : {
421 : TimeValue tv;
422 0 : tv.Nanosec = 0;
423 0 : tv.Seconds = t;
424 : oslDateTime dt;
425 :
426 0 : if ( osl_getDateTimeFromTimeValue( &tv, &dt ) )
427 : return util::DateTime( 0, dt.Seconds, dt.Minutes, dt.Hours,
428 0 : dt.Day, dt.Month, dt.Year, false);
429 : else
430 0 : return util::DateTime();
431 : }
432 :
433 2 : uno::Reference< sdbc::XRow > Content::getPropertyValuesFromGFileInfo(GFileInfo *pInfo,
434 : const uno::Reference< uno::XComponentContext >& rxContext,
435 : const uno::Reference< ucb::XCommandEnvironment > & xEnv,
436 : const uno::Sequence< beans::Property >& rProperties)
437 : {
438 2 : rtl::Reference< ::ucbhelper::PropertyValueSet > xRow = new ::ucbhelper::PropertyValueSet( rxContext );
439 :
440 : sal_Int32 nProps;
441 : const beans::Property* pProps;
442 :
443 2 : nProps = rProperties.getLength();
444 2 : pProps = rProperties.getConstArray();
445 :
446 4 : for( sal_Int32 n = 0; n < nProps; ++n )
447 : {
448 2 : const beans::Property& rProp = pProps[ n ];
449 :
450 2 : if ( rProp.Name == "IsDocument" )
451 : {
452 0 : if (pInfo != 0 && g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE))
453 0 : xRow->appendBoolean( rProp, ( g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_REGULAR ||
454 0 : g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_UNKNOWN ) );
455 : else
456 0 : xRow->appendVoid( rProp );
457 : }
458 2 : else if ( rProp.Name == "IsFolder" )
459 : {
460 2 : if (pInfo != 0 && g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE) )
461 0 : xRow->appendBoolean( rProp, ( g_file_info_get_file_type( pInfo ) == G_FILE_TYPE_DIRECTORY ));
462 : else
463 2 : xRow->appendVoid( rProp );
464 : }
465 0 : else if ( rProp.Name == "Title" )
466 : {
467 0 : if (pInfo != 0 && g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME))
468 : {
469 0 : const char *pName = g_file_info_get_display_name(pInfo);
470 0 : xRow->appendString( rProp, OUString(pName, strlen(pName), RTL_TEXTENCODING_UTF8) );
471 : }
472 : else
473 0 : xRow->appendVoid(rProp);
474 : }
475 0 : else if ( rProp.Name == "IsReadOnly" )
476 : {
477 0 : if (pInfo != 0 && g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE ) )
478 0 : xRow->appendBoolean( rProp, !g_file_info_get_attribute_boolean( pInfo, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE) );
479 : else
480 0 : xRow->appendVoid( rProp );
481 : }
482 0 : else if ( rProp.Name == "DateCreated" )
483 : {
484 0 : if (pInfo != 0 && g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_TIME_CREATED ) )
485 0 : xRow->appendTimestamp( rProp, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo, G_FILE_ATTRIBUTE_TIME_CREATED)) );
486 : else
487 0 : xRow->appendVoid( rProp );
488 : }
489 0 : else if ( rProp.Name == "DateModified" )
490 : {
491 0 : if (pInfo != 0 && g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_TIME_CHANGED ) )
492 0 : xRow->appendTimestamp( rProp, getDateFromUnix(g_file_info_get_attribute_uint64(pInfo, G_FILE_ATTRIBUTE_TIME_CHANGED)) );
493 : else
494 0 : xRow->appendVoid( rProp );
495 : }
496 0 : else if ( rProp.Name == "Size" )
497 : {
498 0 : if (pInfo != 0 && g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_SIZE) )
499 0 : xRow->appendLong( rProp, ( g_file_info_get_size( pInfo ) ));
500 : else
501 0 : xRow->appendVoid( rProp );
502 : }
503 0 : else if ( rProp.Name == "IsVolume" )
504 : {
505 : //What do we use this for ?
506 0 : xRow->appendBoolean( rProp, false );
507 : }
508 0 : else if ( rProp.Name == "IsCompactDisc" )
509 : {
510 0 : if (pInfo != 0 && g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT ) )
511 0 : xRow->appendBoolean( rProp, g_file_info_get_attribute_boolean(pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_EJECT) );
512 : else
513 0 : xRow->appendVoid( rProp );
514 : }
515 0 : else if ( rProp.Name == "IsRemoveable" )
516 : {
517 0 : if (pInfo != 0 && g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT ) )
518 0 : xRow->appendBoolean( rProp, g_file_info_get_attribute_boolean(pInfo, G_FILE_ATTRIBUTE_MOUNTABLE_CAN_UNMOUNT ) );
519 : else
520 0 : xRow->appendVoid( rProp );
521 : }
522 0 : else if ( rProp.Name == "IsFloppy" )
523 : {
524 0 : xRow->appendBoolean( rProp, false );
525 : }
526 0 : else if ( rProp.Name == "IsHidden" )
527 : {
528 0 : if (pInfo != 0 && g_file_info_has_attribute( pInfo, G_FILE_ATTRIBUTE_STANDARD_IS_HIDDEN) )
529 0 : xRow->appendBoolean( rProp, ( g_file_info_get_is_hidden ( pInfo ) ) );
530 : else
531 0 : xRow->appendVoid( rProp );
532 : }
533 0 : else if ( rProp.Name == "CreatableContentsInfo" )
534 : {
535 0 : xRow->appendObject( rProp, uno::makeAny( queryCreatableContentsInfo( xEnv ) ) );
536 : }
537 : else
538 : {
539 : SAL_WARN(
540 : "ucb.ucp.gio",
541 : "Looking for unsupported property " << rProp.Name);
542 : }
543 : }
544 :
545 2 : return uno::Reference< sdbc::XRow >( xRow.get() );
546 : }
547 :
548 2 : uno::Reference< sdbc::XRow > Content::getPropertyValues(
549 : const uno::Sequence< beans::Property >& rProperties,
550 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
551 : {
552 2 : GFileInfo *pInfo = getGFileInfo(xEnv);
553 2 : return getPropertyValuesFromGFileInfo(pInfo, m_xContext, xEnv, rProperties);
554 : }
555 :
556 : static lang::IllegalAccessException
557 0 : getReadOnlyException( const uno::Reference< uno::XInterface >& rContext )
558 : {
559 0 : return lang::IllegalAccessException ("Property is read-only!", rContext );
560 : }
561 :
562 0 : void Content::queryChildren( ContentRefList& rChildren )
563 : {
564 : // Obtain a list with a snapshot of all currently instantiated contents
565 : // from provider and extract the contents which are direct children
566 : // of this content.
567 :
568 0 : ucbhelper::ContentRefList aAllContents;
569 0 : m_xProvider->queryExistingContents( aAllContents );
570 :
571 0 : OUString aURL = m_xIdentifier->getContentIdentifier();
572 0 : sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
573 :
574 0 : if ( nURLPos != ( aURL.getLength() - 1 ) )
575 0 : aURL += "/";
576 :
577 0 : sal_Int32 nLen = aURL.getLength();
578 :
579 0 : ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
580 0 : ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
581 :
582 0 : while ( it != end )
583 : {
584 0 : ucbhelper::ContentImplHelperRef xChild = (*it);
585 0 : OUString aChildURL = xChild->getIdentifier()->getContentIdentifier();
586 :
587 : // Is aURL a prefix of aChildURL?
588 0 : if ( ( aChildURL.getLength() > nLen ) && aChildURL.startsWith( aURL ) )
589 : {
590 0 : sal_Int32 nPos = nLen;
591 0 : nPos = aChildURL.indexOf( '/', nPos );
592 :
593 0 : if ( ( nPos == -1 ) || ( nPos == ( aChildURL.getLength() - 1 ) ) )
594 : {
595 : // No further slashes / only a final slash. It's a child!
596 0 : rChildren.push_back( ::gio::Content::ContentRef (static_cast< ::gio::Content * >(xChild.get() ) ) );
597 : }
598 : }
599 0 : ++it;
600 0 : }
601 0 : }
602 :
603 0 : bool Content::exchangeIdentity( const uno::Reference< ucb::XContentIdentifier >& xNewId )
604 : {
605 0 : if ( !xNewId.is() )
606 0 : return false;
607 :
608 0 : uno::Reference< ucb::XContent > xThis = this;
609 :
610 0 : if ( mbTransient )
611 : {
612 0 : m_xIdentifier = xNewId;
613 0 : return false;
614 : }
615 :
616 0 : OUString aOldURL = m_xIdentifier->getContentIdentifier();
617 :
618 : // Exchange own identitity.
619 0 : if ( exchange( xNewId ) )
620 : {
621 : // Process instantiated children...
622 0 : ContentRefList aChildren;
623 0 : queryChildren( aChildren );
624 :
625 0 : ContentRefList::const_iterator it = aChildren.begin();
626 0 : ContentRefList::const_iterator end = aChildren.end();
627 :
628 0 : while ( it != end )
629 : {
630 0 : ContentRef xChild = (*it);
631 :
632 : // Create new content identifier for the child...
633 0 : uno::Reference< ucb::XContentIdentifier > xOldChildId = xChild->getIdentifier();
634 0 : OUString aOldChildURL = xOldChildId->getContentIdentifier();
635 : OUString aNewChildURL = aOldChildURL.replaceAt(
636 0 : 0, aOldURL.getLength(), xNewId->getContentIdentifier() );
637 :
638 : uno::Reference< ucb::XContentIdentifier > xNewChildId
639 0 : = new ::ucbhelper::ContentIdentifier( aNewChildURL );
640 :
641 0 : if ( !xChild->exchangeIdentity( xNewChildId ) )
642 0 : return false;
643 :
644 0 : ++it;
645 0 : }
646 0 : return true;
647 : }
648 :
649 0 : return false;
650 : }
651 :
652 0 : uno::Sequence< uno::Any > Content::setPropertyValues(
653 : const uno::Sequence< beans::PropertyValue >& rValues,
654 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
655 : {
656 0 : GError *pError=NULL;
657 0 : GFileInfo *pNewInfo=NULL;
658 0 : GFileInfo *pInfo = getGFileInfo(xEnv, &pError);
659 0 : if (pInfo)
660 0 : pNewInfo = g_file_info_dup(pInfo);
661 : else
662 : {
663 0 : if (!mbTransient)
664 0 : ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
665 : else
666 : {
667 0 : if (pError)
668 0 : g_error_free(pError);
669 0 : pNewInfo = g_file_info_new();
670 : }
671 : }
672 :
673 0 : sal_Int32 nCount = rValues.getLength();
674 :
675 0 : beans::PropertyChangeEvent aEvent;
676 0 : aEvent.Source = static_cast< cppu::OWeakObject * >( this );
677 0 : aEvent.Further = sal_False;
678 0 : aEvent.PropertyHandle = -1;
679 :
680 0 : sal_Int32 nChanged = 0, nTitlePos = -1;
681 0 : const char *newName = NULL;
682 0 : uno::Sequence< beans::PropertyChangeEvent > aChanges(nCount);
683 :
684 0 : uno::Sequence< uno::Any > aRet( nCount );
685 0 : const beans::PropertyValue* pValues = rValues.getConstArray();
686 0 : for ( sal_Int32 n = 0; n < nCount; ++n )
687 : {
688 0 : const beans::PropertyValue& rValue = pValues[ n ];
689 : #if OSL_DEBUG_LEVEL > 1
690 : g_warning("Set prop '%s'", OUStringToOString(rValue.Name, RTL_TEXTENCODING_UTF8).getStr());
691 : #endif
692 0 : if ( rValue.Name == "ContentType" ||
693 0 : rValue.Name == "MediaType" ||
694 0 : rValue.Name == "IsDocument" ||
695 0 : rValue.Name == "IsFolder" ||
696 0 : rValue.Name == "Size" ||
697 0 : rValue.Name == "CreatableContentsInfo" )
698 : {
699 0 : aRet[ n ] <<= getReadOnlyException( static_cast< cppu::OWeakObject * >(this) );
700 : }
701 0 : else if ( rValue.Name == "Title" )
702 : {
703 0 : OUString aNewTitle;
704 0 : if (!( rValue.Value >>= aNewTitle ))
705 : {
706 0 : aRet[ n ] <<= beans::IllegalTypeException
707 : ( OUString("Property value has wrong type!"),
708 0 : static_cast< cppu::OWeakObject * >( this ) );
709 0 : continue;
710 : }
711 :
712 0 : if ( aNewTitle.getLength() <= 0 )
713 : {
714 0 : aRet[ n ] <<= lang::IllegalArgumentException
715 : ( OUString("Empty title not allowed!"),
716 0 : static_cast< cppu::OWeakObject * >( this ), -1 );
717 0 : continue;
718 :
719 : }
720 :
721 0 : OString sNewTitle = OUStringToOString(aNewTitle, RTL_TEXTENCODING_UTF8);
722 0 : newName = sNewTitle.getStr();
723 0 : const char *oldName = g_file_info_get_name( pInfo);
724 :
725 0 : if (!newName || !oldName || strcmp(newName, oldName))
726 : {
727 : #if OSL_DEBUG_LEVEL > 1
728 : g_warning ("Set new name to '%s'", newName);
729 : #endif
730 :
731 0 : aEvent.PropertyName = "Title";
732 0 : if (oldName)
733 0 : aEvent.OldValue = uno::makeAny(OUString(oldName, strlen(oldName), RTL_TEXTENCODING_UTF8));
734 0 : aEvent.NewValue = uno::makeAny(aNewTitle);
735 0 : aChanges.getArray()[ nChanged ] = aEvent;
736 0 : nTitlePos = nChanged++;
737 :
738 0 : g_file_info_set_name(pNewInfo, newName);
739 0 : }
740 : }
741 : else
742 : {
743 : SAL_WARN("ucb.ucp.gio", "Unknown property " << rValue.Name << "\n");
744 0 : aRet[ n ] <<= getReadOnlyException( static_cast< cppu::OWeakObject * >(this) );
745 : //TODO
746 : }
747 : }
748 :
749 0 : if (nChanged)
750 : {
751 0 : bool bOk = true;
752 0 : if (!mbTransient)
753 : {
754 0 : if ((bOk = doSetFileInfo(pNewInfo)))
755 : {
756 0 : for (sal_Int32 i = 0; i < nChanged; ++i)
757 0 : aRet[ i ] <<= getBadArgExcept();
758 : }
759 : }
760 :
761 0 : if (bOk)
762 : {
763 0 : if (nTitlePos > -1)
764 : {
765 0 : OUString aNewURL = getParentURL();
766 0 : aNewURL += OUString( newName, strlen(newName), RTL_TEXTENCODING_UTF8 );
767 : uno::Reference< ucb::XContentIdentifier > xNewId
768 0 : = new ::ucbhelper::ContentIdentifier( aNewURL );
769 :
770 0 : if (!exchangeIdentity( xNewId ) )
771 : {
772 0 : aRet[ nTitlePos ] <<= uno::Exception
773 : ( OUString("Exchange failed!"),
774 0 : static_cast< cppu::OWeakObject * >( this ) );
775 0 : }
776 : }
777 :
778 0 : if (!mbTransient) //Discard and refetch
779 : {
780 0 : g_object_unref(mpInfo);
781 0 : mpInfo = NULL;
782 : }
783 :
784 0 : if (mpInfo)
785 : {
786 0 : g_file_info_copy_into(pNewInfo, mpInfo);
787 0 : g_object_unref(pNewInfo);
788 : }
789 : else
790 0 : mpInfo = pNewInfo;
791 :
792 0 : if (mpFile) //Discard and refetch
793 : {
794 0 : g_object_unref(mpFile);
795 0 : mpFile = NULL;
796 : }
797 : }
798 :
799 0 : aChanges.realloc( nChanged );
800 0 : notifyPropertiesChange( aChanges );
801 : }
802 :
803 0 : return aRet;
804 : }
805 :
806 0 : bool Content::doSetFileInfo(GFileInfo *pNewInfo)
807 : {
808 0 : g_assert (!mbTransient);
809 :
810 0 : bool bOk = true;
811 0 : GFile *pFile = getGFile();
812 0 : if(!g_file_set_attributes_from_info(pFile, pNewInfo, G_FILE_QUERY_INFO_NONE, NULL, NULL))
813 0 : bOk = false;
814 0 : return bOk;
815 : }
816 :
817 : const int TRANSFER_BUFFER_SIZE = 65536;
818 :
819 0 : void Content::copyData( uno::Reference< io::XInputStream > xIn,
820 : uno::Reference< io::XOutputStream > xOut )
821 : {
822 0 : uno::Sequence< sal_Int8 > theData( TRANSFER_BUFFER_SIZE );
823 :
824 0 : g_return_if_fail( xIn.is() && xOut.is() );
825 :
826 0 : while ( xIn->readBytes( theData, TRANSFER_BUFFER_SIZE ) > 0 )
827 0 : xOut->writeBytes( theData );
828 :
829 0 : xOut->closeOutput();
830 : }
831 :
832 0 : bool Content::feedSink( uno::Reference< uno::XInterface > xSink,
833 : const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ )
834 : {
835 0 : if ( !xSink.is() )
836 0 : return false;
837 :
838 0 : uno::Reference< io::XOutputStream > xOut = uno::Reference< io::XOutputStream >(xSink, uno::UNO_QUERY );
839 0 : uno::Reference< io::XActiveDataSink > xDataSink = uno::Reference< io::XActiveDataSink >(xSink, uno::UNO_QUERY );
840 :
841 0 : if ( !xOut.is() && !xDataSink.is() )
842 0 : return false;
843 :
844 0 : GError *pError=NULL;
845 0 : GFileInputStream *pStream = g_file_read(getGFile(), NULL, &pError);
846 0 : if (!pStream)
847 0 : convertToException(pError, static_cast< cppu::OWeakObject * >(this));
848 :
849 0 : uno::Reference< io::XInputStream > xIn = new ::gio::InputStream(pStream);
850 0 : if ( !xIn.is() )
851 0 : return false;
852 :
853 0 : if ( xOut.is() )
854 0 : copyData( xIn, xOut );
855 :
856 0 : if ( xDataSink.is() )
857 0 : xDataSink->setInputStream( xIn );
858 :
859 0 : return true;
860 : }
861 :
862 49 : uno::Any Content::open(const ucb::OpenCommandArgument2 & rOpenCommand,
863 : const uno::Reference< ucb::XCommandEnvironment > & xEnv )
864 : throw( uno::Exception )
865 : {
866 49 : bool bIsFolder = isFolder(xEnv);
867 :
868 49 : if (!g_file_query_exists(getGFile(), NULL))
869 : {
870 49 : uno::Sequence< uno::Any > aArgs( 1 );
871 49 : aArgs[ 0 ] <<= m_xIdentifier->getContentIdentifier();
872 : uno::Any aErr = uno::makeAny(
873 : ucb::InteractiveAugmentedIOException(OUString(), static_cast< cppu::OWeakObject * >( this ),
874 : task::InteractionClassification_ERROR,
875 : bIsFolder ? ucb::IOErrorCode_NOT_EXISTING_PATH : ucb::IOErrorCode_NOT_EXISTING, aArgs)
876 49 : );
877 :
878 98 : ucbhelper::cancelCommandExecution(aErr, xEnv);
879 : }
880 :
881 0 : uno::Any aRet;
882 :
883 : bool bOpenFolder = (
884 0 : ( rOpenCommand.Mode == ucb::OpenMode::ALL ) ||
885 0 : ( rOpenCommand.Mode == ucb::OpenMode::FOLDERS ) ||
886 0 : ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENTS )
887 0 : );
888 :
889 0 : if ( bOpenFolder && bIsFolder )
890 : {
891 : uno::Reference< ucb::XDynamicResultSet > xSet
892 0 : = new DynamicResultSet( m_xContext, this, rOpenCommand, xEnv );
893 0 : aRet <<= xSet;
894 : }
895 0 : else if ( rOpenCommand.Sink.is() )
896 : {
897 0 : if (
898 0 : ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
899 0 : ( rOpenCommand.Mode == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE )
900 : )
901 : {
902 : ucbhelper::cancelCommandExecution(
903 : uno::makeAny ( ucb::UnsupportedOpenModeException
904 : ( OUString(), static_cast< cppu::OWeakObject * >( this ),
905 : sal_Int16( rOpenCommand.Mode ) ) ),
906 0 : xEnv );
907 : }
908 :
909 0 : if ( !feedSink( rOpenCommand.Sink, xEnv ) )
910 : {
911 : // Note: rOpenCommand.Sink may contain an XStream
912 : // implementation. Support for this type of
913 : // sink is optional...
914 : #ifdef DEBUG
915 : g_warning ("Failed to load data from '%s'",
916 : OUStringToOString(m_xIdentifier->getContentIdentifier(), RTL_TEXTENCODING_UTF8).getStr());
917 : #endif
918 :
919 : ucbhelper::cancelCommandExecution(
920 : uno::makeAny (ucb::UnsupportedDataSinkException
921 : ( OUString(), static_cast< cppu::OWeakObject * >( this ),
922 : rOpenCommand.Sink ) ),
923 0 : xEnv );
924 : }
925 : }
926 : else
927 0 : g_warning ("Open falling through ...");
928 0 : return aRet;
929 : }
930 :
931 3380 : uno::Any SAL_CALL Content::execute(
932 : const ucb::Command& aCommand,
933 : sal_Int32 /*CommandId*/,
934 : const uno::Reference< ucb::XCommandEnvironment >& xEnv )
935 : throw( uno::Exception,
936 : ucb::CommandAbortedException,
937 : uno::RuntimeException, std::exception )
938 : {
939 : SAL_INFO("ucb.ucp.gio", "Content::execute " << aCommand.Name << "\n");
940 3380 : uno::Any aRet;
941 :
942 3380 : if ( aCommand.Name == "getPropertyValues" )
943 : {
944 2 : uno::Sequence< beans::Property > Properties;
945 2 : if ( !( aCommand.Argument >>= Properties ) )
946 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
947 2 : aRet <<= getPropertyValues( Properties, xEnv );
948 : }
949 3378 : else if ( aCommand.Name == "getPropertySetInfo" )
950 3329 : aRet <<= getPropertySetInfo( xEnv, false );
951 49 : else if ( aCommand.Name == "getCommandInfo" )
952 0 : aRet <<= getCommandInfo( xEnv, false );
953 49 : else if ( aCommand.Name == "open" )
954 : {
955 49 : ucb::OpenCommandArgument2 aOpenCommand;
956 49 : if ( !( aCommand.Argument >>= aOpenCommand ) )
957 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
958 98 : aRet = open( aOpenCommand, xEnv );
959 : }
960 0 : else if ( aCommand.Name == "transfer" )
961 : {
962 0 : ucb::TransferInfo transferArgs;
963 0 : if ( !( aCommand.Argument >>= transferArgs ) )
964 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
965 0 : transfer( transferArgs, xEnv );
966 : }
967 0 : else if ( aCommand.Name == "setPropertyValues" )
968 : {
969 0 : uno::Sequence< beans::PropertyValue > aProperties;
970 0 : if ( !( aCommand.Argument >>= aProperties ) || !aProperties.getLength() )
971 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
972 0 : aRet <<= setPropertyValues( aProperties, xEnv );
973 : }
974 0 : else if (aCommand.Name == "createNewContent"
975 0 : && isFolder( xEnv ) )
976 : {
977 0 : ucb::ContentInfo arg;
978 0 : if ( !( aCommand.Argument >>= arg ) )
979 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
980 0 : aRet <<= createNewContent( arg );
981 : }
982 0 : else if ( aCommand.Name == "insert" )
983 : {
984 0 : ucb::InsertCommandArgument arg;
985 0 : if ( !( aCommand.Argument >>= arg ) )
986 0 : ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
987 0 : insert( arg.Data, arg.ReplaceExisting, xEnv );
988 : }
989 0 : else if ( aCommand.Name == "delete" )
990 : {
991 0 : bool bDeletePhysical = false;
992 0 : aCommand.Argument >>= bDeletePhysical;
993 :
994 : //If no delete physical, try and trashcan it, if that doesn't work go
995 : //ahead and try and delete it anyway
996 0 : if (!bDeletePhysical && !g_file_trash(getGFile(), NULL, NULL))
997 0 : bDeletePhysical = true;
998 :
999 0 : if (bDeletePhysical)
1000 : {
1001 0 : GError *pError = NULL;
1002 0 : if (!g_file_delete( getGFile(), NULL, &pError))
1003 0 : ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
1004 : }
1005 :
1006 0 : destroy( bDeletePhysical );
1007 : }
1008 : else
1009 : {
1010 : SAL_WARN("ucb.ucp.gio", "Unknown command " << aCommand.Name << "\n");
1011 :
1012 : ucbhelper::cancelCommandExecution
1013 : ( uno::makeAny( ucb::UnsupportedCommandException
1014 : ( OUString(),
1015 : static_cast< cppu::OWeakObject * >( this ) ) ),
1016 0 : xEnv );
1017 : }
1018 :
1019 3331 : return aRet;
1020 : }
1021 :
1022 0 : void Content::destroy( bool bDeletePhysical )
1023 : throw( uno::Exception )
1024 : {
1025 0 : uno::Reference< ucb::XContent > xThis = this;
1026 :
1027 0 : deleted();
1028 :
1029 0 : ::gio::Content::ContentRefList aChildren;
1030 0 : queryChildren( aChildren );
1031 :
1032 0 : ContentRefList::const_iterator it = aChildren.begin();
1033 0 : ContentRefList::const_iterator end = aChildren.end();
1034 :
1035 0 : while ( it != end )
1036 : {
1037 0 : (*it)->destroy( bDeletePhysical );
1038 0 : ++it;
1039 0 : }
1040 0 : }
1041 :
1042 0 : void Content::insert(const uno::Reference< io::XInputStream > &xInputStream,
1043 : bool bReplaceExisting, const uno::Reference< ucb::XCommandEnvironment > &xEnv )
1044 : throw( uno::Exception )
1045 : {
1046 0 : GError *pError = NULL;
1047 0 : GFileInfo *pInfo = getGFileInfo(xEnv);
1048 :
1049 0 : if ( pInfo &&
1050 0 : g_file_info_has_attribute(pInfo, G_FILE_ATTRIBUTE_STANDARD_TYPE) &&
1051 0 : g_file_info_get_file_type(pInfo) == G_FILE_TYPE_DIRECTORY )
1052 : {
1053 : #if OSL_DEBUG_LEVEL > 1
1054 : g_warning ("Make directory");
1055 : #endif
1056 0 : if( !g_file_make_directory( getGFile(), NULL, &pError))
1057 0 : ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
1058 0 : return;
1059 : }
1060 :
1061 0 : if ( !xInputStream.is() )
1062 : {
1063 : ucbhelper::cancelCommandExecution( uno::makeAny
1064 : ( ucb::MissingInputStreamException
1065 : ( OUString(), static_cast< cppu::OWeakObject * >( this ) ) ),
1066 0 : xEnv );
1067 : }
1068 :
1069 0 : GFileOutputStream* pOutStream = NULL;
1070 0 : if ( bReplaceExisting )
1071 : {
1072 0 : if (!(pOutStream = g_file_replace(getGFile(), NULL, false, G_FILE_CREATE_PRIVATE, NULL, &pError)))
1073 0 : ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
1074 : }
1075 : else
1076 : {
1077 0 : if (!(pOutStream = g_file_create (getGFile(), G_FILE_CREATE_PRIVATE, NULL, &pError)))
1078 0 : ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
1079 : }
1080 :
1081 0 : uno::Reference < io::XOutputStream > xOutput = new ::gio::OutputStream(pOutStream);
1082 0 : copyData( xInputStream, xOutput );
1083 :
1084 0 : if (mbTransient)
1085 : {
1086 0 : mbTransient = false;
1087 0 : inserted();
1088 0 : }
1089 : }
1090 :
1091 : const GFileCopyFlags DEFAULT_COPYDATA_FLAGS =
1092 : static_cast<GFileCopyFlags>(G_FILE_COPY_OVERWRITE|G_FILE_COPY_TARGET_DEFAULT_PERMS);
1093 :
1094 0 : void Content::transfer( const ucb::TransferInfo& aTransferInfo, const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1095 : throw( uno::Exception )
1096 : {
1097 0 : OUString sDest = m_xIdentifier->getContentIdentifier();
1098 0 : if (!sDest.endsWith("/")) {
1099 0 : sDest += "/";
1100 : }
1101 0 : if (aTransferInfo.NewTitle.getLength())
1102 0 : sDest += aTransferInfo.NewTitle;
1103 : else
1104 0 : sDest += OUString::createFromAscii(g_file_get_basename(getGFile()));
1105 :
1106 0 : GFile *pDest = g_file_new_for_uri(OUStringToOString(sDest, RTL_TEXTENCODING_UTF8).getStr());
1107 0 : GFile *pSource = g_file_new_for_uri(OUStringToOString(aTransferInfo.SourceURL, RTL_TEXTENCODING_UTF8).getStr());
1108 :
1109 0 : gboolean bSuccess = false;
1110 0 : GError *pError = NULL;
1111 0 : if (aTransferInfo.MoveData)
1112 0 : bSuccess = g_file_move(pSource, pDest, G_FILE_COPY_OVERWRITE, NULL, NULL, 0, &pError);
1113 : else
1114 0 : bSuccess = g_file_copy(pSource, pDest, DEFAULT_COPYDATA_FLAGS, NULL, NULL, 0, &pError);
1115 0 : g_object_unref(pSource);
1116 0 : g_object_unref(pDest);
1117 0 : if (!bSuccess)
1118 0 : ucbhelper::cancelCommandExecution(mapGIOError(pError), xEnv);
1119 0 : }
1120 :
1121 0 : uno::Sequence< ucb::ContentInfo > Content::queryCreatableContentsInfo(
1122 : const uno::Reference< ucb::XCommandEnvironment >& xEnv)
1123 : throw( uno::RuntimeException )
1124 : {
1125 0 : if ( isFolder( xEnv ) )
1126 : {
1127 0 : uno::Sequence< ucb::ContentInfo > seq(2);
1128 :
1129 : // Minimum set of props we really need
1130 0 : uno::Sequence< beans::Property > props( 1 );
1131 0 : props[0] = beans::Property(
1132 : OUString("Title"),
1133 : -1,
1134 0 : cppu::UnoType<OUString>::get(),
1135 0 : beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND );
1136 :
1137 : // file
1138 0 : seq[0].Type = GIO_FILE_TYPE;
1139 0 : seq[0].Attributes = ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM |
1140 0 : ucb::ContentInfoAttribute::KIND_DOCUMENT );
1141 0 : seq[0].Properties = props;
1142 :
1143 : // folder
1144 0 : seq[1].Type = GIO_FOLDER_TYPE;
1145 0 : seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
1146 0 : seq[1].Properties = props;
1147 :
1148 0 : return seq;
1149 : }
1150 : else
1151 : {
1152 0 : return uno::Sequence< ucb::ContentInfo >();
1153 : }
1154 : }
1155 :
1156 0 : uno::Sequence< ucb::ContentInfo > SAL_CALL Content::queryCreatableContentsInfo()
1157 : throw( uno::RuntimeException, std::exception )
1158 : {
1159 0 : return queryCreatableContentsInfo( uno::Reference< ucb::XCommandEnvironment >() );
1160 : }
1161 :
1162 : uno::Reference< ucb::XContent >
1163 0 : SAL_CALL Content::createNewContent( const ucb::ContentInfo& Info )
1164 : throw( uno::RuntimeException, std::exception )
1165 : {
1166 : bool create_document;
1167 : const char *name;
1168 :
1169 0 : if ( Info.Type == GIO_FILE_TYPE )
1170 0 : create_document = true;
1171 0 : else if ( Info.Type == GIO_FOLDER_TYPE )
1172 0 : create_document = false;
1173 : else
1174 : {
1175 : #ifdef DEBUG
1176 : g_warning( "Failed to create new content '%s'", OUStringToOString(Info.Type,
1177 : RTL_TEXTENCODING_UTF8).getStr() );
1178 : #endif
1179 0 : return uno::Reference< ucb::XContent >();
1180 : }
1181 :
1182 : #if OSL_DEBUG_LEVEL > 1
1183 : g_warning( "createNewContent (%d)", (int) create_document );
1184 : #endif
1185 :
1186 0 : OUString aURL = m_xIdentifier->getContentIdentifier();
1187 :
1188 0 : if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
1189 0 : aURL += "/";
1190 :
1191 0 : name = create_document ? "[New_Content]" : "[New_Collection]";
1192 0 : aURL += OUString::createFromAscii( name );
1193 :
1194 0 : uno::Reference< ucb::XContentIdentifier > xId(new ::ucbhelper::ContentIdentifier(aURL));
1195 :
1196 : try
1197 : {
1198 0 : return new ::gio::Content( m_xContext, m_pProvider, xId, !create_document );
1199 0 : } catch ( ucb::ContentCreationException & )
1200 : {
1201 0 : return uno::Reference< ucb::XContent >();
1202 0 : }
1203 : }
1204 :
1205 0 : uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
1206 : throw( uno::RuntimeException, std::exception )
1207 : {
1208 0 : if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) )
1209 : {
1210 : static cppu::OTypeCollection aFolderCollection
1211 0 : (CPPU_TYPE_REF( lang::XTypeProvider ),
1212 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
1213 0 : CPPU_TYPE_REF( lang::XComponent ),
1214 0 : CPPU_TYPE_REF( ucb::XContent ),
1215 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
1216 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
1217 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
1218 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
1219 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
1220 0 : CPPU_TYPE_REF( container::XChild ),
1221 0 : CPPU_TYPE_REF( ucb::XContentCreator ) );
1222 0 : return aFolderCollection.getTypes();
1223 : }
1224 : else
1225 : {
1226 : static cppu::OTypeCollection aFileCollection
1227 0 : (CPPU_TYPE_REF( lang::XTypeProvider ),
1228 0 : CPPU_TYPE_REF( lang::XServiceInfo ),
1229 0 : CPPU_TYPE_REF( lang::XComponent ),
1230 0 : CPPU_TYPE_REF( ucb::XContent ),
1231 0 : CPPU_TYPE_REF( ucb::XCommandProcessor ),
1232 0 : CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
1233 0 : CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
1234 0 : CPPU_TYPE_REF( beans::XPropertyContainer ),
1235 0 : CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
1236 0 : CPPU_TYPE_REF( container::XChild ) );
1237 :
1238 0 : return aFileCollection.getTypes();
1239 : }
1240 : }
1241 :
1242 3329 : uno::Sequence< beans::Property > Content::getProperties(
1243 : const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
1244 : {
1245 : static const beans::Property aGenericProperties[] =
1246 : {
1247 : beans::Property( OUString( "IsDocument" ),
1248 40 : -1, cppu::UnoType<bool>::get(),
1249 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1250 : beans::Property( OUString( "IsFolder" ),
1251 40 : -1, cppu::UnoType<bool>::get(),
1252 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1253 : beans::Property( OUString( "Title" ),
1254 40 : -1, cppu::UnoType<OUString>::get(),
1255 : beans::PropertyAttribute::BOUND ),
1256 : beans::Property( OUString( "IsReadOnly" ),
1257 40 : -1, cppu::UnoType<bool>::get(),
1258 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1259 : beans::Property( OUString( "DateCreated" ),
1260 40 : -1, cppu::UnoType<util::DateTime>::get(),
1261 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1262 : beans::Property( OUString( "DateModified" ),
1263 40 : -1, cppu::UnoType<util::DateTime>::get(),
1264 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1265 : beans::Property( OUString( "Size" ),
1266 40 : -1, cppu::UnoType<sal_Int64>::get(),
1267 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1268 : beans::Property( OUString( "IsVolume" ),
1269 40 : 1, cppu::UnoType<bool>::get(),
1270 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1271 : beans::Property( OUString( "IsCompactDisc" ),
1272 40 : -1, cppu::UnoType<bool>::get(),
1273 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1274 : beans::Property( OUString( "IsRemoveable" ),
1275 40 : -1, cppu::UnoType<bool>::get(),
1276 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1277 : beans::Property( OUString( "IsHidden" ),
1278 40 : -1, cppu::UnoType<bool>::get(),
1279 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1280 : beans::Property( OUString( "CreatableContentsInfo" ),
1281 40 : -1, cppu::UnoType<uno::Sequence< ucb::ContentInfo >>::get(),
1282 : beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY )
1283 3849 : };
1284 :
1285 3329 : const int nProps = sizeof (aGenericProperties) / sizeof (aGenericProperties[0]);
1286 3329 : return uno::Sequence< beans::Property > ( aGenericProperties, nProps );
1287 : }
1288 :
1289 0 : uno::Sequence< ucb::CommandInfo > Content::getCommands( const uno::Reference< ucb::XCommandEnvironment > & xEnv)
1290 : {
1291 : static const ucb::CommandInfo aCommandInfoTable[] =
1292 : {
1293 : // Required commands
1294 : ucb::CommandInfo
1295 : ( OUString( "getCommandInfo" ),
1296 0 : -1, cppu::UnoType<void>::get() ),
1297 : ucb::CommandInfo
1298 : ( OUString( "getPropertySetInfo" ),
1299 0 : -1, cppu::UnoType<void>::get() ),
1300 : ucb::CommandInfo
1301 : ( OUString( "getPropertyValues" ),
1302 0 : -1, cppu::UnoType<uno::Sequence< beans::Property >>::get() ),
1303 : ucb::CommandInfo
1304 : ( OUString( "setPropertyValues" ),
1305 0 : -1, cppu::UnoType<uno::Sequence< beans::PropertyValue >>::get() ),
1306 :
1307 : // Optional standard commands
1308 : ucb::CommandInfo
1309 : ( OUString( "delete" ),
1310 0 : -1, cppu::UnoType<bool>::get() ),
1311 : ucb::CommandInfo
1312 : ( OUString( "insert" ),
1313 0 : -1, cppu::UnoType<ucb::InsertCommandArgument>::get() ),
1314 : ucb::CommandInfo
1315 : ( OUString( "open" ),
1316 0 : -1, cppu::UnoType<ucb::OpenCommandArgument2>::get() ),
1317 :
1318 : // Folder Only, omitted if not a folder
1319 : ucb::CommandInfo
1320 : ( OUString( "transfer" ),
1321 0 : -1, cppu::UnoType<ucb::TransferInfo>::get() ),
1322 : ucb::CommandInfo
1323 : ( OUString( "createNewContent" ),
1324 0 : -1, cppu::UnoType<ucb::ContentInfo>::get() )
1325 0 : };
1326 :
1327 0 : const int nProps = sizeof (aCommandInfoTable) / sizeof (aCommandInfoTable[0]);
1328 0 : return uno::Sequence< ucb::CommandInfo >(aCommandInfoTable, isFolder(xEnv) ? nProps : nProps - 2);
1329 : }
1330 :
1331 0 : XTYPEPROVIDER_COMMON_IMPL( Content );
1332 :
1333 27699 : void SAL_CALL Content::acquire() throw()
1334 : {
1335 27699 : ContentImplHelper::acquire();
1336 27699 : }
1337 :
1338 27699 : void SAL_CALL Content::release() throw()
1339 : {
1340 27699 : ContentImplHelper::release();
1341 27699 : }
1342 :
1343 3482 : uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType ) throw ( uno::RuntimeException, std::exception )
1344 : {
1345 3482 : uno::Any aRet = cppu::queryInterface( rType, static_cast< ucb::XContentCreator * >( this ) );
1346 3482 : return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface(rType);
1347 : }
1348 :
1349 0 : OUString SAL_CALL Content::getImplementationName() throw( uno::RuntimeException, std::exception )
1350 : {
1351 0 : return OUString("com.sun.star.comp.GIOContent");
1352 : }
1353 :
1354 0 : uno::Sequence< OUString > SAL_CALL Content::getSupportedServiceNames()
1355 : throw( uno::RuntimeException, std::exception )
1356 : {
1357 0 : uno::Sequence< OUString > aSNS( 1 );
1358 0 : aSNS.getArray()[ 0 ] = "com.sun.star.ucb.GIOContent";
1359 0 : return aSNS;
1360 : }
1361 :
1362 : }
1363 :
1364 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|