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 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 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 118 Content::~Content() 119 { 120 if (mpInfo) g_object_unref(mpInfo); 121 if (mpFile) g_object_unref(mpFile); 122 } 123 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 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 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 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 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 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 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 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 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 339 MountOperation::~MountOperation() 340 { 341 g_object_unref(mpAuthentication); 342 g_main_loop_unref(mpLoop); 343 } 344 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 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 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 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 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 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 525 getReadOnlyException( const uno::Reference< uno::XInterface >& rContext ) 526 { 527 return lang::IllegalAccessException ( rtl::OUString::createFromAscii( "Property is read-only!" ), rContext ); 528 } 529 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 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 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 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 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 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 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 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 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 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 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 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 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 > 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 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 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 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 1301 void SAL_CALL Content::acquire() throw() 1302 { 1303 ContentImplHelper::acquire(); 1304 } 1305 1306 void SAL_CALL Content::release() throw() 1307 { 1308 ContentImplHelper::release(); 1309 } 1310 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 1317 rtl::OUString SAL_CALL Content::getImplementationName() throw( uno::RuntimeException ) 1318 { 1319 return rtl::OUString::createFromAscii("com.sun.star.comp.GIOContent" ); 1320 } 1321 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