LCOV - code coverage report
Current view: top level - libreoffice/ucb/source/ucp/gvfs - gvfs_content.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 699 0.0 %
Date: 2012-12-27 Functions: 0 54 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <string.h>
      21             : #include <unistd.h>
      22             : #include <sys/types.h>
      23             : 
      24             : #include <sal/macros.h>
      25             : #include <osl/time.h>
      26             : #include <osl/diagnose.h>
      27             : 
      28             : #include "osl/doublecheckedlocking.h"
      29             : 
      30             : #include <com/sun/star/beans/PropertyValue.hpp>
      31             : #include <com/sun/star/beans/PropertyAttribute.hpp>
      32             : #include <com/sun/star/beans/PropertySetInfoChange.hpp>
      33             : #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
      34             : #include <com/sun/star/io/XActiveDataSink.hpp>
      35             : #include <com/sun/star/io/XOutputStream.hpp>
      36             : #include <com/sun/star/io/TempFile.hpp>
      37             : #include <com/sun/star/lang/IllegalAccessException.hpp>
      38             : #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
      39             : #include <com/sun/star/ucb/InsertCommandArgument.hpp>
      40             : #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
      41             : #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
      42             : #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
      43             : #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
      44             : #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
      45             : #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
      46             : #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
      47             : #include <com/sun/star/ucb/NameClash.hpp>
      48             : #include <com/sun/star/ucb/NameClashException.hpp>
      49             : #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
      50             : #include <com/sun/star/ucb/OpenMode.hpp>
      51             : #include <com/sun/star/ucb/PostCommandArgument2.hpp>
      52             : #include <com/sun/star/ucb/TransferInfo.hpp>
      53             : #include <com/sun/star/ucb/XCommandInfo.hpp>
      54             : #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
      55             : #include <com/sun/star/ucb/MissingInputStreamException.hpp>
      56             : #include <com/sun/star/ucb/MissingPropertiesException.hpp>
      57             : #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
      58             : #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
      59             : #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
      60             : #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
      61             : #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
      62             : #include <com/sun/star/ucb/NameClashException.hpp>
      63             : #include <comphelper/processfactory.hxx>
      64             : #include <ucbhelper/contentidentifier.hxx>
      65             : #include <ucbhelper/propertyvalueset.hxx>
      66             : #include <ucbhelper/interactionrequest.hxx>
      67             : #include <ucbhelper/cancelcommandexecution.hxx>
      68             : #include <ucbhelper/simpleauthenticationrequest.hxx>
      69             : 
      70             : const int TRANSFER_BUFFER_SIZE = 65536;
      71             : 
      72             : /*
      73             :  * NB. Name escaping is done only for URIs
      74             :  * the 'Title' property is unescaped on set/get
      75             :  */
      76             : #include <libgnomevfs/gnome-vfs-utils.h>
      77             : #include <libgnomevfs/gnome-vfs-result.h>
      78             : #include <libgnomevfs/gnome-vfs-standard-callbacks.h>
      79             : extern "C" { // missing in the header: doh.
      80             : #  include <libgnomevfs/gnome-vfs-module-callback.h>
      81             : }
      82             : 
      83             : #include "gvfs_content.hxx"
      84             : #include "gvfs_provider.hxx"
      85             : #include "gvfs_directory.hxx"
      86             : #include "gvfs_stream.hxx"
      87             : 
      88             : using namespace gvfs;
      89             : using namespace com::sun::star;
      90             : 
      91             : #define CLEAR_INFO(info) memset((info), 0, sizeof ((info)[0]))
      92             : 
      93             : 
      94             : static char *
      95           0 : OUStringToGnome( const rtl::OUString &str )
      96             : {
      97           0 :     rtl::OString aTempStr = rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 );
      98           0 :     return g_strdup( aTempStr.getStr() );
      99             : }
     100             : 
     101             : static rtl::OUString
     102           0 : GnomeToOUString( const char *utf8_str)
     103             : {
     104           0 :     if (!utf8_str)
     105           0 :         return rtl::OUString();
     106             :     else
     107           0 :         return rtl::OUString( utf8_str, strlen( utf8_str ), RTL_TEXTENCODING_UTF8 );
     108             : }
     109             : 
     110             : 
     111           0 : Content::Content(
     112             :           const uno::Reference< uno::XComponentContext >& rxContext,
     113             :           ContentProvider* pProvider,
     114             :           const uno::Reference< ucb::XContentIdentifier >& Identifier)
     115             :   throw ( ucb::ContentCreationException )
     116             :     : ContentImplHelper( rxContext, pProvider, Identifier ),
     117             :       m_pProvider( pProvider ),
     118           0 :       m_bTransient( sal_False )
     119             : {
     120           0 :     CLEAR_INFO (&m_info);
     121             : #if OSL_DEBUG_LEVEL > 1
     122             :     g_warning ("New Content ('%s')", getURI());
     123             : #endif
     124           0 : }
     125             : 
     126           0 : Content::Content(
     127             :     const uno::Reference< uno::XComponentContext >& rxContext,
     128             :     ContentProvider                                   * pProvider,
     129             :     const uno::Reference< ucb::XContentIdentifier >&    Identifier,
     130             :     sal_Bool                                            IsFolder)
     131             :         throw ( ucb::ContentCreationException )
     132             :     : ContentImplHelper( rxContext, pProvider, Identifier ),
     133             :       m_pProvider( pProvider ),
     134           0 :       m_bTransient( sal_True )
     135             : {
     136           0 :     CLEAR_INFO (&m_info);
     137             : 
     138             : #if OSL_DEBUG_LEVEL > 1
     139             :     g_warning ("New Transient content ('%s') (%d)", getURI(), IsFolder);
     140             : #endif
     141             : //  m_info.name = FIXME: set name ?
     142           0 :     m_info.valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE;
     143             :     m_info.type = IsFolder ? GNOME_VFS_FILE_TYPE_DIRECTORY :
     144           0 :                          GNOME_VFS_FILE_TYPE_REGULAR;
     145           0 : }
     146             : 
     147             : // virtual
     148           0 : Content::~Content()
     149             : {
     150           0 :     gnome_vfs_file_info_clear( &m_info );
     151           0 : }
     152             : 
     153             : //
     154             : // XInterface methods.
     155             : //
     156             : 
     157           0 : void SAL_CALL Content::acquire()
     158             :     throw( )
     159             : {
     160           0 :     ContentImplHelper::acquire();
     161           0 : }
     162           0 : void SAL_CALL Content::release()
     163             :     throw( )
     164             : {
     165           0 :     ContentImplHelper::release();
     166           0 : }
     167           0 : uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
     168             :     throw ( uno::RuntimeException )
     169             : {
     170             :     // Note: isFolder may require network activities! So call it only
     171             :     //       if it is really necessary!!!
     172             :     uno::Any aRet = cppu::queryInterface( rType,
     173           0 :                         static_cast< ucb::XContentCreator * >( this ) );
     174           0 :     if ( aRet.hasValue() )
     175           0 :             return isFolder( uno::Reference< ucb::XCommandEnvironment >() )
     176           0 :             ? aRet : uno::Any();
     177             :     else
     178           0 :         return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
     179             : }
     180             : 
     181             : //
     182             : // XTypeProvider methods.
     183             : //
     184             : 
     185           0 : XTYPEPROVIDER_COMMON_IMPL( Content );
     186             : 
     187           0 : uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
     188             :     throw( uno::RuntimeException )
     189             : {
     190             :     static cppu::OTypeCollection *pFolderCollection = NULL;
     191             :     static cppu::OTypeCollection *pFileCollection = NULL;
     192             : 
     193           0 :     if (!pFolderCollection) {
     194           0 :         osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
     195             : 
     196           0 :         if (!pFolderCollection) {
     197             :             static cppu::OTypeCollection aFolderCollection
     198           0 :                 (CPPU_TYPE_REF( lang::XTypeProvider ),
     199           0 :                  CPPU_TYPE_REF( lang::XServiceInfo ),
     200           0 :                  CPPU_TYPE_REF( lang::XComponent ),
     201           0 :                  CPPU_TYPE_REF( ucb::XContent ),
     202           0 :                  CPPU_TYPE_REF( ucb::XCommandProcessor ),
     203           0 :                  CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
     204           0 :                  CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
     205           0 :                  CPPU_TYPE_REF( beans::XPropertyContainer ),
     206           0 :                  CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
     207           0 :                  CPPU_TYPE_REF( container::XChild ),
     208           0 :                  CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
     209             :             static cppu::OTypeCollection aFileCollection
     210           0 :                 (CPPU_TYPE_REF( lang::XTypeProvider ),
     211           0 :                  CPPU_TYPE_REF( lang::XServiceInfo ),
     212           0 :                  CPPU_TYPE_REF( lang::XComponent ),
     213           0 :                  CPPU_TYPE_REF( ucb::XContent ),
     214           0 :                  CPPU_TYPE_REF( ucb::XCommandProcessor ),
     215           0 :                  CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
     216           0 :                  CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
     217           0 :                  CPPU_TYPE_REF( beans::XPropertyContainer ),
     218           0 :                  CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
     219           0 :                  CPPU_TYPE_REF( container::XChild ) );
     220             : 
     221           0 :             pFolderCollection = &aFolderCollection;
     222           0 :             pFileCollection = &aFileCollection;
     223             :             OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     224           0 :         }
     225             :     }
     226             :     else {
     227             :         OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
     228             :     }
     229             : 
     230           0 :     if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) )
     231           0 :         return pFolderCollection->getTypes();
     232             :     else
     233           0 :         return pFileCollection->getTypes();
     234             : }
     235             : 
     236             : //
     237             : // XServiceInfo methods.
     238             : //
     239             : 
     240           0 : rtl::OUString SAL_CALL Content::getImplementationName()
     241             :     throw( uno::RuntimeException )
     242             : {
     243           0 :     return rtl::OUString("com.sun.star.comp.GnomeVFSContent");
     244             : }
     245             : 
     246           0 : uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
     247             :     throw( uno::RuntimeException )
     248             : {
     249           0 :     uno::Sequence< rtl::OUString > aSNS( 1 );
     250           0 :     aSNS.getArray()[ 0 ] = rtl::OUString( "com.sun.star.ucb.GnomeVFSContent" );
     251           0 :     return aSNS;
     252             : }
     253             : 
     254             : //
     255             : // XContent methods.
     256             : //
     257             : 
     258           0 : rtl::OUString SAL_CALL Content::getContentType()
     259             :     throw( uno::RuntimeException )
     260             : {
     261           0 :     if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) )
     262           0 :         return rtl::OUString( GVFS_FOLDER_TYPE );
     263             :     else
     264           0 :         return rtl::OUString( GVFS_FILE_TYPE );
     265             : }
     266             : 
     267             : //
     268             : // XCommandProcessor methods.
     269             : //
     270             : 
     271           0 : uno::Any Content::getBadArgExcept()
     272             : {
     273             :     return uno::makeAny( lang::IllegalArgumentException
     274             :                  ( rtl::OUString("Wrong argument type!"),
     275             :                    static_cast< cppu::OWeakObject * >( this ),
     276           0 :                    -1 ) );
     277             : }
     278             : 
     279             : #include <stdio.h>
     280             : 
     281           0 : uno::Any SAL_CALL Content::execute(
     282             :         const ucb::Command& aCommand,
     283             :         sal_Int32 /*CommandId*/,
     284             :         const uno::Reference< ucb::XCommandEnvironment >& xEnv )
     285             :     throw( uno::Exception,
     286             :            ucb::CommandAbortedException,
     287             :            uno::RuntimeException )
     288             : {
     289           0 :     uno::Any aRet;
     290             : 
     291             : #if OSL_DEBUG_LEVEL > 1
     292             :     {
     293             :         uno::Reference< task::XInteractionHandler > xIH;
     294             : 
     295             :         if ( xEnv.is() )
     296             :             xIH = xEnv->getInteractionHandler();
     297             :         g_warning( "Execute command: '%s' with %s interaction env",
     298             :                OUStringToGnome( aCommand.Name ),
     299             :                xIH.is() ? "" : "NO" );
     300             :     }
     301             : #endif
     302             : 
     303             : #define COMMAND_IS(cmd,name) ( (cmd).Name == name )
     304             : 
     305           0 :     if ( COMMAND_IS( aCommand, "getPropertyValues" ) ) {
     306           0 :         uno::Sequence< beans::Property > Properties;
     307             : 
     308           0 :         if ( !( aCommand.Argument >>= Properties ) )
     309           0 :             ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
     310             : 
     311           0 :         aRet <<= getPropertyValues( Properties, xEnv );
     312             : 
     313           0 :     } else if ( COMMAND_IS( aCommand, "setPropertyValues" ) ) {
     314           0 :         uno::Sequence< beans::PropertyValue > aProperties;
     315             : 
     316           0 :         if ( !( aCommand.Argument >>= aProperties ) ||
     317           0 :              !aProperties.getLength() )
     318           0 :             ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
     319             : 
     320           0 :         aRet <<= setPropertyValues( aProperties, xEnv );
     321             : 
     322           0 :     } else if ( COMMAND_IS( aCommand, "getPropertySetInfo" ) ) {
     323           0 :         aRet <<= getPropertySetInfo( xEnv, sal_False );
     324             : 
     325           0 :     } else if ( COMMAND_IS( aCommand, "getCommandInfo" ) ) {
     326           0 :         aRet <<= getCommandInfo( xEnv, sal_False );
     327             : 
     328           0 :     } else if ( COMMAND_IS( aCommand, "open" ) ) {
     329           0 :         rtl::OUString str = m_xIdentifier->getContentIdentifier();
     330             :         rtl::OString stra(
     331             :             str.getStr(),
     332             :             str.getLength(),
     333           0 :             RTL_TEXTENCODING_UTF8);
     334             : 
     335           0 :         ucb::OpenCommandArgument2 aOpenCommand;
     336           0 :         if ( !( aCommand.Argument >>= aOpenCommand ) )
     337           0 :             ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
     338             : 
     339             :         sal_Bool bOpenFolder =
     340             :             ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) ||
     341             :               ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) ||
     342           0 :               ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) );
     343             : 
     344           0 :         if ( bOpenFolder && isFolder( xEnv ) ) {
     345             :             uno::Reference< ucb::XDynamicResultSet > xSet
     346           0 :                 = new DynamicResultSet( m_xContext, this, aOpenCommand, xEnv );
     347           0 :             aRet <<= xSet;
     348             : 
     349           0 :         } else if ( aOpenCommand.Sink.is() ) {
     350             : 
     351           0 :             if ( ( aOpenCommand.Mode
     352             :                    == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
     353             :                  ( aOpenCommand.Mode
     354             :                    == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) {
     355             :                 ucbhelper::cancelCommandExecution
     356             :                     ( uno::makeAny ( ucb::UnsupportedOpenModeException
     357             :                              ( rtl::OUString(),
     358             :                                static_cast< cppu::OWeakObject * >( this ),
     359             :                                sal_Int16( aOpenCommand.Mode ) ) ),
     360           0 :                       xEnv );
     361             :             }
     362           0 :             if ( !feedSink( aOpenCommand.Sink, xEnv ) ) {
     363             :                 // Note: aOpenCommand.Sink may contain an XStream
     364             :                 //       implementation. Support for this type of
     365             :                 //       sink is optional...
     366             : #ifdef DEBUG
     367             :                 g_warning ("Failed to load data from '%s'", getURI());
     368             : #endif
     369             :                 ucbhelper::cancelCommandExecution
     370             :                     ( uno::makeAny (ucb::UnsupportedDataSinkException
     371             :                             ( rtl::OUString(),
     372             :                               static_cast< cppu::OWeakObject * >( this ),
     373             :                               aOpenCommand.Sink ) ),
     374           0 :                       xEnv );
     375             :             }
     376           0 :         }
     377             : #ifdef DEBUG
     378             :         else
     379             :             g_warning ("Open falling through ...");
     380             : #endif
     381             : 
     382           0 :     } else if ( COMMAND_IS( aCommand, "createNewContent" ) && isFolder( xEnv ) ) {
     383           0 :         ucb::ContentInfo arg;
     384           0 :         if ( !( aCommand.Argument >>= arg ) )
     385           0 :             ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
     386             : 
     387           0 :         aRet <<= createNewContent( arg );
     388             : 
     389           0 :     } else if ( COMMAND_IS( aCommand, "insert" ) ) {
     390           0 :         ucb::InsertCommandArgument arg;
     391           0 :         if ( !( aCommand.Argument >>= arg ) )
     392           0 :             ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
     393             : 
     394           0 :         insert( arg.Data, arg.ReplaceExisting, xEnv );
     395             : 
     396           0 :     } else if ( COMMAND_IS( aCommand, "delete" ) ) {
     397             : 
     398           0 :         sal_Bool bDeletePhysical = sal_False;
     399           0 :         aCommand.Argument >>= bDeletePhysical;
     400             : 
     401           0 :         ::rtl::OString aURI = getOURI();
     402           0 :         GnomeVFSResult result = gnome_vfs_unlink (aURI.getStr());
     403             : 
     404           0 :         if (result != GNOME_VFS_OK)
     405           0 :             cancelCommandExecution( result, xEnv, sal_True );
     406             : 
     407           0 :         destroy( bDeletePhysical );
     408             : 
     409           0 :     } else if ( COMMAND_IS( aCommand, "transfer" ) && isFolder( xEnv ) ) {
     410           0 :         ucb::TransferInfo transferArgs;
     411             : 
     412           0 :         if ( !( aCommand.Argument >>= transferArgs ) )
     413           0 :             ucbhelper::cancelCommandExecution( getBadArgExcept(), xEnv );
     414             : 
     415           0 :         transfer( transferArgs, xEnv );
     416             : 
     417             :     } else { // Unsuported
     418             : #ifdef DEBUG
     419             :         g_warning( "Unsupported command: '%s'",
     420             :                OUStringToGnome( aCommand.Name ) );
     421             : #endif
     422             :         ucbhelper::cancelCommandExecution
     423             :             ( uno::makeAny( ucb::UnsupportedCommandException
     424             :                     ( rtl::OUString(),
     425             :                       static_cast< cppu::OWeakObject * >( this ) ) ),
     426           0 :               xEnv );
     427             :     }
     428             : #undef COMMAND_IS
     429             : 
     430           0 :     return aRet;
     431             : }
     432             : 
     433           0 : void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
     434             :     throw( uno::RuntimeException )
     435             : {
     436             :     // FIXME: we should use the GnomeVFSCancellation APIs here ...
     437           0 : }
     438             : 
     439             : //
     440             : // XContentCreator methods.
     441             : //
     442             : 
     443           0 : uno::Sequence< ucb::ContentInfo > Content::queryCreatableContentsInfo(
     444             :     const uno::Reference< ucb::XCommandEnvironment >& xEnv)
     445             :             throw( uno::RuntimeException )
     446             : {
     447           0 :     if ( isFolder( xEnv ) )
     448             :     {
     449           0 :         uno::Sequence< ucb::ContentInfo > seq(2);
     450             : 
     451             :         // Minimum set of props we really need
     452           0 :         uno::Sequence< beans::Property > props( 1 );
     453           0 :         props[0] = beans::Property(
     454             :             rtl::OUString("Title"),
     455             :             -1,
     456           0 :             getCppuType( static_cast< rtl::OUString* >( 0 ) ),
     457           0 :             beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND );
     458             : 
     459             :         // file
     460           0 :         seq[0].Type       = rtl::OUString( GVFS_FILE_TYPE );
     461           0 :         seq[0].Attributes = ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM |
     462           0 :                               ucb::ContentInfoAttribute::KIND_DOCUMENT );
     463           0 :         seq[0].Properties = props;
     464             : 
     465             :         // folder
     466           0 :         seq[1].Type       = rtl::OUString( GVFS_FOLDER_TYPE );
     467           0 :         seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
     468           0 :         seq[1].Properties = props;
     469             : 
     470           0 :         return seq;
     471             :     }
     472             :     else
     473             :     {
     474           0 :         return uno::Sequence< ucb::ContentInfo >();
     475             :     }
     476             : }
     477             : 
     478           0 : uno::Sequence< ucb::ContentInfo > SAL_CALL Content::queryCreatableContentsInfo()
     479             :             throw( uno::RuntimeException )
     480             : {
     481           0 :     return queryCreatableContentsInfo( uno::Reference< ucb::XCommandEnvironment >() );
     482             : }
     483             : 
     484             : uno::Reference< ucb::XContent > SAL_CALL
     485           0 : Content::createNewContent( const ucb::ContentInfo& Info )
     486             :     throw( uno::RuntimeException )
     487             : {
     488             :     bool create_document;
     489             :     const char *name;
     490             : 
     491           0 :         if ( Info.Type == GVFS_FILE_TYPE )
     492           0 :         create_document = true;
     493           0 :     else if ( Info.Type == GVFS_FOLDER_TYPE )
     494           0 :         create_document = false;
     495             :     else {
     496             : #ifdef DEBUG
     497             :         g_warning( "Failed to create new content '%s'",
     498             :                OUStringToGnome( Info.Type ) );
     499             : #endif
     500           0 :         return uno::Reference< ucb::XContent >();
     501             :     }
     502             : 
     503             : #if OSL_DEBUG_LEVEL > 1
     504             :     g_warning( "createNewContent (%d)", (int) create_document );
     505             : #endif
     506             : 
     507           0 :     rtl::OUString aURL = getOUURI();
     508             : 
     509           0 :     if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
     510           0 :         aURL += rtl::OUString("/");
     511             : 
     512           0 :     name = create_document ? "[New_Content]" : "[New_Collection]";
     513             :     // This looks problematic to me cf. webdav
     514           0 :     aURL += rtl::OUString::createFromAscii( name );
     515             : 
     516             :     uno::Reference< ucb::XContentIdentifier > xId
     517           0 :         ( new ::ucbhelper::ContentIdentifier( aURL ) );
     518             : 
     519             :     try {
     520           0 :         return new ::gvfs::Content( m_xContext, m_pProvider, xId, !create_document );
     521           0 :     } catch ( ucb::ContentCreationException & ) {
     522           0 :         return uno::Reference< ucb::XContent >();
     523           0 :     }
     524             : }
     525             : 
     526           0 : rtl::OUString Content::getParentURL()
     527             : {
     528           0 :     rtl::OUString aParentURL;
     529             :     // <scheme>://              -> ""
     530             :     // <scheme>://foo           -> ""
     531             :     // <scheme>://foo/          -> ""
     532             :     // <scheme>://foo/bar       -> <scheme>://foo/
     533             :     // <scheme>://foo/bar/      -> <scheme>://foo/
     534             :     // <scheme>://foo/bar/abc   -> <scheme>://foo/bar/
     535             : 
     536           0 :     rtl::OUString aURL = getOUURI();
     537             : 
     538           0 :     sal_Int32 nPos = aURL.lastIndexOf( '/' );
     539           0 :     if ( nPos == ( aURL.getLength() - 1 ) ) {
     540             :         // Trailing slash found. Skip.
     541           0 :         nPos = aURL.lastIndexOf( '/', nPos );
     542             :     }
     543             : 
     544           0 :     sal_Int32 nPos1 = aURL.lastIndexOf( '/', nPos );
     545           0 :     if ( nPos1 != -1 )
     546           0 :         nPos1 = aURL.lastIndexOf( '/', nPos1 );
     547             : 
     548           0 :     if ( nPos1 != -1 )
     549           0 :         aParentURL = rtl::OUString( aURL.copy( 0, nPos + 1 ) );
     550             : 
     551             : #if OSL_DEBUG_LEVEL > 1
     552             :     g_warning ("getParentURL '%s' -> '%s'",
     553             :            getURI(), rtl::OUStringToOString
     554             :                ( aParentURL, RTL_TEXTENCODING_UTF8 ).getStr() );
     555             : #endif
     556             : 
     557           0 :     return aParentURL;
     558             : }
     559             : 
     560             : static util::DateTime
     561           0 : getDateFromUnix (time_t t)
     562             : {
     563             :     TimeValue tv;
     564           0 :     tv.Nanosec = 0;
     565           0 :     tv.Seconds = t;
     566             :     oslDateTime dt;
     567             : 
     568           0 :     if ( osl_getDateTimeFromTimeValue( &tv, &dt ) )
     569             :         return util::DateTime( 0, dt.Seconds, dt.Minutes, dt.Hours,
     570           0 :                                dt.Day, dt.Month, dt.Year);
     571             :     else
     572           0 :         return util::DateTime();
     573             : }
     574             : 
     575           0 : uno::Reference< sdbc::XRow > Content::getPropertyValues(
     576             :                 const uno::Sequence< beans::Property >& rProperties,
     577             :                 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
     578             : {
     579             :     int nProps;
     580             :     GnomeVFSResult result;
     581           0 :     uno::Sequence< beans::Property > allProperties;
     582             : 
     583           0 :     if( ( result = getInfo( xEnv ) ) != GNOME_VFS_OK )
     584           0 :         cancelCommandExecution( result, xEnv, sal_False );
     585             : 
     586             :     const beans::Property* pProps;
     587             : 
     588           0 :     if( rProperties.getLength() ) {
     589           0 :         nProps = rProperties.getLength();
     590           0 :         pProps = rProperties.getConstArray();
     591             :     } else {
     592           0 :         allProperties = getPropertySetInfo( xEnv )->getProperties();
     593           0 :         nProps = allProperties.getLength();
     594           0 :         pProps = allProperties.getConstArray();
     595             :     }
     596             : 
     597             :     rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
     598           0 :         = new ::ucbhelper::PropertyValueSet( m_xContext );
     599             : 
     600           0 :         osl::Guard< osl::Mutex > aGuard( m_aMutex );
     601           0 :     for( sal_Int32 n = 0; n < nProps; ++n ) {
     602           0 :         const beans::Property& rProp = pProps[ n ];
     603             : 
     604           0 :         if ( rProp.Name == "Title" ) {
     605           0 :             if (m_info.name && m_info.name[0] == '/')
     606           0 :                 g_warning ("Odd NFS title on item '%s' == '%s'",
     607           0 :                        getURI(), m_info.name);
     608           0 :             xRow->appendString( rProp, GnomeToOUString( m_info.name ) );
     609             :         }
     610             : 
     611           0 :         else if ( rProp.Name == "ContentType" )
     612           0 :             xRow->appendString( rProp, getContentType () );
     613             : 
     614           0 :         else if ( rProp.Name == "IsDocument" ) {
     615           0 :             if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE)
     616             :                 xRow->appendBoolean( rProp, ( m_info.type == GNOME_VFS_FILE_TYPE_REGULAR ||
     617           0 :                                   m_info.type == GNOME_VFS_FILE_TYPE_UNKNOWN ) );
     618             :             else
     619           0 :                 xRow->appendVoid( rProp );
     620             :         }
     621           0 :         else if ( rProp.Name == "IsFolder" ) {
     622           0 :             if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE)
     623           0 :                 xRow->appendBoolean( rProp, ( m_info.type == GNOME_VFS_FILE_TYPE_DIRECTORY ) );
     624             :             else
     625           0 :                 xRow->appendVoid( rProp );
     626             :         }
     627           0 :         else if ( rProp.Name == "IsReadOnly" ) {
     628             : 
     629           0 :             GnomeVFSFileInfo* fileInfo = gnome_vfs_file_info_new ();
     630             : 
     631           0 :             ::rtl::OString aURI = getOURI();
     632             :             gnome_vfs_get_file_info
     633             :                 ( aURI.getStr(), fileInfo,
     634           0 :                         GNOME_VFS_FILE_INFO_GET_ACCESS_RIGHTS );
     635             : 
     636           0 :             if (fileInfo->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_ACCESS) {
     637           0 :                 bool read_only = true;
     638             : 
     639           0 :                 if (fileInfo->permissions & GNOME_VFS_PERM_ACCESS_WRITABLE)
     640           0 :                                         read_only = false;
     641             : 
     642           0 :                 xRow->appendBoolean( rProp, read_only );
     643             :             } else
     644           0 :                 xRow->appendVoid( rProp );
     645           0 :             gnome_vfs_file_info_unref (fileInfo);
     646             :         }
     647           0 :         else if ( rProp.Name == "Size" ) {
     648           0 :             if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)
     649           0 :                 xRow->appendLong( rProp, m_info.size );
     650             :             else
     651           0 :                 xRow->appendVoid( rProp );
     652             :         }
     653           0 :         else if ( rProp.Name == "IsHidden" )
     654           0 :             xRow->appendBoolean( rProp, ( m_info.name && m_info.name[0] == '.' ) );
     655             : 
     656           0 :         else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsVolume" ) ) ||
     657           0 :              rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsCompactDisk" ) ) )
     658           0 :             xRow->appendBoolean( rProp, sal_False );
     659             : 
     660           0 :         else if ( rProp.Name == "DateCreated" ) {
     661           0 :             if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_CTIME)
     662           0 :                 xRow->appendTimestamp( rProp, getDateFromUnix( m_info.ctime ) );
     663             :             else
     664           0 :                 xRow->appendVoid( rProp );
     665             :         }
     666             : 
     667           0 :         else if ( rProp.Name == "DateModified" ) {
     668           0 :             if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME)
     669           0 :                 xRow->appendTimestamp( rProp, getDateFromUnix( m_info.mtime ) );
     670             :             else
     671           0 :                 xRow->appendVoid( rProp );
     672             :         }
     673             : 
     674           0 :         else if ( rProp.Name == "MediaType" ) {
     675             :             // We do this by sniffing in gnome-vfs; rather expensively.
     676             : #ifdef DEBUG
     677             :             g_warning ("FIXME: Requested mime-type - an expensive op. indeed!");
     678             : #endif
     679           0 :             xRow->appendVoid( rProp );
     680           0 :         } else if ( rProp.Name == "CreatableContentsInfo" )
     681           0 :             xRow->appendObject( rProp, uno::makeAny( queryCreatableContentsInfo( xEnv ) ) );
     682             : 
     683             :         else {
     684           0 :             xRow->appendVoid( rProp );
     685             :         }
     686             :     }
     687             : #if OSL_DEBUG_LEVEL > 1
     688             :     g_warning ("getPropertyValues on '%s' %d properties returned (of %d)",
     689             :            getURI(), 0, (int)nProps);
     690             : #endif
     691             : 
     692           0 :     return uno::Reference< sdbc::XRow >( xRow.get() );
     693             : }
     694             : 
     695             : static lang::IllegalAccessException
     696           0 : getReadOnlyException( Content *ctnt )
     697             : {
     698             :     return lang::IllegalAccessException
     699             :         ( rtl::OUString("Property is read-only!"),
     700           0 :           static_cast< cppu::OWeakObject * >( ctnt ) );
     701             : }
     702             : 
     703             : rtl::OUString
     704           0 : Content::makeNewURL( const char */*newName*/ )
     705             : {
     706           0 :     rtl::OUString aNewURL = getParentURL();
     707           0 :     if ( aNewURL.lastIndexOf( '/' ) != ( aNewURL.getLength() - 1 ) )
     708           0 :         aNewURL += rtl::OUString("/");
     709             : 
     710           0 :     char *name = gnome_vfs_escape_string( m_info.name );
     711           0 :     aNewURL += GnomeToOUString( name );
     712           0 :     g_free( name );
     713             : 
     714           0 :     return aNewURL;
     715             : }
     716             : 
     717             : // This is slightly complicated by needing to support either 'move' or 'setname'
     718             : GnomeVFSResult
     719           0 : Content::doSetFileInfo( const GnomeVFSFileInfo *newInfo,
     720             :             GnomeVFSSetFileInfoMask setMask,
     721             :             const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ )
     722             : {
     723           0 :     GnomeVFSResult result = GNOME_VFS_OK;
     724             : 
     725           0 :     g_assert (!m_bTransient);
     726             : 
     727           0 :     ::rtl::OString aURI = getOURI();
     728             : 
     729           0 :         osl::Guard< osl::Mutex > aGuard( m_aMutex );
     730             : 
     731             :     // The simple approach:
     732           0 :     if( setMask != GNOME_VFS_SET_FILE_INFO_NONE )
     733             :         result = gnome_vfs_set_file_info // missed a const in the API there
     734           0 :             ( aURI.getStr(), (GnomeVFSFileInfo *)newInfo, setMask );
     735             : 
     736           0 :     if ( result == GNOME_VFS_ERROR_NOT_SUPPORTED &&
     737             :          ( setMask & GNOME_VFS_SET_FILE_INFO_NAME ) ) {
     738             :         // Try a move instead
     739             : #ifdef DEBUG
     740             :         g_warning( "SetFileInfo not supported on '%s'", getURI() );
     741             : #endif
     742             : 
     743           0 :         char *newURI = OUStringToGnome( makeNewURL( newInfo->name ) );
     744             : 
     745           0 :         result = gnome_vfs_move (aURI.getStr(), newURI, FALSE);
     746             : 
     747           0 :         g_free (newURI);
     748             :     }
     749             : 
     750           0 :     return result;
     751             : }
     752             : 
     753             : 
     754           0 : uno::Sequence< uno::Any > Content::setPropertyValues(
     755             :                 const uno::Sequence< beans::PropertyValue >& rValues,
     756             :                 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
     757             : {
     758           0 :     rtl::OUString    aNewTitle;
     759             :     GnomeVFSFileInfo newInfo;
     760           0 :     int              setMask = GNOME_VFS_SET_FILE_INFO_NONE;
     761             : 
     762           0 :     getInfo( xEnv );
     763             : 
     764           0 :     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
     765             : 
     766           0 :     gnome_vfs_file_info_copy( &newInfo, &m_info );
     767             : 
     768           0 :     Authentication aAuth( xEnv );
     769             : 
     770           0 :     int nChanged = 0, nTitlePos = 0;
     771           0 :     uno::Sequence< uno::Any > aRet( rValues.getLength() );
     772           0 :     uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
     773             : 
     774           0 :     beans::PropertyChangeEvent aEvent;
     775           0 :     aEvent.Source         = static_cast< cppu::OWeakObject * >( this );
     776           0 :     aEvent.Further        = sal_False;
     777           0 :     aEvent.PropertyHandle = -1;
     778             :     // aEvent.PropertyName = fill in later ...
     779             :     // aEvent.OldValue     =
     780             :     // aEvent.NewValue     =
     781             : 
     782           0 :     int nCount = rValues.getLength();
     783           0 :     const beans::PropertyValue* pValues = rValues.getConstArray();
     784             : 
     785           0 :     for ( sal_Int32 n = 0; n < nCount; ++n ) {
     786           0 :         const beans::PropertyValue& rValue = pValues[ n ];
     787             : 
     788             : #if OSL_DEBUG_LEVEL > 1
     789             :         g_warning( "Set prop '%s'", OUStringToGnome( rValue.Name ) );
     790             : #endif
     791           0 :         if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ||
     792           0 :              rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ||
     793           0 :              rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ||
     794           0 :              rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ||
     795           0 :              rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ||
     796           0 :              rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "CreatableContentsInfo" ) ) )
     797           0 :             aRet[ n ] <<= getReadOnlyException( this );
     798             : 
     799           0 :         else if ( rValue.Name == "Title" ) {
     800           0 :             if ( rValue.Value >>= aNewTitle ) {
     801           0 :                 if ( aNewTitle.isEmpty() )
     802           0 :                     aRet[ n ] <<= lang::IllegalArgumentException
     803             :                         ( rtl::OUString("Empty title not allowed!"),
     804           0 :                           static_cast< cppu::OWeakObject * >( this ), -1 );
     805             :                 else {
     806           0 :                     char *newName = OUStringToGnome( aNewTitle );
     807             : 
     808           0 :                     if( !newName || !m_info.name || strcmp( newName, m_info.name ) ) {
     809             : #if OSL_DEBUG_LEVEL > 1
     810             :                         g_warning ("Set new name to '%s'", newName);
     811             : #endif
     812             : 
     813           0 :                         aEvent.PropertyName = rtl::OUString("Title");
     814           0 :                         aEvent.OldValue     = uno::makeAny( GnomeToOUString( newInfo.name ) );
     815           0 :                         aEvent.NewValue     = uno::makeAny( aNewTitle );
     816           0 :                         aChanges.getArray()[ nChanged ] = aEvent;
     817           0 :                         nTitlePos = nChanged++;
     818             : 
     819           0 :                         newInfo.name = newName;
     820           0 :                         setMask |= GNOME_VFS_SET_FILE_INFO_NAME;
     821             :                     } else // same name
     822           0 :                         g_free (newName);
     823             :                 }
     824             :             } else
     825           0 :                 aRet[ n ] <<= beans::IllegalTypeException
     826             :                     ( rtl::OUString("Property value has wrong type!"),
     827           0 :                       static_cast< cppu::OWeakObject * >( this ) );
     828             : 
     829           0 :         } else if ( rValue.Name == "DateCreated" || rValue.Name == "DateModified" ) {
     830             :             // FIXME: should be able to set the timestamps
     831           0 :             aRet[ n ] <<= getReadOnlyException( this );
     832             :         } else {
     833             : #ifdef DEBUG
     834             :             g_warning( "Unhandled property '%s'", OUStringToGnome( rValue.Name ) );
     835             : #endif
     836           0 :             aRet[ n ] <<= getReadOnlyException( this );
     837             :         }
     838             :     }
     839             : 
     840           0 :     GnomeVFSResult result = GNOME_VFS_OK;
     841             : 
     842           0 :     if ( !m_bTransient &&
     843             :          ( result = doSetFileInfo( &newInfo,
     844             :                        (GnomeVFSSetFileInfoMask) setMask,
     845           0 :                        xEnv ) ) != GNOME_VFS_OK ) {
     846           0 :         for (int i = 0; i < nChanged; i++)
     847           0 :             aRet[ i ] <<= mapVFSException( result, sal_True );
     848             : 
     849             :     }
     850             : 
     851           0 :     if ( result == GNOME_VFS_OK) {
     852           0 :         gnome_vfs_file_info_copy( &m_info, &newInfo );
     853             : 
     854           0 :         if ( setMask & GNOME_VFS_SET_FILE_INFO_NAME ) {
     855             :             uno::Reference< ucb::XContentIdentifier > xNewId
     856           0 :                 = new ::ucbhelper::ContentIdentifier( makeNewURL( newInfo.name ) );
     857             : 
     858           0 :             aGuard.clear();
     859           0 :             if (!exchangeIdentity( xNewId ) )
     860           0 :                 aRet[ nTitlePos ] <<= uno::Exception
     861             :                     ( rtl::OUString("Exchange failed!"),
     862           0 :                       static_cast< cppu::OWeakObject * >( this ) );
     863             :         }
     864             :     }
     865             : 
     866           0 :     gnome_vfs_file_info_clear( &newInfo );
     867             : 
     868           0 :     if ( nChanged > 0 ) {
     869           0 :             aGuard.clear();
     870           0 :         aChanges.realloc( nChanged );
     871           0 :         notifyPropertiesChange( aChanges );
     872             :     }
     873             : 
     874           0 :     return aRet;
     875             : }
     876             : 
     877           0 : void Content::queryChildren( ContentRefList& rChildren )
     878             : {
     879             :     // Obtain a list with a snapshot of all currently instanciated contents
     880             :     // from provider and extract the contents which are direct children
     881             :     // of this content.
     882             : 
     883           0 :     ::ucbhelper::ContentRefList aAllContents;
     884           0 :     m_xProvider->queryExistingContents( aAllContents );
     885             : 
     886           0 :     rtl::OUString aURL = getOUURI();
     887           0 :     sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
     888             : 
     889           0 :     if ( nURLPos != ( aURL.getLength() - 1 ) )
     890           0 :         aURL += rtl::OUString("/");
     891             : 
     892           0 :     sal_Int32 nLen = aURL.getLength();
     893             : 
     894           0 :     ::ucbhelper::ContentRefList::const_iterator it  = aAllContents.begin();
     895           0 :     ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
     896             : 
     897           0 :     while ( it != end ) {
     898           0 :         ::ucbhelper::ContentImplHelperRef xChild = (*it);
     899             :         rtl::OUString aChildURL
     900           0 :             = xChild->getIdentifier()->getContentIdentifier();
     901             : 
     902             :         // Is aURL a prefix of aChildURL?
     903           0 :         if ( ( aChildURL.getLength() > nLen ) &&
     904           0 :              ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) {
     905           0 :             sal_Int32 nPos = nLen;
     906           0 :             nPos = aChildURL.indexOf( '/', nPos );
     907             : 
     908           0 :             if ( ( nPos == -1 ) ||
     909           0 :                  ( nPos == ( aChildURL.getLength() - 1 ) ) ) {
     910             :                 // No further slashes / only a final slash. It's a child!
     911             :                 rChildren.push_back( ::gvfs::Content::ContentRef
     912           0 :                              (static_cast< ::gvfs::Content * >(xChild.get() ) ) );
     913             :             }
     914             :         }
     915           0 :         ++it;
     916           0 :     }
     917           0 : }
     918             : 
     919           0 : void Content::insert(
     920             :         const uno::Reference< io::XInputStream >               &xInputStream,
     921             :         sal_Bool                                                bReplaceExisting,
     922             :         const uno::Reference< ucb::XCommandEnvironment > &xEnv )
     923             :         throw( uno::Exception )
     924             : {
     925           0 :     osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
     926             : 
     927             : #if OSL_DEBUG_LEVEL > 1
     928             :     g_warning( "Insert '%s' (%d) (0x%x:%d)", getURI(), bReplaceExisting,
     929             :            m_info.valid_fields, m_info.type );
     930             : #endif
     931             : 
     932           0 :     GnomeVFSResult result = getInfo( xEnv );
     933             :     // a racy design indeed.
     934           0 :     if( !bReplaceExisting && !m_bTransient &&
     935             :         result != GNOME_VFS_ERROR_NOT_FOUND) {
     936             : #ifdef DEBUG
     937             :         g_warning ("Nasty error inserting to '%s' ('%s')",
     938             :                getURI(), gnome_vfs_result_to_string( result ));
     939             : #endif
     940           0 :         cancelCommandExecution( GNOME_VFS_ERROR_FILE_EXISTS, xEnv, sal_True );
     941             :     }
     942             : 
     943           0 :     if ( m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE &&
     944             :          m_info.type == GNOME_VFS_FILE_TYPE_DIRECTORY ) {
     945           0 :         ::rtl::OString aURI = getOURI();
     946             :         int perm;
     947             : 
     948             :         perm = ( GNOME_VFS_PERM_USER_ALL |
     949             :              GNOME_VFS_PERM_GROUP_READ |
     950           0 :              GNOME_VFS_PERM_OTHER_READ );
     951             : 
     952             : #if OSL_DEBUG_LEVEL > 1
     953             :         g_warning ("Make directory");
     954             : #endif
     955           0 :         result = gnome_vfs_make_directory( aURI.getStr(), perm );
     956             : 
     957           0 :         if( result != GNOME_VFS_OK )
     958           0 :             cancelCommandExecution( result, xEnv, sal_True );
     959             : 
     960           0 :         return;
     961             :     }
     962             : 
     963           0 :     if ( !xInputStream.is() ) {
     964             :         // FIXME: slightly unclear whether to accept this and create an empty file
     965             :         ucbhelper::cancelCommandExecution
     966             :             ( uno::makeAny
     967             :               ( ucb::MissingInputStreamException
     968             :                 ( rtl::OUString(),
     969             :                   static_cast< cppu::OWeakObject * >( this ) ) ),
     970           0 :               xEnv );
     971             :     }
     972             : 
     973           0 :     GnomeVFSHandle *handle = NULL;
     974           0 :     ::rtl::OString aURI = getOURI();
     975             : 
     976           0 :     result = GNOME_VFS_OK;
     977           0 :     if ( bReplaceExisting ) {
     978           0 :         Authentication aAuth( xEnv );
     979           0 :         result = gnome_vfs_open( &handle, aURI.getStr(), GNOME_VFS_OPEN_WRITE );
     980             :     }
     981             : 
     982           0 :     if ( result != GNOME_VFS_OK ) {
     983             :         int perm;
     984           0 :         Authentication aAuth( xEnv );
     985             : 
     986             :         perm = ( ( GNOME_VFS_PERM_USER_WRITE | GNOME_VFS_PERM_USER_READ ) |
     987           0 :              ( GNOME_VFS_PERM_GROUP_WRITE | GNOME_VFS_PERM_GROUP_READ ) );
     988             : 
     989             :         result = gnome_vfs_create
     990           0 :             ( &handle, aURI.getStr(), GNOME_VFS_OPEN_WRITE, TRUE, perm );
     991             :     }
     992             : 
     993           0 :     if( result != GNOME_VFS_OK )
     994           0 :         cancelCommandExecution( result, xEnv, sal_True );
     995             : 
     996           0 :     if ( !xInputStream.is() ) {
     997           0 :         result = gnome_vfs_close( handle );
     998           0 :         if (result != GNOME_VFS_OK)
     999           0 :             cancelCommandExecution( result, xEnv, sal_True );
    1000             : 
    1001             :     } else { // copy it over
    1002             :         uno::Reference < io::XOutputStream > xOutput =
    1003           0 :             new gvfs::Stream( handle, &m_info );
    1004             : 
    1005           0 :         copyData( xInputStream, xOutput );
    1006             :     }
    1007             : 
    1008           0 :     if (m_bTransient) {
    1009           0 :         m_bTransient = sal_False;
    1010           0 :         aGuard.clear();
    1011           0 :         inserted();
    1012           0 :     }
    1013             : }
    1014             : 
    1015           0 : void Content::transfer(const ucb::TransferInfo & /*rArgs*/,
    1016             :                const uno::Reference< ucb::XCommandEnvironment >& xEnv )
    1017             :     throw( uno::Exception )
    1018             : {
    1019             :     // FIXME: see gnome-vfs-xfer.h - but we need to be able to easily
    1020             :     // detect which are gnome-vfs owned URI types ...
    1021             :     ucbhelper::cancelCommandExecution
    1022             :         ( uno::makeAny
    1023             :             ( ucb::InteractiveBadTransferURLException
    1024             :                 ( rtl::OUString("Unsupported URL scheme!"),
    1025             :                   static_cast< cppu::OWeakObject * >( this ) ) ),
    1026           0 :           xEnv );
    1027           0 : }
    1028             : 
    1029           0 : void Content::destroy( sal_Bool bDeletePhysical )
    1030             :     throw( uno::Exception )
    1031             : {
    1032             :     // @@@ take care about bDeletePhysical -> trashcan support
    1033           0 :     uno::Reference< ucb::XContent > xThis = this;
    1034             : 
    1035           0 :     deleted();
    1036             : 
    1037           0 :     osl::Guard< osl::Mutex > aGuard( m_aMutex );
    1038             : 
    1039             :     // Process instanciated children...
    1040           0 :     ::gvfs::Content::ContentRefList aChildren;
    1041           0 :     queryChildren( aChildren );
    1042             : 
    1043           0 :     ContentRefList::const_iterator it  = aChildren.begin();
    1044           0 :     ContentRefList::const_iterator end = aChildren.end();
    1045             : 
    1046           0 :     while ( it != end ) {
    1047           0 :         (*it)->destroy( bDeletePhysical );
    1048           0 :         ++it;
    1049           0 :     }
    1050           0 : }
    1051             : 
    1052             : // Used by the 'setPropertyValues' method for
    1053             : // propagating the renaming of a Content.
    1054           0 : sal_Bool Content::exchangeIdentity(
    1055             :     const uno::Reference< ucb::XContentIdentifier >& xNewId )
    1056             : {
    1057           0 :     if ( !xNewId.is() )
    1058           0 :         return sal_False;
    1059             : 
    1060           0 :     uno::Reference< ucb::XContent > xThis = this;
    1061             : 
    1062             : #if OSL_DEBUG_LEVEL > 1
    1063             :     g_warning( "exchangeIdentity from '%s' to '%s'",
    1064             :            getURI(), OUStringToGnome( xNewId->getContentIdentifier() ) );
    1065             : #endif
    1066             : 
    1067           0 :     if ( m_bTransient ) {
    1068           0 :         osl::Guard< osl::Mutex > aGuard( m_aMutex );
    1069             :         /* FIXME: can we not screw up an identically named
    1070             :          * Content pointing to ourself here ? */
    1071           0 :         m_xIdentifier = xNewId;
    1072           0 :         return sal_False;
    1073             :     }
    1074             : 
    1075           0 :     rtl::OUString aOldURL = getOUURI();
    1076             : 
    1077             :     // Exchange own identitity.
    1078           0 :     if ( exchange( xNewId ) ) {
    1079             : 
    1080             :         // Process instanciated children...
    1081           0 :         ContentRefList aChildren;
    1082           0 :         queryChildren( aChildren );
    1083             : 
    1084           0 :         ContentRefList::const_iterator it  = aChildren.begin();
    1085           0 :         ContentRefList::const_iterator end = aChildren.end();
    1086             : 
    1087           0 :         while ( it != end ) {
    1088           0 :             ContentRef xChild = (*it);
    1089             : 
    1090             :             // Create new content identifier for the child...
    1091             :             uno::Reference< ucb::XContentIdentifier >
    1092           0 :                 xOldChildId = xChild->getIdentifier();
    1093             :             rtl::OUString aOldChildURL
    1094           0 :                 = xOldChildId->getContentIdentifier();
    1095             :             rtl::OUString aNewChildURL
    1096             :                 = aOldChildURL.replaceAt(
    1097             :                              0,
    1098             :                              aOldURL.getLength(),
    1099           0 :                              xNewId->getContentIdentifier() );
    1100             :             uno::Reference< ucb::XContentIdentifier >
    1101             :                 xNewChildId
    1102           0 :                 = new ::ucbhelper::ContentIdentifier( aNewChildURL );
    1103             : 
    1104           0 :             if ( !xChild->exchangeIdentity( xNewChildId ) )
    1105           0 :                 return sal_False;
    1106             : 
    1107           0 :             ++it;
    1108           0 :         }
    1109           0 :         return sal_True;
    1110             :     }
    1111             : 
    1112           0 :     return sal_False;
    1113             : }
    1114             : 
    1115             : GnomeVFSResult
    1116           0 : Content::getInfo( const uno::Reference< ucb::XCommandEnvironment >& xEnv )
    1117             : {
    1118             :     GnomeVFSResult result;
    1119           0 :         osl::Guard< osl::Mutex > aGuard( m_aMutex );
    1120             : 
    1121           0 :     if (m_bTransient)
    1122           0 :         result = GNOME_VFS_OK;
    1123             : 
    1124           0 :     else if ( !m_info.valid_fields ) {
    1125           0 :         ::rtl::OString aURI = getOURI();
    1126           0 :         Authentication aAuth( xEnv );
    1127             :         result = gnome_vfs_get_file_info
    1128           0 :             ( aURI.getStr(), &m_info, GNOME_VFS_FILE_INFO_DEFAULT );
    1129           0 :         if (result != GNOME_VFS_OK)
    1130           0 :             gnome_vfs_file_info_clear( &m_info );
    1131             :     } else
    1132           0 :         result = GNOME_VFS_OK;
    1133             : #if OSL_DEBUG_LEVEL > 1
    1134             :     g_warning( "getInfo on '%s' returns '%s' (%d) (0x%x)",
    1135             :            getURI(), gnome_vfs_result_to_string( result ),
    1136             :            result, m_info.valid_fields );
    1137             : #endif
    1138           0 :     return result;
    1139             : }
    1140             : 
    1141             : sal_Bool
    1142           0 : Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv )
    1143             : {
    1144           0 :         osl::Guard< osl::Mutex > aGuard( m_aMutex );
    1145           0 :     getInfo( xEnv );
    1146             :     return (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE &&
    1147           0 :         m_info.type == GNOME_VFS_FILE_TYPE_DIRECTORY);
    1148             : }
    1149             : 
    1150           0 : uno::Any Content::mapVFSException( const GnomeVFSResult result, sal_Bool bWrite )
    1151             : {
    1152           0 :     uno::Any aException;
    1153             :     const char *gvfs_message;
    1154           0 :     rtl::OUString message;
    1155           0 :     uno::Sequence< uno::Any > aArgs( 1 );
    1156             : 
    1157             : #if OSL_DEBUG_LEVEL > 1
    1158             :     g_warning ("Map VFS exception '%s' (%d)",
    1159             :            gnome_vfs_result_to_string( result ), result );
    1160             : #endif
    1161             : 
    1162           0 :     if ((gvfs_message = gnome_vfs_result_to_string (result)))
    1163           0 :         message = GnomeToOUString( gvfs_message );
    1164             : 
    1165           0 :     switch (result) {
    1166             :     case GNOME_VFS_OK:
    1167           0 :         g_warning("VFS_OK mapped to exception.");
    1168           0 :         break;
    1169             :     case GNOME_VFS_ERROR_EOF:
    1170           0 :         g_warning ("VFS_EOF not handled somewhere.");
    1171           0 :         break;
    1172             :     case GNOME_VFS_ERROR_NOT_FOUND:
    1173           0 :         aArgs[ 0 ] <<= m_xIdentifier->getContentIdentifier();
    1174             :         aException <<=
    1175             :             ucb::InteractiveAugmentedIOException
    1176             :             ( rtl::OUString("Not found!"),
    1177             :               static_cast< cppu::OWeakObject * >( this ),
    1178             :               task::InteractionClassification_ERROR,
    1179             :               ucb::IOErrorCode_NOT_EXISTING,
    1180           0 :               aArgs );
    1181           0 :         break;
    1182             :     case GNOME_VFS_ERROR_BAD_PARAMETERS:
    1183             :         aException <<=
    1184             :             lang::IllegalArgumentException
    1185             :                 ( rtl::OUString(),
    1186             :                   static_cast< cppu::OWeakObject * >( this ),
    1187           0 :                   -1 );
    1188           0 :         break;
    1189             :     case GNOME_VFS_ERROR_GENERIC:
    1190             :     case GNOME_VFS_ERROR_INTERNAL:
    1191             :     case GNOME_VFS_ERROR_NOT_SUPPORTED:
    1192             : #ifdef DEBUG
    1193             :         g_warning ("Internal - un-mapped error");
    1194             : #endif
    1195           0 :         aException <<= io::IOException();
    1196           0 :         break;
    1197             :     case GNOME_VFS_ERROR_IO:
    1198           0 :         if ( bWrite )
    1199             :             aException <<=
    1200             :                 ucb::InteractiveNetworkWriteException
    1201             :                 ( rtl::OUString(),
    1202             :                   static_cast< cppu::OWeakObject * >( this ),
    1203             :                   task::InteractionClassification_ERROR,
    1204           0 :                   message );
    1205             :         else
    1206             :             aException <<=
    1207             :                 ucb::InteractiveNetworkReadException
    1208             :                 ( rtl::OUString(),
    1209             :                   static_cast< cppu::OWeakObject * >( this ),
    1210             :                   task::InteractionClassification_ERROR,
    1211           0 :                   message );
    1212           0 :         break;
    1213             :     case GNOME_VFS_ERROR_HOST_NOT_FOUND:
    1214             :     case GNOME_VFS_ERROR_INVALID_HOST_NAME:
    1215             :         aException <<=
    1216             :             ucb::InteractiveNetworkResolveNameException
    1217             :             ( rtl::OUString(),
    1218             :               static_cast< cppu::OWeakObject * >( this ),
    1219             :               task::InteractionClassification_ERROR,
    1220           0 :               message );
    1221           0 :         break;
    1222             :     case GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE:
    1223             :     case GNOME_VFS_ERROR_SERVICE_OBSOLETE:
    1224             :     case GNOME_VFS_ERROR_PROTOCOL_ERROR:
    1225             :     case GNOME_VFS_ERROR_NO_MASTER_BROWSER:
    1226             :         aException <<=
    1227             :             ucb::InteractiveNetworkConnectException
    1228             :                 ( rtl::OUString(),
    1229             :                   static_cast< cppu::OWeakObject * >( this ),
    1230             :                   task::InteractionClassification_ERROR,
    1231           0 :                   message );
    1232           0 :         break;
    1233             : 
    1234             :     case GNOME_VFS_ERROR_FILE_EXISTS:
    1235             :         aException <<= ucb::NameClashException
    1236             :                 ( rtl::OUString(),
    1237             :                   static_cast< cppu::OWeakObject * >( this ),
    1238             :                   task::InteractionClassification_ERROR,
    1239           0 :                   message );
    1240           0 :         break;
    1241             : 
    1242             :     case GNOME_VFS_ERROR_INVALID_OPEN_MODE:
    1243           0 :         aException <<= ucb::UnsupportedOpenModeException();
    1244           0 :         break;
    1245             : 
    1246             :     case GNOME_VFS_ERROR_CORRUPTED_DATA:
    1247             :     case GNOME_VFS_ERROR_WRONG_FORMAT:
    1248             :     case GNOME_VFS_ERROR_BAD_FILE:
    1249             :     case GNOME_VFS_ERROR_TOO_BIG:
    1250             :     case GNOME_VFS_ERROR_NO_SPACE:
    1251             :     case GNOME_VFS_ERROR_READ_ONLY:
    1252             :     case GNOME_VFS_ERROR_INVALID_URI:
    1253             :     case GNOME_VFS_ERROR_NOT_OPEN:
    1254             :     case GNOME_VFS_ERROR_ACCESS_DENIED:
    1255             :     case GNOME_VFS_ERROR_TOO_MANY_OPEN_FILES:
    1256             :     case GNOME_VFS_ERROR_NOT_A_DIRECTORY:
    1257             :     case GNOME_VFS_ERROR_IN_PROGRESS:
    1258             :     case GNOME_VFS_ERROR_INTERRUPTED:
    1259             :     case GNOME_VFS_ERROR_LOOP:
    1260             :     case GNOME_VFS_ERROR_NOT_PERMITTED:
    1261             :     case GNOME_VFS_ERROR_IS_DIRECTORY:
    1262             :     case GNOME_VFS_ERROR_NO_MEMORY:
    1263             :     case GNOME_VFS_ERROR_HOST_HAS_NO_ADDRESS:
    1264             :     case GNOME_VFS_ERROR_LOGIN_FAILED:
    1265             :     case GNOME_VFS_ERROR_CANCELLED:
    1266             :     case GNOME_VFS_ERROR_DIRECTORY_BUSY:
    1267             :     case GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY:
    1268             :     case GNOME_VFS_ERROR_TOO_MANY_LINKS:
    1269             :     case GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM:
    1270             :     case GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM:
    1271             :     case GNOME_VFS_ERROR_NAME_TOO_LONG:
    1272             : #ifdef DEBUG
    1273             :         g_warning( "FIXME: Un-mapped VFS exception '%s' (%d)",
    1274             :                gnome_vfs_result_to_string( result ), result );
    1275             : #endif
    1276             :     default:
    1277             :         aException <<= ucb::InteractiveNetworkGeneralException
    1278             :             ( rtl::OUString(),
    1279             :               static_cast< cppu::OWeakObject * >( this ),
    1280           0 :               task::InteractionClassification_ERROR );
    1281           0 :         break;
    1282             :     }
    1283             : 
    1284           0 :     return aException;
    1285             : }
    1286             : 
    1287           0 : void Content::cancelCommandExecution(
    1288             :     GnomeVFSResult result,
    1289             :     const uno::Reference< ucb::XCommandEnvironment > & xEnv,
    1290             :     sal_Bool bWrite /* = sal_False */ )
    1291             :     throw ( uno::Exception )
    1292             : {
    1293           0 :     ucbhelper::cancelCommandExecution( mapVFSException( result, bWrite ), xEnv );
    1294             :     // Unreachable
    1295           0 : }
    1296             : 
    1297           0 : uno::Sequence< beans::Property > Content::getProperties(
    1298             :     const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
    1299             : {
    1300             :     static const beans::Property aGenericProperties[] = {
    1301             :                 beans::Property( rtl::OUString(  "ContentType"  ),
    1302           0 :                  -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
    1303             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1304             :                 beans::Property( rtl::OUString(  "IsDocument"  ),
    1305           0 :                  -1, getCppuBooleanType(),
    1306             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1307             :                 beans::Property( rtl::OUString(  "IsFolder"  ),
    1308           0 :                  -1, getCppuBooleanType(),
    1309             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1310             :                 beans::Property( rtl::OUString(  "Title"  ),
    1311           0 :                  -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
    1312             :                  beans::PropertyAttribute::BOUND ),
    1313             :         // Optional ...
    1314             :         beans::Property( rtl::OUString(  "DateCreated"  ),
    1315           0 :                  -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
    1316             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1317             :                 beans::Property( rtl::OUString(  "DateModified"  ),
    1318           0 :                  -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
    1319             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1320             : // FIXME: Too expensive for now (?)
    1321             : //                beans::Property( rtl::OUString(  "MediaType"  ),
    1322             : //                 -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
    1323             : //                 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1324             :                 beans::Property( rtl::OUString(  "Size"  ),
    1325           0 :                  -1, getCppuType( static_cast< const sal_Int64 * >( 0 ) ),
    1326             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1327             :                 beans::Property( rtl::OUString(  "IsReadOnly"  ),
    1328           0 :                  -1, getCppuBooleanType(),
    1329             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1330             :                 beans::Property( rtl::OUString(  "IsVolume"  ),
    1331           0 :                  -1, getCppuBooleanType(),
    1332             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1333             :                 beans::Property( rtl::OUString(  "IsCompactDisk"  ),
    1334           0 :                  -1, getCppuBooleanType(),
    1335             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1336             :                 beans::Property( rtl::OUString(  "IsHidden"  ),
    1337           0 :                  -1, getCppuBooleanType(),
    1338             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
    1339             :                 beans::Property( rtl::OUString(  "CreatableContentsInfo"  ),
    1340           0 :                  -1, getCppuType( static_cast< const uno::Sequence< ucb::ContentInfo > * >( 0 ) ),
    1341             :                  beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY )
    1342           0 :     };
    1343             : 
    1344           0 :     const int nProps = sizeof (aGenericProperties) / sizeof (aGenericProperties[0]);
    1345             : 
    1346           0 :     return uno::Sequence< beans::Property > ( aGenericProperties, nProps );
    1347             : 
    1348             : }
    1349             : 
    1350           0 : uno::Sequence< ucb::CommandInfo > Content::getCommands(
    1351             :     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
    1352             : {
    1353             :     static ucb::CommandInfo aCommandInfoTable[] = {
    1354             :         // Required commands
    1355             :         ucb::CommandInfo
    1356             :         ( rtl::OUString(  "getCommandInfo"  ),
    1357           0 :           -1, getCppuVoidType() ),
    1358             :         ucb::CommandInfo
    1359             :         ( rtl::OUString(  "getPropertySetInfo"  ),
    1360           0 :           -1, getCppuVoidType() ),
    1361             :         ucb::CommandInfo
    1362             :         ( rtl::OUString(  "getPropertyValues"  ),
    1363           0 :           -1, getCppuType( static_cast<uno::Sequence< beans::Property > * >( 0 ) ) ),
    1364             :         ucb::CommandInfo
    1365             :         ( rtl::OUString(  "setPropertyValues"  ),
    1366           0 :           -1, getCppuType( static_cast<uno::Sequence< beans::PropertyValue > * >( 0 ) ) ),
    1367             : 
    1368             :         // Optional standard commands
    1369             :         ucb::CommandInfo
    1370             :         ( rtl::OUString(  "delete"  ),
    1371           0 :           -1, getCppuBooleanType() ),
    1372             :         ucb::CommandInfo
    1373             :         ( rtl::OUString(  "insert"  ),
    1374           0 :           -1, getCppuType( static_cast<ucb::InsertCommandArgument * >( 0 ) ) ),
    1375             :         ucb::CommandInfo
    1376             :         ( rtl::OUString(  "open"  ),
    1377           0 :           -1, getCppuType( static_cast<ucb::OpenCommandArgument2 * >( 0 ) ) ),
    1378             : 
    1379             :         // Folder Only, omitted if not a folder
    1380             :         ucb::CommandInfo
    1381             :         ( rtl::OUString(  "transfer"  ),
    1382           0 :           -1, getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) ),
    1383             :         ucb::CommandInfo
    1384             :         ( rtl::OUString(  "createNewContent"  ),
    1385           0 :           -1, getCppuType( static_cast<ucb::ContentInfo * >( 0 ) ) )
    1386           0 :     };
    1387             : 
    1388             :     const int nProps
    1389           0 :         = sizeof( aCommandInfoTable ) / sizeof( aCommandInfoTable[ 0 ] );
    1390             :     return uno::Sequence< ucb::CommandInfo >(
    1391           0 :         aCommandInfoTable, isFolder( xEnv ) ? nProps : nProps - 2 );
    1392             : }
    1393             : 
    1394             : rtl::OUString
    1395           0 : Content::getOUURI ()
    1396             : {
    1397           0 :     osl::Guard< osl::Mutex > aGuard( m_aMutex );
    1398           0 :     return m_xIdentifier->getContentIdentifier();
    1399             : }
    1400             : 
    1401             : rtl::OString
    1402           0 : Content::getOURI ()
    1403             : {
    1404           0 :     return rtl::OUStringToOString( getOUURI(), RTL_TEXTENCODING_UTF8 );
    1405             : }
    1406             : 
    1407             : char *
    1408           0 : Content::getURI ()
    1409             : {
    1410           0 :     return OUStringToGnome( getOUURI() );
    1411             : }
    1412             : 
    1413             : void
    1414           0 : Content::copyData( uno::Reference< io::XInputStream > xIn,
    1415             :                    uno::Reference< io::XOutputStream > xOut )
    1416             : {
    1417           0 :     uno::Sequence< sal_Int8 > theData( TRANSFER_BUFFER_SIZE );
    1418             : 
    1419           0 :     g_return_if_fail( xIn.is() && xOut.is() );
    1420             : 
    1421           0 :     while ( xIn->readBytes( theData, TRANSFER_BUFFER_SIZE ) > 0 )
    1422           0 :         xOut->writeBytes( theData );
    1423             : 
    1424           0 :     xOut->closeOutput();
    1425             : }
    1426             : 
    1427             : // Inherits an authentication context
    1428             : uno::Reference< io::XInputStream >
    1429           0 : Content::createTempStream(
    1430             :     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
    1431             :         throw( uno::Exception )
    1432             : {
    1433             :     GnomeVFSResult result;
    1434           0 :     GnomeVFSHandle *handle = NULL;
    1435           0 :     ::rtl::OString aURI = getOURI();
    1436             : 
    1437           0 :     osl::Guard< osl::Mutex > aGuard( m_aMutex );
    1438             :     // Something badly wrong happened - can't seek => stream to a temporary file
    1439             :     uno::Reference < io::XOutputStream > xTempOut =
    1440             :         uno::Reference < io::XOutputStream >
    1441           0 :             ( io::TempFile::create( m_xContext ), uno::UNO_QUERY );
    1442             : 
    1443           0 :     if ( !xTempOut.is() )
    1444           0 :         cancelCommandExecution( GNOME_VFS_ERROR_IO, xEnv );
    1445             : 
    1446             :     result = gnome_vfs_open
    1447           0 :         ( &handle, aURI.getStr(), GNOME_VFS_OPEN_READ );
    1448           0 :     if (result != GNOME_VFS_OK)
    1449           0 :         cancelCommandExecution( result, xEnv );
    1450             : 
    1451           0 :     uno::Reference < io::XInputStream > pStream = new ::gvfs::Stream( handle, &m_info );
    1452           0 :     copyData( pStream, xTempOut );
    1453             : 
    1454           0 :     return uno::Reference < io::XInputStream > ( xTempOut, uno::UNO_QUERY );
    1455             : }
    1456             : 
    1457             : uno::Reference< io::XInputStream >
    1458           0 : Content::createInputStream(
    1459             :     const uno::Reference< ucb::XCommandEnvironment >& xEnv )
    1460             :         throw( uno::Exception )
    1461             : {
    1462           0 :     GnomeVFSHandle *handle = NULL;
    1463             :     GnomeVFSResult  result;
    1464           0 :     uno::Reference<io::XInputStream > xIn;
    1465             : 
    1466           0 :     Authentication aAuth( xEnv );
    1467           0 :         osl::Guard< osl::Mutex > aGuard( m_aMutex );
    1468             : 
    1469           0 :     getInfo( xEnv );
    1470           0 :     ::rtl::OString aURI = getOURI();
    1471             : 
    1472           0 :     if ( !(m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) )
    1473           0 :         return createTempStream( xEnv );
    1474             : 
    1475             :     result = gnome_vfs_open
    1476             :         ( &handle, aURI.getStr(),
    1477           0 :           (GnomeVFSOpenMode) (GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_RANDOM ) );
    1478             : 
    1479           0 :     if (result == GNOME_VFS_ERROR_INVALID_OPEN_MODE ||
    1480             :         result == GNOME_VFS_ERROR_NOT_SUPPORTED)
    1481           0 :         return createTempStream( xEnv );
    1482             : 
    1483           0 :     if (result != GNOME_VFS_OK)
    1484           0 :         cancelCommandExecution( result, xEnv );
    1485             : 
    1486             :     // Try a seek just to make sure it's Random access: some lie.
    1487           0 :     result = gnome_vfs_seek( handle, GNOME_VFS_SEEK_START, 0);
    1488           0 :     if (result == GNOME_VFS_ERROR_NOT_SUPPORTED) {
    1489           0 :         gnome_vfs_close( handle );
    1490           0 :         return createTempStream( xEnv );
    1491             :     }
    1492             : 
    1493           0 :     if (result != GNOME_VFS_OK)
    1494           0 :         cancelCommandExecution( result, xEnv );
    1495             : 
    1496           0 :     if (handle != NULL)
    1497           0 :         xIn = new ::gvfs::Stream( handle, &m_info );
    1498             : 
    1499           0 :     return xIn;
    1500             : }
    1501             : 
    1502             : sal_Bool
    1503           0 : Content::feedSink( uno::Reference< uno::XInterface > aSink,
    1504             :                    const uno::Reference< ucb::XCommandEnvironment >& xEnv )
    1505             : {
    1506           0 :     if ( !aSink.is() )
    1507           0 :         return sal_False;
    1508             : 
    1509             :     uno::Reference< io::XOutputStream > xOut
    1510           0 :         = uno::Reference< io::XOutputStream >(aSink, uno::UNO_QUERY );
    1511             :     uno::Reference< io::XActiveDataSink > xDataSink
    1512           0 :         = uno::Reference< io::XActiveDataSink >(aSink, uno::UNO_QUERY );
    1513             : 
    1514           0 :     if ( !xOut.is() && !xDataSink.is() )
    1515           0 :         return sal_False;
    1516             : 
    1517           0 :     uno::Reference< io::XInputStream > xIn = createInputStream( xEnv );
    1518           0 :     if ( !xIn.is() )
    1519           0 :         return sal_False;
    1520             : 
    1521           0 :     if ( xOut.is() )
    1522           0 :         copyData( xIn, xOut );
    1523             : 
    1524           0 :     if ( xDataSink.is() )
    1525           0 :         xDataSink->setInputStream( xIn );
    1526             : 
    1527           0 :     return sal_True;
    1528             : }
    1529             : 
    1530             : extern "C" {
    1531             : 
    1532             : #ifndef GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION
    1533             : #  error "We require Gnome VFS 2.6.x to compile (will run fine with < 2.6)"
    1534             : #endif
    1535             : 
    1536             :     static void
    1537           0 :     vfs_authentication_callback (gconstpointer in_void,
    1538             :                      gsize         in_size,
    1539             :                      gpointer      out_void,
    1540             :                      gsize         out_size,
    1541             :                      gpointer      callback_data)
    1542             :     {
    1543             :         task::XInteractionHandler *xIH;
    1544             : 
    1545             : #if OSL_DEBUG_LEVEL > 1
    1546             :         g_warning ("Full authentication callback (%p) ...", callback_data);
    1547             : #endif
    1548             : 
    1549           0 :         if( !( xIH = (task::XInteractionHandler *) callback_data ) )
    1550             :             return;
    1551             : 
    1552             :         const GnomeVFSModuleCallbackFullAuthenticationIn *in =
    1553           0 :             (const GnomeVFSModuleCallbackFullAuthenticationIn *) in_void;
    1554             :         GnomeVFSModuleCallbackFullAuthenticationOut *out =
    1555           0 :             (GnomeVFSModuleCallbackFullAuthenticationOut *) out_void;
    1556             : 
    1557           0 :         g_return_if_fail (in != NULL && out != NULL);
    1558           0 :         g_return_if_fail (sizeof (GnomeVFSModuleCallbackFullAuthenticationIn) == in_size &&
    1559             :                   sizeof (GnomeVFSModuleCallbackFullAuthenticationOut) == out_size);
    1560             : 
    1561             : #if OSL_DEBUG_LEVEL > 1
    1562             : #  define NNIL(x) (x?x:"<Null>")
    1563             :         g_warning (" InComing data 0x%x uri '%s' prot '%s' server '%s' object '%s' "
    1564             :                    "port %d auth_t '%s' user '%s' domain '%s' "
    1565             :                    "def user '%s', def domain '%s'",
    1566             :                    (int) in->flags, NNIL(in->uri), NNIL(in->protocol),
    1567             :                    NNIL(in->server), NNIL(in->object),
    1568             :                    (int) in->port, NNIL(in->authtype), NNIL(in->username), NNIL(in->domain),
    1569             :                    NNIL(in->default_user), NNIL(in->default_domain));
    1570             : #  undef NNIL
    1571             : #endif
    1572             : 
    1573             :         ucbhelper::SimpleAuthenticationRequest::EntityType
    1574             :                                    eDomain, eUserName, ePassword;
    1575           0 :         ::rtl::OUString aHostName, aDomain, aUserName, aPassword;
    1576             : 
    1577           0 :         aHostName = GnomeToOUString( in->server );
    1578             : 
    1579           0 :         if (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_DOMAIN)
    1580             :         {
    1581           0 :             aDomain = GnomeToOUString( in->domain );
    1582           0 :             eDomain = ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY;
    1583           0 :             if (aDomain.isEmpty())
    1584           0 :                 aDomain = GnomeToOUString( in->default_domain );
    1585             :         }
    1586             :         else // no underlying capability to display realm otherwise
    1587           0 :             eDomain = ucbhelper::SimpleAuthenticationRequest::ENTITY_NA;
    1588             : 
    1589           0 :         aUserName = GnomeToOUString( in->username );
    1590           0 :         if (aUserName.isEmpty())
    1591           0 :             aUserName = GnomeToOUString( in->default_user );
    1592             :         eUserName = (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME) ?
    1593             :             ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY :
    1594           0 :                 (!aUserName.isEmpty() ?
    1595             :                     ucbhelper::SimpleAuthenticationRequest::ENTITY_FIXED :
    1596           0 :                     ucbhelper::SimpleAuthenticationRequest::ENTITY_NA);
    1597             : 
    1598             :         // No suggested password.
    1599             :         ePassword = (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_PASSWORD) ?
    1600             :             ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY :
    1601           0 :             ucbhelper::SimpleAuthenticationRequest::ENTITY_FIXED;
    1602             : 
    1603             :         // Really, really bad things happen if we don't provide
    1604             :         // the same user/password as was entered last time if
    1605             :         // we failed to authenticate - infinite looping / flickering
    1606             :         // madness etc. [ nice infrastructure ! ]
    1607           0 :         static rtl::OUString aLastUserName, aLastPassword;
    1608           0 :         if (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_PREVIOUS_ATTEMPT_FAILED)
    1609             :         {
    1610           0 :             osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
    1611           0 :             aUserName = aLastUserName;
    1612           0 :             aPassword = aLastPassword;
    1613             :         }
    1614             : 
    1615             :         rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest
    1616             :             = new ucbhelper::SimpleAuthenticationRequest (GnomeToOUString(in->uri),
    1617             :                                                           aHostName, eDomain, aDomain,
    1618             :                                                           eUserName, aUserName,
    1619           0 :                                                           ePassword, aPassword);
    1620             : 
    1621           0 :         xIH->handle( xRequest.get() );
    1622             : 
    1623             :         rtl::Reference< ucbhelper::InteractionContinuation > xSelection
    1624           0 :             = xRequest->getSelection();
    1625             : 
    1626           0 :         if ( xSelection.is() ) {
    1627             :             // Handler handled the request.
    1628           0 :             uno::Reference< task::XInteractionAbort > xAbort(xSelection.get(), uno::UNO_QUERY );
    1629           0 :             if ( !xAbort.is() ) {
    1630             :                 const rtl::Reference<
    1631             :                     ucbhelper::InteractionSupplyAuthentication > & xSupp
    1632           0 :                     = xRequest->getAuthenticationSupplier();
    1633             : 
    1634           0 :                 ::rtl::OUString aNewDomain, aNewUserName, aNewPassword;
    1635             : 
    1636           0 :                 aNewUserName = xSupp->getUserName();
    1637           0 :                 if ( !aNewUserName.isEmpty() )
    1638           0 :                     aUserName = aNewUserName;
    1639           0 :                 aNewDomain = xSupp->getRealm();
    1640           0 :                 if ( !aNewDomain.isEmpty() )
    1641           0 :                     aDomain = aNewDomain;
    1642           0 :                 aNewPassword = xSupp->getPassword();
    1643           0 :                 if ( !aNewPassword.isEmpty() )
    1644           0 :                     aPassword = aNewPassword;
    1645             : 
    1646             :                 {
    1647           0 :                     osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
    1648           0 :                     aLastUserName = aUserName;
    1649           0 :                     aLastPassword = aPassword;
    1650             :                 }
    1651             : 
    1652           0 :                 out->username = OUStringToGnome( aUserName );
    1653           0 :                 out->domain   = OUStringToGnome( aDomain );
    1654           0 :                 out->password = OUStringToGnome( aPassword );
    1655           0 :                 out->save_password = xSupp->getRememberPasswordMode();
    1656             : 
    1657             : #if OSL_DEBUG_LEVEL > 1
    1658             :                 g_warning ("Got valid user/domain/password '%s' '%s' '%s', %s password",
    1659             :                            out->username, out->domain, out->password,
    1660             :                            out->save_password ? "save" : "don't save");
    1661             : #endif
    1662             :             }
    1663             :             else
    1664           0 :                 out->abort_auth = TRUE;
    1665             :         }
    1666             :         else
    1667           0 :             out->abort_auth = TRUE;
    1668             :     }
    1669             : 
    1670             :     static void
    1671           0 :     vfs_authentication_old_callback (gconstpointer in_void,
    1672             :                                      gsize         in_size,
    1673             :                                      gpointer      out_void,
    1674             :                                      gsize         out_size,
    1675             :                                      gpointer      callback_data)
    1676             :     {
    1677             : #ifdef DEBUG
    1678             :         g_warning ("Old authentication callback (%p) [ UNTESTED ] ...", callback_data);
    1679             : #endif
    1680             :         const GnomeVFSModuleCallbackAuthenticationIn *in =
    1681           0 :             (const GnomeVFSModuleCallbackAuthenticationIn *) in_void;
    1682             :         GnomeVFSModuleCallbackAuthenticationOut *out =
    1683           0 :             (GnomeVFSModuleCallbackAuthenticationOut *) out_void;
    1684             : 
    1685           0 :         g_return_if_fail (in != NULL && out != NULL);
    1686           0 :         g_return_if_fail (sizeof (GnomeVFSModuleCallbackAuthenticationIn) == in_size &&
    1687             :                   sizeof (GnomeVFSModuleCallbackAuthenticationOut) == out_size);
    1688             : 
    1689             :         GnomeVFSModuleCallbackFullAuthenticationIn mapped_in = {
    1690             :                 (GnomeVFSModuleCallbackFullAuthenticationFlags)
    1691             :                 (GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_PASSWORD |
    1692             :                  GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME |
    1693             :                  GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_DOMAIN),
    1694           0 :                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
    1695           0 :         GnomeVFSModuleCallbackFullAuthenticationOut mapped_out = { 0, 0, 0, 0, 0, 0, 0, 0 };
    1696             : 
    1697             :         // Map the old style input auth. data to the new style structure.
    1698           0 :         if (in->previous_attempt_failed)
    1699             :             mapped_in.flags = (GnomeVFSModuleCallbackFullAuthenticationFlags)
    1700             :                 (mapped_in.flags |
    1701           0 :                  GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_PREVIOUS_ATTEMPT_FAILED);
    1702             : 
    1703           0 :         GnomeVFSURI *pURI = NULL;
    1704             :         // Urk - parse all this from the URL ...
    1705           0 :         mapped_in.uri = in->uri;
    1706           0 :         if (in->uri)
    1707             :         {
    1708           0 :             pURI = gnome_vfs_uri_new( in->uri );
    1709           0 :             mapped_in.protocol = (char *) gnome_vfs_uri_get_scheme (pURI);
    1710           0 :             mapped_in.server   = (char *) gnome_vfs_uri_get_host_name (pURI);
    1711           0 :             mapped_in.port     = gnome_vfs_uri_get_host_port (pURI);
    1712           0 :             mapped_in.username = (char *) gnome_vfs_uri_get_user_name (pURI);
    1713             :         }
    1714           0 :         mapped_in.domain = in->realm;
    1715           0 :         mapped_in.default_user = mapped_in.username;
    1716           0 :         mapped_in.default_domain = mapped_in.domain;
    1717             : 
    1718             :         vfs_authentication_callback ((gconstpointer) &mapped_in,
    1719             :                                      sizeof (mapped_in),
    1720             :                                      (gpointer) &mapped_out,
    1721             :                                      sizeof (mapped_out),
    1722           0 :                                      callback_data);
    1723             : 
    1724           0 :         if (pURI)
    1725           0 :             gnome_vfs_uri_unref (pURI);
    1726             : 
    1727             :         // Map the new style auth. out data to the old style out structure.
    1728           0 :         out->username = mapped_out.username;
    1729           0 :         out->password = mapped_out.password;
    1730           0 :         g_free (mapped_out.domain);
    1731           0 :         g_free (mapped_out.keyring);
    1732             :     }
    1733             : 
    1734             : 
    1735             :     static void
    1736           0 :     auth_destroy (gpointer data)
    1737             :     {
    1738             :         task::XInteractionHandler *xIH;
    1739           0 :         if( ( xIH = ( task::XInteractionHandler * )data ) )
    1740           0 :             xIH->release();
    1741           0 :     }
    1742             : 
    1743             :     // This sucks, but gnome-vfs doesn't much like
    1744             :     // repeated set / unsets - so we have to compensate.
    1745             :     GPrivate *auth_queue = NULL;
    1746             : 
    1747           0 :     void auth_queue_destroy( gpointer data )
    1748             :     {
    1749             :         GList  *l;
    1750           0 :         GQueue *vq = (GQueue *) data;
    1751             : 
    1752           0 :         for (l = vq->head; l; l = l->next)
    1753           0 :             auth_destroy (l->data);
    1754           0 :         g_queue_free (vq);
    1755           0 :     }
    1756             : }
    1757             : 
    1758             : static void
    1759           0 : refresh_auth( GQueue *vq )
    1760             : {
    1761             :     GList *l;
    1762             : 
    1763           0 :     gnome_vfs_module_callback_pop( GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION );
    1764           0 :     gnome_vfs_module_callback_pop( GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION );
    1765             : 
    1766           0 :     for (l = vq->head; l; l = l->next) {
    1767           0 :         if (l->data) {
    1768             :             gnome_vfs_module_callback_push
    1769             :                 ( GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION,
    1770           0 :                   vfs_authentication_old_callback, l->data, NULL );
    1771             :             gnome_vfs_module_callback_push
    1772             :                 ( GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION,
    1773           0 :                   vfs_authentication_callback, l->data, NULL );
    1774           0 :             break;
    1775             :         }
    1776             :     }
    1777           0 : }
    1778             : 
    1779           0 : gvfs::Authentication::Authentication(
    1780             :     const uno::Reference< ucb::XCommandEnvironment > & xEnv )
    1781             : {
    1782             :     GQueue *vq;
    1783           0 :     uno::Reference< task::XInteractionHandler > xIH;
    1784             : 
    1785           0 :     if ( xEnv.is() )
    1786           0 :         xIH = xEnv->getInteractionHandler();
    1787             : 
    1788           0 :     if ( xIH.is() )
    1789           0 :         xIH->acquire();
    1790             : 
    1791           0 :     if( !(vq = (GQueue *)g_private_get( auth_queue ) ) ) {
    1792           0 :         vq = g_queue_new();
    1793           0 :         g_private_set( auth_queue, vq );
    1794             :     }
    1795             : 
    1796           0 :     g_queue_push_head( vq, (gpointer) xIH.get() );
    1797           0 :     refresh_auth( vq );
    1798           0 : }
    1799             : 
    1800           0 : gvfs::Authentication::~Authentication()
    1801             : {
    1802             :     GQueue *vq;
    1803             :     gpointer data;
    1804             : 
    1805           0 :     vq = (GQueue *)g_private_get( auth_queue );
    1806             : 
    1807           0 :     data = g_queue_pop_head( vq );
    1808           0 :     auth_destroy (data);
    1809             : 
    1810           0 :     refresh_auth( vq );
    1811           0 : }
    1812             : 
    1813             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10