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