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