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