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