--- ucb/source/ucp/gvfs/content.cxx	2007-04-03 15:32:17.000000000 +0200
+++ ucb/source/ucp/gvfs/content.cxx	2007-04-03 15:33:24.000000000 +0200
@@ -63,6 +63,9 @@
 #ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
 #include <com/sun/star/io/XOutputStream.hpp>
 #endif
+#ifndef _COM_SUN_STAR_IO_XACTIVEDATASTREAMER_HPP_
+#include <com/sun/star/io/XActiveDataStreamer.hpp>
+#endif
 #ifndef _COM_SUN_STAR_LANG_ILLEGALACCESSEXCEPTION_HPP_
 #include <com/sun/star/lang/IllegalAccessException.hpp>
 #endif
@@ -93,6 +96,9 @@
 #ifndef _COM_SUN_STAR_UCB_INTERACTIVENETWORKWRITEEXCEPTION_HPP_
 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
 #endif
+#ifndef _COM_SUN_STAR_UCB_IOERRORCODE_HPP_
+#include <com/sun/star/ucb/IOErrorCode.hpp>
+#endif
 #ifndef _COM_SUN_STAR_UCB_NAMECLASH_HPP_
 #include <com/sun/star/ucb/NameClash.hpp>
 #endif
@@ -206,7 +212,8 @@ Content::Content(
   throw ( ucb::ContentCreationException )
 	: ContentImplHelper( rxSMgr, pProvider, Identifier ),
 	  m_pProvider( pProvider ),
-	  m_bTransient( sal_False )
+	  m_bTransient( sal_False ),
+	  m_bForceReadOnly( sal_False )
 {
 	CLEAR_INFO (&m_info);
 #ifdef DEBUG
@@ -222,7 +229,8 @@ Content::Content( const ::com::sun::star
 	throw ( ucb::ContentCreationException )
 	: ContentImplHelper( rxSMgr, pProvider, Identifier ),
 	  m_pProvider( pProvider ),
-	  m_bTransient( sal_True )
+	  m_bTransient( sal_True ),
+	  m_bForceReadOnly( sal_False )
 {
 	CLEAR_INFO (&m_info);
 
@@ -648,8 +659,7 @@ uno::Reference< sdbc::XRow > Content::ge
 	GnomeVFSResult result;
 	uno::Sequence< beans::Property > allProperties;
 
-	if( ( result = getInfo( xEnv ) ) != GNOME_VFS_OK )
-		cancelCommandExecution( result, xEnv, sal_False );
+	result = getInfo( xEnv );
 		
 	const beans::Property* pProps;
 
@@ -665,11 +672,19 @@ uno::Reference< sdbc::XRow > Content::ge
 	rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
 		= new ::ucbhelper::PropertyValueSet( m_xSMgr );
 
-    	osl::Guard< osl::Mutex > aGuard( m_aMutex );
+	osl::Guard< osl::Mutex > aGuard( m_aMutex );
 	for( sal_Int32 n = 0; n < nProps; ++n ) {
 		const beans::Property& rProp = pProps[ n ];
 
-		if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) {
+		if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SupportsActiveStreaming" ) ) ) {
+			xRow->appendBoolean( rProp, sal_True );
+		}
+		else if (result != GNOME_VFS_OK) {
+			// 'SupportsActiveStreaming' is the only property that can be
+			// obtained even if getInfo() failed
+			cancelCommandExecution( result, xEnv, sal_False );
+		}
+		else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) {
 			if (m_info.name && m_info.name[0] == '/')
 				g_warning ("Odd NFS title on item '%s' == '%s'",
 					   getURI(), m_info.name);
@@ -702,7 +717,9 @@ uno::Reference< sdbc::XRow > Content::ge
 		}
 
 		else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) {
-			if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS) {
+			if ( m_bForceReadOnly )
+				xRow->appendBoolean( rProp, sal_True );
+			else if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS) {
 				bool read_only = true;
 
 				if (m_info.uid == getuid () &&
@@ -990,6 +1007,8 @@ void Content::insert(
 {
   	osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
 
+	GnomeVFSOpenMode nOpenMode;
+
 #ifdef DEBUG
 	g_warning( "Insert '%s' (%d) (0x%x:%d)", getURI(), bReplaceExisting,
 		   m_info.valid_fields, m_info.type );
@@ -1042,22 +1061,27 @@ void Content::insert(
 	result = GNOME_VFS_OK;
 	if ( bReplaceExisting ) {
 		Authentication aAuth( xEnv );
-		result = gnome_vfs_open( &handle, (const sal_Char *)aURI,
-					 GNOME_VFS_OPEN_WRITE );
+		nOpenMode = (GnomeVFSOpenMode)(GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_LOCKED);
+		result = gnome_vfs_open( &handle, (const sal_Char *)aURI, nOpenMode );
 	}
 
-	if ( result != GNOME_VFS_OK ) {
+	if ( result == GNOME_VFS_ERROR_LOCKED )
+		throwLocked( xEnv );
+	else if ( result != GNOME_VFS_OK ) {
 		int perm;
 		Authentication aAuth( xEnv );
 
 		perm = ( ( GNOME_VFS_PERM_USER_WRITE | GNOME_VFS_PERM_USER_READ ) |
 			 ( GNOME_VFS_PERM_GROUP_WRITE | GNOME_VFS_PERM_GROUP_READ ) );
 
+		nOpenMode = (GnomeVFSOpenMode)(GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_LOCKED);
 		result = gnome_vfs_create
-			( &handle, (const sal_Char *)aURI, GNOME_VFS_OPEN_WRITE, TRUE, perm );
+			( &handle, (const sal_Char *)aURI, nOpenMode, TRUE, perm );
 	}
 
-	if( result != GNOME_VFS_OK )
+	if ( result == GNOME_VFS_ERROR_LOCKED )
+		throwLocked( xEnv );
+	else if ( result != GNOME_VFS_OK )
 		cancelCommandExecution( result, xEnv, sal_True );
 
 	if ( !xInputStream.is() ) {
@@ -1067,7 +1091,7 @@ void Content::insert(
 
 	} else { // copy it over
 		uno::Reference < io::XOutputStream > xOutput =
-			new gvfs::Stream( handle, &m_info );
+			new gvfs::Stream( handle, &m_info, (const sal_Char *)aURI, nOpenMode );
 
 		copyData( xInputStream, xOutput );
 	}
@@ -1363,6 +1387,22 @@ void Content::cancelCommandExecution(
     // Unreachable
 }
 
+void Content::throwLocked( const uno::Reference< ucb::XCommandEnvironment > & xEnv)
+	throw( uno::Exception )
+{
+#ifdef DEBUG
+	g_warning( "File locked, throwing IOErrorCode_LOCKING_VIOLATION" );
+#endif
+
+	m_bForceReadOnly = sal_True;
+
+	ucbhelper::cancelCommandExecution( ucb::IOErrorCode_LOCKING_VIOLATION,
+			uno::Sequence< uno::Any >( 0 ), // FIXME more info about the file?
+			xEnv,
+			rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "an error occured during file opening" ) ),
+			this );
+}
+
 uno::Sequence< beans::Property > Content::getProperties(
     const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
 {
@@ -1404,6 +1444,10 @@ uno::Sequence< beans::Property > Content
 				 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
                 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ),
 				 -1, getCppuBooleanType(),
+				 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
+
+                beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SupportsActiveStreaming" ) ),
+				 -1, getCppuBooleanType(),
 				 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY )
 	};
 
@@ -1497,6 +1541,7 @@ Content::createTempStream( const ::com::
 	GnomeVFSResult result;
 	GnomeVFSHandle *handle = NULL;
 	::rtl::OString aURI = getOURI();
+	GnomeVFSOpenMode nOpenMode = GNOME_VFS_OPEN_READ;
 
     	osl::Guard< osl::Mutex > aGuard( m_aMutex );
 	// Something badly wrong happened - can't seek => stream to a temporary file
@@ -1507,60 +1552,74 @@ Content::createTempStream( const ::com::
 	if ( !xTempOut.is() )
 		cancelCommandExecution( GNOME_VFS_ERROR_IO, xEnv );
 
-	result = gnome_vfs_open
-		( &handle, (const sal_Char *)aURI, GNOME_VFS_OPEN_READ );
+	result = gnome_vfs_open( &handle, (const sal_Char *)aURI, nOpenMode );
 	if (result != GNOME_VFS_OK)
 		cancelCommandExecution( result, xEnv );
 
-	uno::Reference < io::XInputStream > pStream = new ::gvfs::Stream( handle, &m_info );
+	uno::Reference < io::XInputStream > pStream = new ::gvfs::Stream( handle, &m_info, (const sal_Char *)aURI, nOpenMode );
 	copyData( pStream, xTempOut );
 
 	return uno::Reference < io::XInputStream > ( xTempOut, uno::UNO_QUERY );
 }
 
-uno::Reference< io::XInputStream > 
-Content::createInputStream(
-    const uno::Reference< ucb::XCommandEnvironment >& xEnv )
+uno::Reference< io::XStream > 
+Content::createStream( const uno::Reference< ucb::XCommandEnvironment >& xEnv,
+                       bool bReadWrite )
 	throw( uno::Exception )
 {
 	GnomeVFSHandle *handle = NULL;
 	GnomeVFSResult  result;
-	uno::Reference<io::XInputStream > xIn;
+	uno::Reference< io::XStream > xStream;
 
 	Authentication aAuth( xEnv );
-    	osl::Guard< osl::Mutex > aGuard( m_aMutex );
+	osl::Guard< osl::Mutex > aGuard( m_aMutex );
 
 	getInfo( xEnv );
 	::rtl::OString aURI = getOURI();
 
-	if ( !(m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) )
-		return createTempStream( xEnv );
+	if ( !bReadWrite && !(m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) )
+		return xStream;
 
-	result = gnome_vfs_open
-		( &handle, (const sal_Char *)aURI,
-		  (GnomeVFSOpenMode) (GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_RANDOM ) );
+	GnomeVFSOpenMode nOpenMode = (GnomeVFSOpenMode)(GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_RANDOM);
+	if ( bReadWrite )
+		nOpenMode = (GnomeVFSOpenMode)(nOpenMode | GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_LOCKED);
+
+	result = gnome_vfs_open( &handle, (const sal_Char *)aURI, nOpenMode );
 	
+	if (bReadWrite && (result == GNOME_VFS_ERROR_NOT_FOUND))
+	{
+		int perm;
+		Authentication aAuth( xEnv );
+
+		perm = ( ( GNOME_VFS_PERM_USER_WRITE | GNOME_VFS_PERM_USER_READ ) |
+			 ( GNOME_VFS_PERM_GROUP_WRITE | GNOME_VFS_PERM_GROUP_READ ) );
+
+		result = gnome_vfs_create
+			( &handle, (const sal_Char *)aURI, nOpenMode, TRUE, perm );
+	}
+
 	if (result == GNOME_VFS_ERROR_INVALID_OPEN_MODE ||
 	    result == GNOME_VFS_ERROR_NOT_SUPPORTED)
-		return createTempStream( xEnv );
-	
-	if (result != GNOME_VFS_OK)
+		return xStream;
+	else if (result == GNOME_VFS_ERROR_LOCKED )
+		throwLocked( xEnv );
+	else if (result != GNOME_VFS_OK)
 		cancelCommandExecution( result, xEnv );
 
 	// Try a seek just to make sure it's Random access: some lie.
 	result = gnome_vfs_seek( handle, GNOME_VFS_SEEK_START, 0);
 	if (result == GNOME_VFS_ERROR_NOT_SUPPORTED) {
 		gnome_vfs_close( handle );
-		return createTempStream( xEnv );
+		return xStream;
 	}
 
 	if (result != GNOME_VFS_OK)
 		cancelCommandExecution( result, xEnv );
 
 	if (handle != NULL)
-		xIn = new ::gvfs::Stream( handle, &m_info );
+		xStream = new ::gvfs::Stream( handle, &m_info, (const sal_Char *)aURI, nOpenMode );
 
-	return xIn;
+	return xStream;
 }
 
 sal_Bool
@@ -1570,25 +1630,53 @@ Content::feedSink( uno::Reference< ::com
 	if ( !aSink.is() )
 		return sal_False;
 
-	uno::Reference< io::XOutputStream > xOut
-		= uno::Reference< io::XOutputStream >(aSink, uno::UNO_QUERY );
-	uno::Reference< io::XActiveDataSink > xDataSink
-		= uno::Reference< io::XActiveDataSink >(aSink, uno::UNO_QUERY );
-	
-	if ( !xOut.is() && !xDataSink.is() )
-		return sal_False;
-
-	uno::Reference< io::XInputStream > xIn = createInputStream( xEnv );
-	if ( !xIn.is() )
-		return sal_False;
-	
+	uno::Reference< io::XOutputStream > xOut( aSink, uno::UNO_QUERY );
 	if ( xOut.is() )
+	{
+#ifdef DEBUG
+		g_warning( "feedSink(), using XOutputStream" );
+#endif
+		uno::Reference< io::XInputStream > xIn( createStream( xEnv, false ), uno::UNO_QUERY );
+		if ( !xIn.is() )
+			xIn = createTempStream( xEnv );
+		if ( !xIn.is() )
+			return sal_False;
+
 		copyData( xIn, xOut );
+		return sal_True;
+	}
 
+	uno::Reference< io::XActiveDataSink > xDataSink( aSink, uno::UNO_QUERY );
 	if ( xDataSink.is() )
+	{
+#ifdef DEBUG
+		g_warning( "feedSink(), using XActiveDataSink" );
+#endif
+		uno::Reference< io::XInputStream > xIn( createStream( xEnv, false ), uno::UNO_QUERY );
+		if ( !xIn.is() )
+			xIn = createTempStream( xEnv );
+		if ( !xIn.is() )
+			return sal_False;
+
 		xDataSink->setInputStream( xIn );
+		return sal_True;
+	}
+
+	uno::Reference< io::XActiveDataStreamer > xDataStreamer( aSink, uno::UNO_QUERY );
+	if ( xDataStreamer.is() )
+	{
+#ifdef DEBUG
+		g_warning( "feedSink(), using XActiveDataStreamer" );
+#endif
+		uno::Reference< io::XStream > xStream = createStream( xEnv, true );
+		if ( !xStream.is() )
+			return sal_False;
 
-	return sal_True;
+		xDataStreamer->setStream( xStream );
+		return sal_True;
+	}
+	
+	return sal_False;
 }
 
 extern "C" {
--- ucb/source/ucp/gvfs/content.hxx	2007-04-03 15:32:17.000000000 +0200
+++ ucb/source/ucp/gvfs/content.hxx	2007-04-03 15:32:40.000000000 +0200
@@ -65,6 +65,7 @@ namespace com { namespace sun { namespac
 namespace com { namespace sun { namespace star { namespace io {
 	class XInputStream;
 	class XOutputStream;
+	class XStream;
 } } } }
 
 namespace com { namespace sun { namespace star { namespace sdbc {
@@ -108,6 +109,7 @@ private:
 	ContentProvider  *m_pProvider;  // No need for a ref, base class holds object
 	sal_Bool          m_bTransient; // A non-existant (as yet) item
 	GnomeVFSFileInfo  m_info;       // cached status information
+	sal_Bool          m_bForceReadOnly; // behave as read-only
 
 	// Internal helpers
 	void                       queryChildren   ( ContentRefList& rChildren );
@@ -182,9 +184,10 @@ private:
 					com::sun::star::ucb::XCommandEnvironment >& xEnv )
 		throw( ::com::sun::star::uno::Exception );
 	::com::sun::star::uno::Reference<
-		::com::sun::star::io::XInputStream > 
-		createInputStream(  const ::com::sun::star::uno::Reference<
-					com::sun::star::ucb::XCommandEnvironment >& xEnv )
+		::com::sun::star::io::XStream > 
+		createStream(  const ::com::sun::star::uno::Reference<
+					com::sun::star::ucb::XCommandEnvironment >& xEnv,
+					bool bReadWrite )
 		throw( ::com::sun::star::uno::Exception );
        	sal_Bool feedSink( ::com::sun::star::uno::Reference<
 				::com::sun::star::uno::XInterface> aSink,
@@ -200,6 +203,9 @@ private:
 				    sal_Bool bWrite = sal_False )
 		throw( ::com::sun::star::uno::Exception );
 
+	void throwLocked(const ::com::sun::star::uno::Reference< com::sun::star::ucb::XCommandEnvironment > & xEnv)
+		throw( ::com::sun::star::uno::Exception );
+
 
 public:
 	// Non-interface bits
--- ucb/source/ucp/gvfs/makefile.mk	2007-04-03 15:32:17.000000000 +0200
+++ ucb/source/ucp/gvfs/makefile.mk	2007-04-03 15:32:40.000000000 +0200
@@ -61,6 +61,14 @@ CFLAGS+=-gdwarf-2
 PKGCONFIG_LIBS!:=-Wl,--export-dynamic $(PKGCONFIG_LIBS:s/ -llinc//:s/ -lbonobo-activation//:s/ -lgconf-2//:s/ -lORBit-2//:s/ -lIDL-2//:s/ -lgmodule-2.0//:s/ -lgobject-2.0//:s/ -lgthread-2.0//)
 .ENDIF          # "$(OS)" == "LINUX"
 
+.IF "$(debug)" != "" || "$(DEBUG)" != ""
+CFLAGS+=-DDEBUG
+.ENDIF
+
+.IF "$(GNOMEVFS_HAS_LOCKING)" != "YES"
+CFLAGS+=-DGNOME_VFS_OPEN_LOCKED=16
+.ENDIF
+
 # no "lib" prefix
 DLLPRE =
 
--- ucb/source/ucp/gvfs/stream.cxx	2007-04-03 15:32:17.000000000 +0200
+++ ucb/source/ucp/gvfs/stream.cxx	2007-04-03 15:32:40.000000000 +0200
@@ -54,10 +54,14 @@ using namespace com::sun::star::ucb;
 using namespace gvfs;
 
 Stream::Stream( GnomeVFSHandle         *handle,
-		const GnomeVFSFileInfo *aInfo ) :
+		const GnomeVFSFileInfo *aInfo,
+		const gchar *uri,
+		GnomeVFSOpenMode open_mode ) :
 	m_eof (sal_False),
 	m_bInputStreamCalled( sal_False ),
-	m_bOutputStreamCalled( sal_False )
+	m_bOutputStreamCalled( sal_False ),
+	m_pURI( g_strdup( uri ) ),
+	m_nOpenMode( open_mode )
 {
 	m_handle = handle;
 	gnome_vfs_file_info_copy (&m_info, aInfo);
@@ -69,6 +73,7 @@ Stream::~Stream( void )
 		gnome_vfs_close (m_handle);
 		m_handle = NULL;
 	}
+	g_free( m_pURI );
 }
 
 Any Stream::queryInterface( const Type &type )
@@ -271,7 +276,17 @@ void SAL_CALL Stream::truncate( void )
 	if( ! m_handle )
 		throw IOException();
 
-	throwOnError( gnome_vfs_truncate_handle( m_handle, 0 ) );
+	GnomeVFSResult result = gnome_vfs_truncate_handle( m_handle, 0 );
+
+	if ( result == GNOME_VFS_ERROR_NOT_SUPPORTED )
+	{
+		result = gnome_vfs_close( m_handle );
+		m_handle = NULL;
+		if ( result == GNOME_VFS_OK )
+			result = gnome_vfs_open( &m_handle, m_pURI, (GnomeVFSOpenMode)( m_nOpenMode | GNOME_VFS_OPEN_LOCKED ) );
+	}
+
+	throwOnError( result );
 }
 
 // -------------------------------------------------------------------
--- ucb/source/ucp/gvfs/stream.hxx	2007-04-03 15:32:17.000000000 +0200
+++ ucb/source/ucp/gvfs/stream.hxx	2007-04-03 15:32:40.000000000 +0200
@@ -80,6 +80,8 @@ private:
 	sal_Bool         m_eof;
 	sal_Bool         m_bInputStreamCalled;
 	sal_Bool         m_bOutputStreamCalled;
+	gchar           *m_pURI;     // necessary to be able to simulate gnome_vfs_truncate if not supported
+	GnomeVFSOpenMode m_nOpenMode;// necessary to be able to simulate gnome_vfs_truncate if not supported
 
 	void throwOnError( GnomeVFSResult result )
 		throw( ::com::sun::star::io::NotConnectedException,
@@ -94,7 +96,9 @@ private:
 
 public:
 	Stream ( GnomeVFSHandle         *handle,
-		 const GnomeVFSFileInfo *aInfo );
+		 const GnomeVFSFileInfo *aInfo,
+		 const gchar *uri,
+		 GnomeVFSOpenMode open_mode );
 	virtual ~Stream();
 	
 	// XInterface
