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