Update ooo320-m1
[ooovba.git] / ucb / source / ucp / gvfs / content.cxx
blobeeb4387ea0f8c5118ff8c8e0bf8546e278b3e387
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: content.cxx,v $
10 * $Revision: 1.12 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_ucb.hxx"
33 #include <string.h>
34 #include <unistd.h>
35 #include <sys/types.h>
37 #include "osl/time.h"
38 #include <osl/diagnose.h>
40 #include "osl/doublecheckedlocking.h"
42 #include <com/sun/star/beans/PropertyValue.hpp>
43 #include <com/sun/star/beans/PropertyAttribute.hpp>
44 #include <com/sun/star/beans/PropertySetInfoChange.hpp>
45 #include <com/sun/star/beans/PropertySetInfoChangeEvent.hpp>
46 #include <com/sun/star/io/XActiveDataSink.hpp>
47 #include <com/sun/star/io/XOutputStream.hpp>
48 #include <com/sun/star/io/XActiveDataStreamer.hpp>
49 #include <com/sun/star/lang/IllegalAccessException.hpp>
50 #include <com/sun/star/ucb/ContentInfoAttribute.hpp>
51 #include <com/sun/star/ucb/InsertCommandArgument.hpp>
52 #include <com/sun/star/ucb/InteractiveBadTransferURLException.hpp>
53 #include <com/sun/star/ucb/InteractiveAugmentedIOException.hpp>
54 #include <com/sun/star/ucb/InteractiveNetworkConnectException.hpp>
55 #include <com/sun/star/ucb/InteractiveNetworkGeneralException.hpp>
56 #include <com/sun/star/ucb/InteractiveNetworkReadException.hpp>
57 #include <com/sun/star/ucb/InteractiveNetworkResolveNameException.hpp>
58 #include <com/sun/star/ucb/InteractiveNetworkWriteException.hpp>
59 #include <com/sun/star/ucb/IOErrorCode.hpp>
60 #include <com/sun/star/ucb/NameClash.hpp>
61 #include <com/sun/star/ucb/NameClashException.hpp>
62 #include <com/sun/star/ucb/OpenCommandArgument2.hpp>
63 #include <com/sun/star/ucb/OpenMode.hpp>
64 #include <com/sun/star/ucb/PostCommandArgument2.hpp>
65 #include <com/sun/star/ucb/TransferInfo.hpp>
66 #include <com/sun/star/ucb/XCommandInfo.hpp>
67 #include <com/sun/star/ucb/XPersistentPropertySet.hpp>
68 #include <com/sun/star/ucb/MissingInputStreamException.hpp>
69 #include <com/sun/star/ucb/MissingPropertiesException.hpp>
70 #include <com/sun/star/ucb/UnsupportedCommandException.hpp>
71 #include <com/sun/star/ucb/UnsupportedDataSinkException.hpp>
72 #include <com/sun/star/ucb/UnsupportedNameClashException.hpp>
73 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
74 #include <com/sun/star/ucb/UnsupportedOpenModeException.hpp>
75 #include <com/sun/star/ucb/NameClashException.hpp>
76 #include <ucbhelper/contentidentifier.hxx>
77 #include <ucbhelper/propertyvalueset.hxx>
78 #include <ucbhelper/interactionrequest.hxx>
79 #include <ucbhelper/cancelcommandexecution.hxx>
80 #include <ucbhelper/simpleauthenticationrequest.hxx>
82 const int TRANSFER_BUFFER_SIZE = 65536;
85 * NB. Name escaping is done only for URIs
86 * the 'Title' property is unescaped on set/get
88 #include <libgnomevfs/gnome-vfs-utils.h>
89 #include <libgnomevfs/gnome-vfs-result.h>
90 #include <libgnomevfs/gnome-vfs-standard-callbacks.h>
91 extern "C" { // missing in the header: doh.
92 # include <libgnomevfs/gnome-vfs-module-callback.h>
95 #include "content.hxx"
96 #include "provider.hxx"
97 #include "directory.hxx"
98 #include "stream.hxx"
100 using namespace gvfs;
101 using namespace com::sun::star;
103 #define CLEAR_INFO(info) memset((info), 0, sizeof ((info)[0]))
106 static char *
107 OUStringToGnome( const rtl::OUString &str )
109 rtl::OString aTempStr = rtl::OUStringToOString( str, RTL_TEXTENCODING_UTF8 );
110 return g_strdup( (const sal_Char *) aTempStr );
113 static rtl::OUString
114 GnomeToOUString( const char *utf8_str)
116 if (!utf8_str)
117 return rtl::OUString();
118 else
119 return rtl::OUString( utf8_str, strlen( utf8_str ), RTL_TEXTENCODING_UTF8 );
123 Content::Content(
124 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
125 ContentProvider* pProvider,
126 const uno::Reference< ucb::XContentIdentifier >& Identifier)
127 throw ( ucb::ContentCreationException )
128 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
129 m_pProvider( pProvider ),
130 m_bTransient( sal_False ),
131 m_bForceReadOnly( sal_False )
133 CLEAR_INFO (&m_info);
134 #ifdef DEBUG
135 g_warning ("New Content ('%s')", getURI());
136 #endif
139 Content::Content(
140 const uno::Reference< lang::XMultiServiceFactory >& rxSMgr,
141 ContentProvider * pProvider,
142 const uno::Reference< ucb::XContentIdentifier >& Identifier,
143 sal_Bool IsFolder)
144 throw ( ucb::ContentCreationException )
145 : ContentImplHelper( rxSMgr, pProvider, Identifier ),
146 m_pProvider( pProvider ),
147 m_bTransient( sal_True ),
148 m_bForceReadOnly( sal_False )
150 CLEAR_INFO (&m_info);
152 #ifdef DEBUG
153 g_warning ("New Transient content ('%s') (%d)", getURI(), IsFolder);
154 #endif
155 // m_info.name = FIXME: set name ?
156 m_info.valid_fields = GNOME_VFS_FILE_INFO_FIELDS_TYPE;
157 m_info.type = IsFolder ? GNOME_VFS_FILE_TYPE_DIRECTORY :
158 GNOME_VFS_FILE_TYPE_REGULAR;
161 // virtual
162 Content::~Content()
164 gnome_vfs_file_info_clear( &m_info );
168 // XInterface methods.
171 void SAL_CALL Content::acquire()
172 throw( )
174 ContentImplHelper::acquire();
176 void SAL_CALL Content::release()
177 throw( )
179 ContentImplHelper::release();
181 uno::Any SAL_CALL Content::queryInterface( const uno::Type & rType )
182 throw ( uno::RuntimeException )
184 // Note: isFolder may require network activities! So call it only
185 // if it is really necessary!!!
186 uno::Any aRet = cppu::queryInterface( rType,
187 static_cast< ucb::XContentCreator * >( this ) );
188 if ( aRet.hasValue() )
189 return isFolder( uno::Reference< ucb::XCommandEnvironment >() )
190 ? aRet : uno::Any();
191 else
192 return aRet.hasValue() ? aRet : ContentImplHelper::queryInterface( rType );
196 // XTypeProvider methods.
199 XTYPEPROVIDER_COMMON_IMPL( Content );
201 uno::Sequence< uno::Type > SAL_CALL Content::getTypes()
202 throw( uno::RuntimeException )
204 static cppu::OTypeCollection *pFolderCollection = NULL;
205 static cppu::OTypeCollection *pFileCollection = NULL;
207 if (!pFolderCollection) {
208 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
210 if (!pFolderCollection) {
211 static cppu::OTypeCollection aFolderCollection
212 (CPPU_TYPE_REF( lang::XTypeProvider ),
213 CPPU_TYPE_REF( lang::XServiceInfo ),
214 CPPU_TYPE_REF( lang::XComponent ),
215 CPPU_TYPE_REF( ucb::XContent ),
216 CPPU_TYPE_REF( ucb::XCommandProcessor ),
217 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
218 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
219 CPPU_TYPE_REF( beans::XPropertyContainer ),
220 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
221 CPPU_TYPE_REF( container::XChild ),
222 CPPU_TYPE_REF( ucb::XContentCreator ) ); // !!
223 static cppu::OTypeCollection aFileCollection
224 (CPPU_TYPE_REF( lang::XTypeProvider ),
225 CPPU_TYPE_REF( lang::XServiceInfo ),
226 CPPU_TYPE_REF( lang::XComponent ),
227 CPPU_TYPE_REF( ucb::XContent ),
228 CPPU_TYPE_REF( ucb::XCommandProcessor ),
229 CPPU_TYPE_REF( beans::XPropertiesChangeNotifier ),
230 CPPU_TYPE_REF( ucb::XCommandInfoChangeNotifier ),
231 CPPU_TYPE_REF( beans::XPropertyContainer ),
232 CPPU_TYPE_REF( beans::XPropertySetInfoChangeNotifier ),
233 CPPU_TYPE_REF( container::XChild ) );
235 pFolderCollection = &aFolderCollection;
236 pFileCollection = &aFileCollection;
237 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
240 else {
241 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
244 if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) )
245 return pFolderCollection->getTypes();
246 else
247 return pFileCollection->getTypes();
251 // XServiceInfo methods.
254 rtl::OUString SAL_CALL Content::getImplementationName()
255 throw( uno::RuntimeException )
257 return rtl::OUString::createFromAscii("com.sun.star.comp.GnomeVFSContent" );
260 uno::Sequence< rtl::OUString > SAL_CALL Content::getSupportedServiceNames()
261 throw( uno::RuntimeException )
263 uno::Sequence< rtl::OUString > aSNS( 1 );
264 aSNS.getArray()[ 0 ] = rtl::OUString::createFromAscii(
265 "com.sun.star.ucb.GnomeVFSContent" );
266 return aSNS;
270 // XContent methods.
273 rtl::OUString SAL_CALL Content::getContentType()
274 throw( uno::RuntimeException )
276 if ( isFolder( uno::Reference< ucb::XCommandEnvironment >() ) )
277 return rtl::OUString::createFromAscii( GVFS_FOLDER_TYPE );
278 else
279 return rtl::OUString::createFromAscii( GVFS_FILE_TYPE );
283 // XCommandProcessor methods.
286 uno::Any Content::getBadArgExcept()
288 return uno::makeAny( lang::IllegalArgumentException
289 ( rtl::OUString::createFromAscii( "Wrong argument type!" ),
290 static_cast< cppu::OWeakObject * >( this ),
291 -1 ) );
294 #include <stdio.h>
296 uno::Any SAL_CALL Content::execute(
297 const ucb::Command& aCommand,
298 sal_Int32 /*CommandId*/,
299 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
300 throw( uno::Exception,
301 ucb::CommandAbortedException,
302 uno::RuntimeException )
304 uno::Any aRet;
306 #ifdef DEBUG
308 uno::Reference< task::XInteractionHandler > xIH;
310 if ( xEnv.is() )
311 xIH = xEnv->getInteractionHandler();
312 g_warning( "Execute command: '%s' with %s interaction env",
313 OUStringToGnome( aCommand.Name ),
314 xIH.is() ? "" : "NO" );
316 #endif
318 #define COMMAND_IS(cmd,name) ( (cmd).Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( name ) ) )
320 if ( COMMAND_IS( aCommand, "getPropertyValues" ) ) {
321 uno::Sequence< beans::Property > Properties;
323 if ( !( aCommand.Argument >>= Properties ) )
324 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
326 aRet <<= getPropertyValues( Properties, xEnv );
328 } else if ( COMMAND_IS( aCommand, "setPropertyValues" ) ) {
329 uno::Sequence< beans::PropertyValue > aProperties;
331 if ( !( aCommand.Argument >>= aProperties ) ||
332 !aProperties.getLength() )
333 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
335 aRet <<= setPropertyValues( aProperties, xEnv );
337 } else if ( COMMAND_IS( aCommand, "getPropertySetInfo" ) ) {
338 aRet <<= getPropertySetInfo( xEnv, sal_False );
340 } else if ( COMMAND_IS( aCommand, "getCommandInfo" ) ) {
341 aRet <<= getCommandInfo( xEnv, sal_False );
343 } else if ( COMMAND_IS( aCommand, "open" ) ) {
344 rtl::OUString str = m_xIdentifier->getContentIdentifier();
345 rtl::OString stra(
346 str.getStr(),
347 str.getLength(),
348 RTL_TEXTENCODING_UTF8);
350 ucb::OpenCommandArgument2 aOpenCommand;
351 if ( !( aCommand.Argument >>= aOpenCommand ) )
352 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
354 sal_Bool bOpenFolder =
355 ( ( aOpenCommand.Mode == ucb::OpenMode::ALL ) ||
356 ( aOpenCommand.Mode == ucb::OpenMode::FOLDERS ) ||
357 ( aOpenCommand.Mode == ucb::OpenMode::DOCUMENTS ) );
359 if ( bOpenFolder && isFolder( xEnv ) ) {
360 uno::Reference< ucb::XDynamicResultSet > xSet
361 = new DynamicResultSet(m_xSMgr, this, aOpenCommand, xEnv );
362 aRet <<= xSet;
364 } else if ( aOpenCommand.Sink.is() ) {
366 if ( ( aOpenCommand.Mode
367 == ucb::OpenMode::DOCUMENT_SHARE_DENY_NONE ) ||
368 ( aOpenCommand.Mode
369 == ucb::OpenMode::DOCUMENT_SHARE_DENY_WRITE ) ) {
370 ucbhelper::cancelCommandExecution
371 ( uno::makeAny ( ucb::UnsupportedOpenModeException
372 ( rtl::OUString(),
373 static_cast< cppu::OWeakObject * >( this ),
374 sal_Int16( aOpenCommand.Mode ) ) ),
375 xEnv );
377 if ( !feedSink( aOpenCommand.Sink, xEnv ) ) {
378 // Note: aOpenCommand.Sink may contain an XStream
379 // implementation. Support for this type of
380 // sink is optional...
381 #ifdef DEBUG
382 g_warning ("Failed to load data from '%s'", getURI());
383 #endif
384 ucbhelper::cancelCommandExecution
385 ( uno::makeAny (ucb::UnsupportedDataSinkException
386 ( rtl::OUString(),
387 static_cast< cppu::OWeakObject * >( this ),
388 aOpenCommand.Sink ) ),
389 xEnv );
392 #ifdef DEBUG
393 else
394 g_warning ("Open falling through ...");
395 #endif
397 } else if ( COMMAND_IS( aCommand, "insert" ) ) {
398 ucb::InsertCommandArgument arg;
399 if ( !( aCommand.Argument >>= arg ) )
400 ucbhelper::cancelCommandExecution ( getBadArgExcept (), xEnv );
402 insert( arg.Data, arg.ReplaceExisting, xEnv );
404 } else if ( COMMAND_IS( aCommand, "delete" ) ) {
406 sal_Bool bDeletePhysical = sal_False;
407 aCommand.Argument >>= bDeletePhysical;
409 ::rtl::OString aURI = getOURI();
410 GnomeVFSResult result = gnome_vfs_unlink ((const sal_Char *) aURI);
412 if (result != GNOME_VFS_OK)
413 cancelCommandExecution( result, xEnv, sal_True );
415 destroy( bDeletePhysical );
417 } else if ( COMMAND_IS( aCommand, "transfer" ) && isFolder( xEnv ) ) {
418 ucb::TransferInfo transferArgs;
420 if ( !( aCommand.Argument >>= transferArgs ) )
421 ucbhelper::cancelCommandExecution( getBadArgExcept(), xEnv );
423 transfer( transferArgs, xEnv );
425 } else { // Unsuported
426 #ifdef DEBUG
427 g_warning( "Unsupported command: '%s'",
428 OUStringToGnome( aCommand.Name ) );
429 #endif
430 ucbhelper::cancelCommandExecution
431 ( uno::makeAny( ucb::UnsupportedCommandException
432 ( rtl::OUString(),
433 static_cast< cppu::OWeakObject * >( this ) ) ),
434 xEnv );
436 #undef COMMAND_IS
438 return aRet;
441 void SAL_CALL Content::abort( sal_Int32 /*CommandId*/ )
442 throw( uno::RuntimeException )
444 // FIXME: we should use the GnomeVFSCancellation APIs here ...
448 // XContentCreator methods.
451 uno::Sequence< ucb::ContentInfo > SAL_CALL
452 Content::queryCreatableContentsInfo()
453 throw( uno::RuntimeException )
455 uno::Sequence< ucb::ContentInfo > seq(2);
457 // Minimum set of props we really need
458 uno::Sequence< beans::Property > props( 1 );
459 props[0] = beans::Property(
460 rtl::OUString::createFromAscii( "Title" ),
462 getCppuType( static_cast< rtl::OUString* >( 0 ) ),
463 beans::PropertyAttribute::MAYBEVOID | beans::PropertyAttribute::BOUND );
465 // file
466 seq[0].Type = rtl::OUString::createFromAscii( GVFS_FILE_TYPE );
467 seq[0].Attributes = ( ucb::ContentInfoAttribute::INSERT_WITH_INPUTSTREAM |
468 ucb::ContentInfoAttribute::KIND_DOCUMENT );
469 seq[0].Properties = props;
471 // folder
472 seq[1].Type = rtl::OUString::createFromAscii( GVFS_FOLDER_TYPE );
473 seq[1].Attributes = ucb::ContentInfoAttribute::KIND_FOLDER;
474 seq[1].Properties = props;
476 return seq;
479 uno::Reference< ucb::XContent > SAL_CALL
480 Content::createNewContent( const ucb::ContentInfo& Info )
481 throw( uno::RuntimeException )
483 bool create_document;
484 const char *name;
486 if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GVFS_FILE_TYPE ) ) )
487 create_document = true;
488 else if ( Info.Type.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( GVFS_FOLDER_TYPE ) ) )
489 create_document = false;
490 else {
491 #ifdef DEBUG
492 g_warning( "Failed to create new content '%s'",
493 OUStringToGnome( Info.Type ) );
494 #endif
495 return uno::Reference< ucb::XContent >();
498 #ifdef DEBUG
499 g_warning( "createNewContent (%d)", (int) create_document );
500 #endif
502 rtl::OUString aURL = getOUURI();
504 if ( ( aURL.lastIndexOf( '/' ) + 1 ) != aURL.getLength() )
505 aURL += rtl::OUString::createFromAscii( "/" );
507 name = create_document ? "[New_Content]" : "[New_Collection]";
508 // This looks problematic to me cf. webdav
509 aURL += rtl::OUString::createFromAscii( name );
511 uno::Reference< ucb::XContentIdentifier > xId
512 ( new ::ucbhelper::ContentIdentifier( m_xSMgr, aURL ) );
514 try {
515 return new ::gvfs::Content( m_xSMgr, m_pProvider, xId, !create_document );
516 } catch ( ucb::ContentCreationException & ) {
517 return uno::Reference< ucb::XContent >();
521 rtl::OUString Content::getParentURL()
523 rtl::OUString aParentURL;
524 // <scheme>:// -> ""
525 // <scheme>://foo -> ""
526 // <scheme>://foo/ -> ""
527 // <scheme>://foo/bar -> <scheme>://foo/
528 // <scheme>://foo/bar/ -> <scheme>://foo/
529 // <scheme>://foo/bar/abc -> <scheme>://foo/bar/
531 rtl::OUString aURL = getOUURI();
533 sal_Int32 nPos = aURL.lastIndexOf( '/' );
534 if ( nPos == ( aURL.getLength() - 1 ) ) {
535 // Trailing slash found. Skip.
536 nPos = aURL.lastIndexOf( '/', nPos );
539 sal_Int32 nPos1 = aURL.lastIndexOf( '/', nPos );
540 if ( nPos1 != -1 )
541 nPos1 = aURL.lastIndexOf( '/', nPos1 );
543 if ( nPos1 != -1 )
544 aParentURL = rtl::OUString( aURL.copy( 0, nPos + 1 ) );
546 #ifdef DEBUG
547 g_warning ("getParentURL '%s' -> '%s'",
548 getURI(), (const sal_Char *) rtl::OUStringToOString
549 ( aParentURL, RTL_TEXTENCODING_UTF8 ) );
550 #endif
552 return aParentURL;
555 static util::DateTime
556 getDateFromUnix (time_t t)
558 TimeValue tv;
559 tv.Nanosec = 0;
560 tv.Seconds = t;
561 oslDateTime dt;
563 if ( osl_getDateTimeFromTimeValue( &tv, &dt ) )
564 return util::DateTime( 0, dt.Seconds, dt.Minutes, dt.Hours,
565 dt.Day, dt.Month, dt.Year);
566 else
567 return util::DateTime();
570 uno::Reference< sdbc::XRow > Content::getPropertyValues(
571 const uno::Sequence< beans::Property >& rProperties,
572 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
574 int nProps;
575 GnomeVFSResult result;
576 uno::Sequence< beans::Property > allProperties;
578 result = getInfo( xEnv );
580 const beans::Property* pProps;
582 if( rProperties.getLength() ) {
583 nProps = rProperties.getLength();
584 pProps = rProperties.getConstArray();
585 } else {
586 allProperties = getPropertySetInfo( xEnv )->getProperties();
587 nProps = allProperties.getLength();
588 pProps = allProperties.getConstArray();
591 rtl::Reference< ::ucbhelper::PropertyValueSet > xRow
592 = new ::ucbhelper::PropertyValueSet( m_xSMgr );
594 osl::Guard< osl::Mutex > aGuard( m_aMutex );
595 for( sal_Int32 n = 0; n < nProps; ++n ) {
596 const beans::Property& rProp = pProps[ n ];
598 if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "SupportsActiveStreaming" ) ) ) {
599 xRow->appendBoolean( rProp, sal_True );
601 else if (result != GNOME_VFS_OK && result != GNOME_VFS_ERROR_PROTOCOL_ERROR) {
602 // 'SupportsActiveStreaming' is the only property that can be
603 // obtained even if getInfo() failed
604 // We ignore protocol errors - happens eg. for broken links over sftp:// :-(
605 cancelCommandExecution( result, xEnv, sal_False );
607 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) {
608 if (m_info.name && m_info.name[0] == '/')
609 g_warning ("Odd NFS title on item '%s' == '%s'",
610 getURI(), m_info.name);
612 if (result != GNOME_VFS_ERROR_PROTOCOL_ERROR)
613 xRow->appendString( rProp, GnomeToOUString( m_info.name ) );
614 else {
615 // m_info is not valid, we have to guess something close enough
616 rtl::OUString aURI( getOUURI() );
618 sal_Int32 nLastSlash = aURI.lastIndexOf( '/' );
619 if (nLastSlash >= 0)
620 aURI = aURI.copy( nLastSlash + 1 );
622 xRow->appendString( rProp, aURI );
626 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) )
627 xRow->appendString( rProp, getContentType () );
629 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ) {
630 if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE)
631 xRow->appendBoolean( rProp, ( m_info.type == GNOME_VFS_FILE_TYPE_REGULAR ||
632 m_info.type == GNOME_VFS_FILE_TYPE_UNKNOWN ) );
633 else
634 xRow->appendVoid( rProp );
637 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ) {
638 if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE)
639 xRow->appendBoolean( rProp, ( m_info.type == GNOME_VFS_FILE_TYPE_DIRECTORY ) );
640 else
641 xRow->appendVoid( rProp );
644 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) ) {
645 if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE)
646 xRow->appendLong( rProp, m_info.size );
647 else
648 xRow->appendVoid( rProp );
651 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsReadOnly" ) ) ) {
652 if ( m_bForceReadOnly )
653 xRow->appendBoolean( rProp, sal_True );
654 else if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS) {
655 bool read_only = true;
657 if (m_info.uid == getuid () &&
658 m_info.permissions & GNOME_VFS_PERM_USER_WRITE)
659 read_only = false;
660 else if (m_info.gid == getgid () &&
661 m_info.permissions & GNOME_VFS_PERM_GROUP_WRITE)
662 read_only = false;
663 else if (m_info.permissions & GNOME_VFS_PERM_OTHER_WRITE)
664 read_only = false;
665 xRow->appendBoolean( rProp, read_only );
666 } else
667 xRow->appendVoid( rProp );
670 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsHidden" ) ) )
671 xRow->appendBoolean( rProp, ( m_info.name && m_info.name[0] == '.' ) );
673 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsVolume" ) ) ||
674 rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsCompactDisk" ) ) )
675 xRow->appendBoolean( rProp, sal_False );
677 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ) {
678 if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_CTIME)
679 xRow->appendTimestamp( rProp, getDateFromUnix( m_info.ctime ) );
680 else
681 xRow->appendVoid( rProp );
684 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) {
685 if (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MTIME)
686 xRow->appendTimestamp( rProp, getDateFromUnix( m_info.mtime ) );
687 else
688 xRow->appendVoid( rProp );
691 else if (rProp.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) {
692 // We do this by sniffing in gnome-vfs; rather expensively.
693 #ifdef DEBUG
694 g_warning ("FIXME: Requested mime-type - an expensive op. indeed!");
695 #endif
696 xRow->appendVoid( rProp );
697 } else {
698 xRow->appendVoid( rProp );
701 #ifdef DEBUG
702 g_warning ("getPropertyValues on '%s' %d properties returned (of %d)",
703 getURI(), (int)xRow->getLength(), (int)nProps);
704 #endif
706 return uno::Reference< sdbc::XRow >( xRow.get() );
709 static lang::IllegalAccessException
710 getReadOnlyException( Content *ctnt )
712 return lang::IllegalAccessException
713 ( rtl::OUString::createFromAscii( "Property is read-only!" ),
714 static_cast< cppu::OWeakObject * >( ctnt ) );
717 rtl::OUString
718 Content::makeNewURL( const char */*newName*/ )
720 rtl::OUString aNewURL = getParentURL();
721 if ( aNewURL.lastIndexOf( '/' ) != ( aNewURL.getLength() - 1 ) )
722 aNewURL += rtl::OUString::createFromAscii( "/" );
724 char *name = gnome_vfs_escape_string( m_info.name );
725 aNewURL += GnomeToOUString( name );
726 g_free( name );
728 return aNewURL;
731 // This is slightly complicated by needing to support either 'move' or 'setname'
732 GnomeVFSResult
733 Content::doSetFileInfo( const GnomeVFSFileInfo *newInfo,
734 GnomeVFSSetFileInfoMask setMask,
735 const uno::Reference< ucb::XCommandEnvironment >& /*xEnv*/ )
737 GnomeVFSResult result = GNOME_VFS_OK;
739 g_assert (!m_bTransient);
741 ::rtl::OString aURI = getOURI();
743 osl::Guard< osl::Mutex > aGuard( m_aMutex );
745 // The simple approach:
746 if( setMask != GNOME_VFS_SET_FILE_INFO_NONE )
747 result = gnome_vfs_set_file_info // missed a const in the API there
748 ( (const sal_Char *) aURI, (GnomeVFSFileInfo *)newInfo, setMask );
750 if ( result == GNOME_VFS_ERROR_NOT_SUPPORTED &&
751 ( setMask & GNOME_VFS_SET_FILE_INFO_NAME ) ) {
752 // Try a move instead
753 #ifdef DEBUG
754 g_warning( "SetFileInfo not supported on '%s'", getURI() );
755 #endif
757 char *newURI = OUStringToGnome( makeNewURL( newInfo->name ) );
759 result = gnome_vfs_move ((const sal_Char *)aURI, newURI, FALSE);
761 g_free (newURI);
764 return result;
768 uno::Sequence< uno::Any > Content::setPropertyValues(
769 const uno::Sequence< beans::PropertyValue >& rValues,
770 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
772 rtl::OUString aNewTitle;
773 GnomeVFSFileInfo newInfo;
774 int setMask = GNOME_VFS_SET_FILE_INFO_NONE;
776 getInfo( xEnv );
778 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
780 gnome_vfs_file_info_copy( &newInfo, &m_info );
782 Authentication aAuth( xEnv );
784 int nChanged = 0, nTitlePos = 0;
785 uno::Sequence< uno::Any > aRet( rValues.getLength() );
786 uno::Sequence< beans::PropertyChangeEvent > aChanges( rValues.getLength() );
788 beans::PropertyChangeEvent aEvent;
789 aEvent.Source = static_cast< cppu::OWeakObject * >( this );
790 aEvent.Further = sal_False;
791 aEvent.PropertyHandle = -1;
792 // aEvent.PropertyName = fill in later ...
793 // aEvent.OldValue =
794 // aEvent.NewValue =
796 int nCount = rValues.getLength();
797 const beans::PropertyValue* pValues = rValues.getConstArray();
799 for ( sal_Int32 n = 0; n < nCount; ++n ) {
800 const beans::PropertyValue& rValue = pValues[ n ];
802 #ifdef DEBUG
803 g_warning( "Set prop '%s'", OUStringToGnome( rValue.Name ) );
804 #endif
805 if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ContentType" ) ) ||
806 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ||
807 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsDocument" ) ) ||
808 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsFolder" ) ) ||
809 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Size" ) ) )
810 aRet[ n ] <<= getReadOnlyException( this );
812 else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "Title" ) ) ) {
813 if ( rValue.Value >>= aNewTitle ) {
814 if ( aNewTitle.getLength() <= 0 )
815 aRet[ n ] <<= lang::IllegalArgumentException
816 ( rtl::OUString::createFromAscii( "Empty title not allowed!" ),
817 static_cast< cppu::OWeakObject * >( this ), -1 );
818 else {
819 char *newName = OUStringToGnome( aNewTitle );
821 if( !newName || !m_info.name || strcmp( newName, m_info.name ) ) {
822 #ifdef DEBUG
823 g_warning ("Set new name to '%s'", newName);
824 #endif
826 aEvent.PropertyName = rtl::OUString::createFromAscii( "Title" );
827 aEvent.OldValue = uno::makeAny( GnomeToOUString( newInfo.name ) );
828 aEvent.NewValue = uno::makeAny( aNewTitle );
829 aChanges.getArray()[ nChanged ] = aEvent;
830 nTitlePos = nChanged++;
832 newInfo.name = newName;
833 setMask |= GNOME_VFS_SET_FILE_INFO_NAME;
834 } else // same name
835 g_free (newName);
837 } else
838 aRet[ n ] <<= beans::IllegalTypeException
839 ( rtl::OUString::createFromAscii( "Property value has wrong type!" ),
840 static_cast< cppu::OWeakObject * >( this ) );
842 } else if ( rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateCreated" ) ) ||
843 rValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "DateModified" ) ) ) {
844 // FIXME: should be able to set the timestamps
845 aRet[ n ] <<= getReadOnlyException( this );
846 } else {
847 #ifdef DEBUG
848 g_warning( "Unhandled property '%s'", OUStringToGnome( rValue.Name ) );
849 #endif
850 aRet[ n ] <<= getReadOnlyException( this );
854 GnomeVFSResult result = GNOME_VFS_OK;
856 if ( !m_bTransient &&
857 ( result = doSetFileInfo( &newInfo,
858 (GnomeVFSSetFileInfoMask) setMask,
859 xEnv ) ) != GNOME_VFS_OK ) {
860 for (int i = 0; i < nChanged; i++)
861 aRet[ i ] <<= mapVFSException( result, sal_True );
865 if ( result == GNOME_VFS_OK) {
866 gnome_vfs_file_info_copy( &m_info, &newInfo );
868 if ( setMask & GNOME_VFS_SET_FILE_INFO_NAME ) {
869 uno::Reference< ucb::XContentIdentifier > xNewId
870 = new ::ucbhelper::ContentIdentifier(
871 m_xSMgr, makeNewURL( newInfo.name ) );
873 aGuard.clear();
874 if (!exchangeIdentity( xNewId ) )
875 aRet[ nTitlePos ] <<= uno::Exception
876 ( rtl::OUString::createFromAscii( "Exchange failed!" ),
877 static_cast< cppu::OWeakObject * >( this ) );
881 gnome_vfs_file_info_clear( &newInfo );
883 if ( nChanged > 0 ) {
884 aGuard.clear();
885 aChanges.realloc( nChanged );
886 notifyPropertiesChange( aChanges );
889 return aRet;
892 void Content::queryChildren( ContentRefList& rChildren )
894 // Obtain a list with a snapshot of all currently instanciated contents
895 // from provider and extract the contents which are direct children
896 // of this content.
898 ::ucbhelper::ContentRefList aAllContents;
899 m_xProvider->queryExistingContents( aAllContents );
901 rtl::OUString aURL = getOUURI();
902 sal_Int32 nURLPos = aURL.lastIndexOf( '/' );
904 if ( nURLPos != ( aURL.getLength() - 1 ) )
905 aURL += rtl::OUString::createFromAscii( "/" );
907 sal_Int32 nLen = aURL.getLength();
909 ::ucbhelper::ContentRefList::const_iterator it = aAllContents.begin();
910 ::ucbhelper::ContentRefList::const_iterator end = aAllContents.end();
912 while ( it != end ) {
913 ::ucbhelper::ContentImplHelperRef xChild = (*it);
914 rtl::OUString aChildURL
915 = xChild->getIdentifier()->getContentIdentifier();
917 // Is aURL a prefix of aChildURL?
918 if ( ( aChildURL.getLength() > nLen ) &&
919 ( aChildURL.compareTo( aURL, nLen ) == 0 ) ) {
920 sal_Int32 nPos = nLen;
921 nPos = aChildURL.indexOf( '/', nPos );
923 if ( ( nPos == -1 ) ||
924 ( nPos == ( aChildURL.getLength() - 1 ) ) ) {
925 // No further slashes / only a final slash. It's a child!
926 rChildren.push_back( ::gvfs::Content::ContentRef
927 (static_cast< ::gvfs::Content * >(xChild.get() ) ) );
930 ++it;
934 void Content::insert(
935 const uno::Reference< io::XInputStream > &xInputStream,
936 sal_Bool bReplaceExisting,
937 const uno::Reference< ucb::XCommandEnvironment > &xEnv )
938 throw( uno::Exception )
940 osl::ClearableGuard< osl::Mutex > aGuard( m_aMutex );
942 GnomeVFSOpenMode nOpenMode;
944 #ifdef DEBUG
945 g_warning( "Insert '%s' (%d) (0x%x:%d)", getURI(), bReplaceExisting,
946 m_info.valid_fields, m_info.type );
947 #endif
949 GnomeVFSResult result = getInfo( xEnv );
950 // a racy design indeed.
951 if( !bReplaceExisting && !m_bTransient &&
952 result != GNOME_VFS_ERROR_NOT_FOUND) {
953 #ifdef DEBUG
954 g_warning ("Nasty error inserting to '%s' ('%s')",
955 getURI(), gnome_vfs_result_to_string( result ));
956 #endif
957 cancelCommandExecution( GNOME_VFS_ERROR_FILE_EXISTS, xEnv, sal_True );
960 if ( m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE &&
961 m_info.type == GNOME_VFS_FILE_TYPE_DIRECTORY ) {
962 ::rtl::OString aURI = getOURI();
963 int perm;
965 perm = ( GNOME_VFS_PERM_USER_ALL |
966 GNOME_VFS_PERM_GROUP_READ |
967 GNOME_VFS_PERM_OTHER_READ );
969 #ifdef DEBUG
970 g_warning ("Make directory");
971 #endif
972 result = gnome_vfs_make_directory( (const sal_Char *) aURI, perm );
974 if( result != GNOME_VFS_OK )
975 cancelCommandExecution( result, xEnv, sal_True );
977 return;
980 if ( !xInputStream.is() ) {
981 // FIXME: slightly unclear whether to accept this and create an empty file
982 ucbhelper::cancelCommandExecution
983 ( uno::makeAny
984 ( ucb::MissingInputStreamException
985 ( rtl::OUString(),
986 static_cast< cppu::OWeakObject * >( this ) ) ),
987 xEnv );
990 GnomeVFSHandle *handle = NULL;
991 ::rtl::OString aURI = getOURI();
993 result = GNOME_VFS_OK;
994 if ( bReplaceExisting ) {
995 Authentication aAuth( xEnv );
996 nOpenMode = (GnomeVFSOpenMode)(GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_LOCKED);
997 result = gnome_vfs_open( &handle, (const sal_Char *)aURI, nOpenMode );
1000 if ( result == GNOME_VFS_ERROR_LOCKED )
1001 throwLocked( xEnv );
1002 else if ( result != GNOME_VFS_OK ) {
1003 int perm;
1004 Authentication aAuth( xEnv );
1006 perm = ( ( GNOME_VFS_PERM_USER_WRITE | GNOME_VFS_PERM_USER_READ ) |
1007 ( GNOME_VFS_PERM_GROUP_WRITE | GNOME_VFS_PERM_GROUP_READ ) );
1009 nOpenMode = (GnomeVFSOpenMode)(GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_LOCKED);
1010 result = gnome_vfs_create
1011 ( &handle, (const sal_Char *)aURI, nOpenMode, TRUE, perm );
1014 if ( result == GNOME_VFS_ERROR_LOCKED )
1015 throwLocked( xEnv );
1016 else if ( result != GNOME_VFS_OK )
1017 cancelCommandExecution( result, xEnv, sal_True );
1019 if ( !xInputStream.is() ) {
1020 result = gnome_vfs_close( handle );
1021 if (result != GNOME_VFS_OK)
1022 cancelCommandExecution( result, xEnv, sal_True );
1024 } else { // copy it over
1025 uno::Reference < io::XOutputStream > xOutput =
1026 new gvfs::Stream( handle, &m_info, (const sal_Char *)aURI, nOpenMode );
1028 copyData( xInputStream, xOutput );
1031 if (m_bTransient) {
1032 m_bTransient = sal_False;
1033 aGuard.clear();
1034 inserted();
1038 void Content::transfer(const ucb::TransferInfo & /*rArgs*/,
1039 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1040 throw( uno::Exception )
1042 // FIXME: see gnome-vfs-xfer.h - but we need to be able to easily
1043 // detect which are gnome-vfs owned URI types ...
1044 ucbhelper::cancelCommandExecution
1045 ( uno::makeAny
1046 ( ucb::InteractiveBadTransferURLException
1047 ( rtl::OUString::createFromAscii( "Unsupported URL scheme!" ),
1048 static_cast< cppu::OWeakObject * >( this ) ) ),
1049 xEnv );
1052 void Content::destroy( sal_Bool bDeletePhysical )
1053 throw( uno::Exception )
1055 // @@@ take care about bDeletePhysical -> trashcan support
1056 rtl::OUString aURL = getOUURI();
1058 uno::Reference< ucb::XContent > xThis = this;
1060 deleted();
1062 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1064 // Process instanciated children...
1065 ::gvfs::Content::ContentRefList aChildren;
1066 queryChildren( aChildren );
1068 ContentRefList::const_iterator it = aChildren.begin();
1069 ContentRefList::const_iterator end = aChildren.end();
1071 while ( it != end ) {
1072 (*it)->destroy( bDeletePhysical );
1073 ++it;
1077 // Used by the 'setPropertyValues' method for
1078 // propagating the renaming of a Content.
1079 sal_Bool Content::exchangeIdentity(
1080 const uno::Reference< ucb::XContentIdentifier >& xNewId )
1082 if ( !xNewId.is() )
1083 return sal_False;
1085 uno::Reference< ucb::XContent > xThis = this;
1087 #ifdef DEBUG
1088 g_warning( "exchangeIdentity from '%s' to '%s'",
1089 getURI(), OUStringToGnome( xNewId->getContentIdentifier() ) );
1090 #endif
1092 if ( m_bTransient ) {
1093 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1094 /* FIXME: can we not screw up an identically named
1095 * Content pointing to ourself here ? */
1096 m_xIdentifier = xNewId;
1097 return sal_False;
1100 rtl::OUString aOldURL = getOUURI();
1102 // Exchange own identitity.
1103 if ( exchange( xNewId ) ) {
1105 // Process instanciated children...
1106 ContentRefList aChildren;
1107 queryChildren( aChildren );
1109 ContentRefList::const_iterator it = aChildren.begin();
1110 ContentRefList::const_iterator end = aChildren.end();
1112 while ( it != end ) {
1113 ContentRef xChild = (*it);
1115 // Create new content identifier for the child...
1116 uno::Reference< ucb::XContentIdentifier >
1117 xOldChildId = xChild->getIdentifier();
1118 rtl::OUString aOldChildURL
1119 = xOldChildId->getContentIdentifier();
1120 rtl::OUString aNewChildURL
1121 = aOldChildURL.replaceAt(
1123 aOldURL.getLength(),
1124 xNewId->getContentIdentifier() );
1125 uno::Reference< ucb::XContentIdentifier >
1126 xNewChildId
1127 = new ::ucbhelper::ContentIdentifier( m_xSMgr, aNewChildURL );
1129 if ( !xChild->exchangeIdentity( xNewChildId ) )
1130 return sal_False;
1132 ++it;
1134 return sal_True;
1137 return sal_False;
1140 GnomeVFSResult
1141 Content::getInfo( const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1143 GnomeVFSResult result;
1144 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1146 if (m_bTransient)
1147 result = GNOME_VFS_OK;
1149 else if ( !m_info.valid_fields ) {
1150 ::rtl::OString aURI = getOURI();
1151 Authentication aAuth( xEnv );
1152 result = gnome_vfs_get_file_info
1153 ( (const sal_Char *)aURI, &m_info, GNOME_VFS_FILE_INFO_DEFAULT );
1154 if (result != GNOME_VFS_OK)
1155 gnome_vfs_file_info_clear( &m_info );
1156 } else
1157 result = GNOME_VFS_OK;
1158 #ifdef DEBUG
1159 g_warning( "getInfo on '%s' returns '%s' (%d) (0x%x)",
1160 getURI(), gnome_vfs_result_to_string( result ),
1161 result, m_info.valid_fields );
1162 #endif
1163 return result;
1166 sal_Bool
1167 Content::isFolder(const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1169 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1170 getInfo( xEnv );
1171 return (m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_TYPE &&
1172 m_info.type == GNOME_VFS_FILE_TYPE_DIRECTORY);
1175 uno::Any Content::mapVFSException( const GnomeVFSResult result, sal_Bool bWrite )
1177 uno::Any aException;
1178 const char *gvfs_message;
1179 rtl::OUString message;
1180 uno::Sequence< uno::Any > aArgs( 1 );
1182 #ifdef DEBUG
1183 g_warning ("Map VFS exception '%s' (%d)",
1184 gnome_vfs_result_to_string( result ), result );
1185 #endif
1187 if ((gvfs_message = gnome_vfs_result_to_string (result)))
1188 message = GnomeToOUString( gvfs_message );
1190 switch (result) {
1191 case GNOME_VFS_OK:
1192 g_error ("VFS_OK mapped to exception.");
1193 break;
1194 case GNOME_VFS_ERROR_EOF:
1195 g_warning ("VFS_EOF not handled somewhere.");
1196 break;
1197 case GNOME_VFS_ERROR_NOT_FOUND:
1198 aArgs[ 0 ] <<= m_xIdentifier->getContentIdentifier();
1199 aException <<=
1200 ucb::InteractiveAugmentedIOException
1201 ( rtl::OUString::createFromAscii( "Not found!" ),
1202 static_cast< cppu::OWeakObject * >( this ),
1203 task::InteractionClassification_ERROR,
1204 ucb::IOErrorCode_NOT_EXISTING,
1205 aArgs );
1206 break;
1207 case GNOME_VFS_ERROR_BAD_PARAMETERS:
1208 aException <<=
1209 lang::IllegalArgumentException
1210 ( rtl::OUString(),
1211 static_cast< cppu::OWeakObject * >( this ),
1212 -1 );
1213 break;
1214 case GNOME_VFS_ERROR_GENERIC:
1215 case GNOME_VFS_ERROR_INTERNAL:
1216 case GNOME_VFS_ERROR_NOT_SUPPORTED:
1217 #ifdef DEBUG
1218 g_warning ("Internal - un-mapped error");
1219 #endif
1220 aException <<= io::IOException();
1221 break;
1222 case GNOME_VFS_ERROR_IO:
1223 if ( bWrite )
1224 aException <<=
1225 ucb::InteractiveNetworkWriteException
1226 ( rtl::OUString(),
1227 static_cast< cppu::OWeakObject * >( this ),
1228 task::InteractionClassification_ERROR,
1229 message );
1230 else
1231 aException <<=
1232 ucb::InteractiveNetworkReadException
1233 ( rtl::OUString(),
1234 static_cast< cppu::OWeakObject * >( this ),
1235 task::InteractionClassification_ERROR,
1236 message );
1237 break;
1238 case GNOME_VFS_ERROR_HOST_NOT_FOUND:
1239 case GNOME_VFS_ERROR_INVALID_HOST_NAME:
1240 aException <<=
1241 ucb::InteractiveNetworkResolveNameException
1242 ( rtl::OUString(),
1243 static_cast< cppu::OWeakObject * >( this ),
1244 task::InteractionClassification_ERROR,
1245 message );
1246 break;
1247 case GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE:
1248 case GNOME_VFS_ERROR_SERVICE_OBSOLETE:
1249 case GNOME_VFS_ERROR_PROTOCOL_ERROR:
1250 case GNOME_VFS_ERROR_NO_MASTER_BROWSER:
1251 aException <<=
1252 ucb::InteractiveNetworkConnectException
1253 ( rtl::OUString(),
1254 static_cast< cppu::OWeakObject * >( this ),
1255 task::InteractionClassification_ERROR,
1256 message );
1257 break;
1259 case GNOME_VFS_ERROR_FILE_EXISTS:
1260 aException <<= ucb::NameClashException
1261 ( rtl::OUString(),
1262 static_cast< cppu::OWeakObject * >( this ),
1263 task::InteractionClassification_ERROR,
1264 message );
1265 break;
1267 case GNOME_VFS_ERROR_INVALID_OPEN_MODE:
1268 aException <<= ucb::UnsupportedOpenModeException();
1269 break;
1271 case GNOME_VFS_ERROR_CORRUPTED_DATA:
1272 case GNOME_VFS_ERROR_WRONG_FORMAT:
1273 case GNOME_VFS_ERROR_BAD_FILE:
1274 case GNOME_VFS_ERROR_TOO_BIG:
1275 case GNOME_VFS_ERROR_NO_SPACE:
1276 case GNOME_VFS_ERROR_READ_ONLY:
1277 case GNOME_VFS_ERROR_INVALID_URI:
1278 case GNOME_VFS_ERROR_NOT_OPEN:
1279 case GNOME_VFS_ERROR_ACCESS_DENIED:
1280 case GNOME_VFS_ERROR_TOO_MANY_OPEN_FILES:
1281 case GNOME_VFS_ERROR_NOT_A_DIRECTORY:
1282 case GNOME_VFS_ERROR_IN_PROGRESS:
1283 case GNOME_VFS_ERROR_INTERRUPTED:
1284 case GNOME_VFS_ERROR_LOOP:
1285 case GNOME_VFS_ERROR_NOT_PERMITTED:
1286 case GNOME_VFS_ERROR_IS_DIRECTORY:
1287 case GNOME_VFS_ERROR_NO_MEMORY:
1288 case GNOME_VFS_ERROR_HOST_HAS_NO_ADDRESS:
1289 case GNOME_VFS_ERROR_LOGIN_FAILED:
1290 case GNOME_VFS_ERROR_CANCELLED:
1291 case GNOME_VFS_ERROR_DIRECTORY_BUSY:
1292 case GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY:
1293 case GNOME_VFS_ERROR_TOO_MANY_LINKS:
1294 case GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM:
1295 case GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM:
1296 case GNOME_VFS_ERROR_NAME_TOO_LONG:
1297 #ifdef DEBUG
1298 g_warning( "FIXME: Un-mapped VFS exception '%s' (%d)",
1299 gnome_vfs_result_to_string( result ), result );
1300 #endif
1301 default:
1302 aException <<= ucb::InteractiveNetworkGeneralException
1303 ( rtl::OUString(),
1304 static_cast< cppu::OWeakObject * >( this ),
1305 task::InteractionClassification_ERROR );
1306 break;
1309 return aException;
1312 void Content::cancelCommandExecution(
1313 GnomeVFSResult result,
1314 const uno::Reference< ucb::XCommandEnvironment > & xEnv,
1315 sal_Bool bWrite /* = sal_False */ )
1316 throw ( uno::Exception )
1318 ucbhelper::cancelCommandExecution( mapVFSException( result, bWrite ), xEnv );
1319 // Unreachable
1322 void Content::throwLocked( const uno::Reference< ucb::XCommandEnvironment > & xEnv)
1323 throw( uno::Exception )
1325 #ifdef DEBUG
1326 g_warning( "File locked, throwing IOErrorCode_LOCKING_VIOLATION" );
1327 #endif
1329 m_bForceReadOnly = sal_True;
1331 ucbhelper::cancelCommandExecution( ucb::IOErrorCode_LOCKING_VIOLATION,
1332 uno::Sequence< uno::Any >( 0 ), // FIXME more info about the file?
1333 xEnv,
1334 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "an error occured during file opening" ) ),
1335 this );
1338 uno::Sequence< beans::Property > Content::getProperties(
1339 const uno::Reference< ucb::XCommandEnvironment > & /*xEnv*/ )
1341 static const beans::Property aGenericProperties[] = {
1342 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ContentType" ) ),
1343 -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1344 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1345 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsDocument" ) ),
1346 -1, getCppuBooleanType(),
1347 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1348 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsFolder" ) ),
1349 -1, getCppuBooleanType(),
1350 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1351 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Title" ) ),
1352 -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1353 beans::PropertyAttribute::BOUND ),
1354 // Optional ...
1355 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateCreated" ) ),
1356 -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
1357 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1358 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DateModified" ) ),
1359 -1, getCppuType( static_cast< const util::DateTime * >( 0 ) ),
1360 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1361 // FIXME: Too expensive for now (?)
1362 // beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "MediaType" ) ),
1363 // -1, getCppuType( static_cast< const rtl::OUString * >( 0 ) ),
1364 // beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1365 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Size" ) ),
1366 -1, getCppuType( static_cast< const sal_Int64 * >( 0 ) ),
1367 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1368 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsReadOnly" ) ),
1369 -1, getCppuBooleanType(),
1370 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1371 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsVolume" ) ),
1372 -1, getCppuBooleanType(),
1373 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1374 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsCompactDisk" ) ),
1375 -1, getCppuBooleanType(),
1376 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1377 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsHidden" ) ),
1378 -1, getCppuBooleanType(),
1379 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY ),
1381 beans::Property( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "SupportsActiveStreaming" ) ),
1382 -1, getCppuBooleanType(),
1383 beans::PropertyAttribute::BOUND | beans::PropertyAttribute::READONLY )
1386 const int nProps = sizeof (aGenericProperties) / sizeof (aGenericProperties[0]);
1388 return uno::Sequence< beans::Property > ( aGenericProperties, nProps );
1392 uno::Sequence< ucb::CommandInfo > Content::getCommands(
1393 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1395 static ucb::CommandInfo aDocumentCommandInfoTable[] = {
1396 // Required commands
1397 ucb::CommandInfo
1398 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getCommandInfo" ) ),
1399 -1, getCppuVoidType() ),
1400 ucb::CommandInfo
1401 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertySetInfo" ) ),
1402 -1, getCppuVoidType() ),
1403 ucb::CommandInfo
1404 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "getPropertyValues" ) ),
1405 -1, getCppuType( static_cast<uno::Sequence< beans::Property > * >( 0 ) ) ),
1406 ucb::CommandInfo
1407 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "setPropertyValues" ) ),
1408 -1, getCppuType( static_cast<uno::Sequence< beans::PropertyValue > * >( 0 ) ) ),
1410 // Optional standard commands
1411 ucb::CommandInfo
1412 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete" ) ),
1413 -1, getCppuBooleanType() ),
1414 ucb::CommandInfo
1415 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert" ) ),
1416 -1, getCppuType( static_cast<ucb::InsertCommandArgument * >( 0 ) ) ),
1417 ucb::CommandInfo
1418 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "open" ) ),
1419 -1, getCppuType( static_cast<ucb::OpenCommandArgument2 * >( 0 ) ) ),
1421 // Folder only
1422 ucb::CommandInfo
1423 ( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "transfer" ) ),
1424 -1, getCppuType( static_cast<ucb::TransferInfo * >( 0 ) ) )
1426 int num = 7;
1428 if ( isFolder( xEnv ) )
1429 num += 1;
1431 return uno::Sequence< ucb::CommandInfo >(aDocumentCommandInfoTable, num );
1434 rtl::OUString
1435 Content::getOUURI ()
1437 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1438 return m_xIdentifier->getContentIdentifier();
1441 rtl::OString
1442 Content::getOURI ()
1444 return rtl::OUStringToOString( getOUURI(), RTL_TEXTENCODING_UTF8 );
1447 char *
1448 Content::getURI ()
1450 return OUStringToGnome( getOUURI() );
1453 void
1454 Content::copyData( uno::Reference< io::XInputStream > xIn,
1455 uno::Reference< io::XOutputStream > xOut )
1457 uno::Sequence< sal_Int8 > theData( TRANSFER_BUFFER_SIZE );
1459 g_return_if_fail( xIn.is() && xOut.is() );
1461 while ( xIn->readBytes( theData, TRANSFER_BUFFER_SIZE ) > 0 )
1462 xOut->writeBytes( theData );
1464 xOut->closeOutput();
1467 // Inherits an authentication context
1468 uno::Reference< io::XInputStream >
1469 Content::createTempStream(
1470 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1471 throw( uno::Exception )
1473 GnomeVFSResult result;
1474 GnomeVFSHandle *handle = NULL;
1475 ::rtl::OString aURI = getOURI();
1476 GnomeVFSOpenMode nOpenMode = GNOME_VFS_OPEN_READ;
1478 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1479 // Something badly wrong happened - can't seek => stream to a temporary file
1480 const rtl::OUString sServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
1481 uno::Reference < io::XOutputStream > xTempOut =
1482 uno::Reference < io::XOutputStream >
1483 ( m_xSMgr->createInstance( sServiceName ), uno::UNO_QUERY );
1485 if ( !xTempOut.is() )
1486 cancelCommandExecution( GNOME_VFS_ERROR_IO, xEnv );
1488 result = gnome_vfs_open( &handle, (const sal_Char *)aURI, nOpenMode );
1489 if (result != GNOME_VFS_OK)
1490 cancelCommandExecution( result, xEnv );
1492 uno::Reference < io::XInputStream > pStream = new ::gvfs::Stream( handle, &m_info, (const sal_Char *)aURI, nOpenMode );
1493 copyData( pStream, xTempOut );
1495 return uno::Reference < io::XInputStream > ( xTempOut, uno::UNO_QUERY );
1498 uno::Reference< io::XStream >
1499 Content::createStream( const uno::Reference< ucb::XCommandEnvironment >& xEnv,
1500 bool bReadWrite )
1501 throw( uno::Exception )
1503 GnomeVFSHandle *handle = NULL;
1504 GnomeVFSResult result;
1505 uno::Reference< io::XStream > xStream;
1507 Authentication aAuth( xEnv );
1508 osl::Guard< osl::Mutex > aGuard( m_aMutex );
1510 getInfo( xEnv );
1511 ::rtl::OString aURI = getOURI();
1513 if ( !bReadWrite && !(m_info.valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) )
1514 return xStream;
1516 GnomeVFSOpenMode nOpenMode = (GnomeVFSOpenMode)(GNOME_VFS_OPEN_READ | GNOME_VFS_OPEN_RANDOM);
1517 if ( bReadWrite )
1518 nOpenMode = (GnomeVFSOpenMode)(nOpenMode | GNOME_VFS_OPEN_WRITE | GNOME_VFS_OPEN_LOCKED);
1520 result = gnome_vfs_open( &handle, (const sal_Char *)aURI, nOpenMode );
1522 if (bReadWrite && (result == GNOME_VFS_ERROR_NOT_FOUND))
1524 int perm;
1525 Authentication aAuth2( xEnv );
1527 perm = ( ( GNOME_VFS_PERM_USER_WRITE | GNOME_VFS_PERM_USER_READ ) |
1528 ( GNOME_VFS_PERM_GROUP_WRITE | GNOME_VFS_PERM_GROUP_READ ) );
1530 result = gnome_vfs_create
1531 ( &handle, (const sal_Char *)aURI, nOpenMode, TRUE, perm );
1534 if (result == GNOME_VFS_ERROR_INVALID_OPEN_MODE ||
1535 result == GNOME_VFS_ERROR_NOT_SUPPORTED ||
1536 result == GNOME_VFS_ERROR_ACCESS_DENIED)
1538 m_bForceReadOnly = sal_True;
1539 return xStream;
1541 else if (result == GNOME_VFS_ERROR_LOCKED )
1542 throwLocked( xEnv );
1543 else if (result != GNOME_VFS_OK)
1544 cancelCommandExecution( result, xEnv );
1546 // Try a seek just to make sure it's Random access: some lie.
1547 result = gnome_vfs_seek( handle, GNOME_VFS_SEEK_START, 0);
1548 if (result == GNOME_VFS_ERROR_NOT_SUPPORTED) {
1549 gnome_vfs_close( handle );
1550 return xStream;
1553 if (result != GNOME_VFS_OK)
1554 cancelCommandExecution( result, xEnv );
1556 if (handle != NULL)
1557 xStream = new ::gvfs::Stream( handle, &m_info, (const sal_Char *)aURI, nOpenMode );
1559 return xStream;
1562 sal_Bool
1563 Content::feedSink( uno::Reference< uno::XInterface > aSink,
1564 const uno::Reference< ucb::XCommandEnvironment >& xEnv )
1566 if ( !aSink.is() )
1567 return sal_False;
1569 uno::Reference< io::XOutputStream > xOut( aSink, uno::UNO_QUERY );
1570 if ( xOut.is() )
1572 #ifdef DEBUG
1573 g_warning( "feedSink(), using XOutputStream" );
1574 #endif
1575 uno::Reference< io::XInputStream > xIn( createStream( xEnv, false ), uno::UNO_QUERY );
1576 if ( !xIn.is() )
1577 xIn = createTempStream( xEnv );
1578 if ( !xIn.is() )
1579 return sal_False;
1581 copyData( xIn, xOut );
1582 return sal_True;
1585 uno::Reference< io::XActiveDataSink > xDataSink( aSink, uno::UNO_QUERY );
1586 if ( xDataSink.is() )
1588 #ifdef DEBUG
1589 g_warning( "feedSink(), using XActiveDataSink" );
1590 #endif
1591 uno::Reference< io::XInputStream > xIn( createStream( xEnv, false ), uno::UNO_QUERY );
1592 if ( !xIn.is() )
1593 xIn = createTempStream( xEnv );
1594 if ( !xIn.is() )
1595 return sal_False;
1597 xDataSink->setInputStream( xIn );
1598 return sal_True;
1601 uno::Reference< io::XActiveDataStreamer > xDataStreamer( aSink, uno::UNO_QUERY );
1602 if ( xDataStreamer.is() )
1604 #ifdef DEBUG
1605 g_warning( "feedSink(), using XActiveDataStreamer" );
1606 #endif
1607 uno::Reference< io::XStream > xStream = createStream( xEnv, true );
1608 if ( !xStream.is() )
1609 return sal_False;
1611 xDataStreamer->setStream( xStream );
1612 return sal_True;
1615 return sal_False;
1618 extern "C" {
1620 #ifndef GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION
1621 # error "We require Gnome VFS 2.6.x to compile (will run fine with < 2.6)"
1622 #endif
1624 static void
1625 vfs_authentication_callback (gconstpointer in_void,
1626 gsize in_size,
1627 gpointer out_void,
1628 gsize out_size,
1629 gpointer callback_data)
1631 task::XInteractionHandler *xIH;
1633 #ifdef DEBUG
1634 g_warning ("Full authentication callback (%p) ...", callback_data);
1635 #endif
1637 if( !( xIH = (task::XInteractionHandler *) callback_data ) )
1638 return;
1640 const GnomeVFSModuleCallbackFullAuthenticationIn *in =
1641 (const GnomeVFSModuleCallbackFullAuthenticationIn *) in_void;
1642 GnomeVFSModuleCallbackFullAuthenticationOut *out =
1643 (GnomeVFSModuleCallbackFullAuthenticationOut *) out_void;
1645 g_return_if_fail (in != NULL && out != NULL);
1646 g_return_if_fail (sizeof (GnomeVFSModuleCallbackFullAuthenticationIn) == in_size &&
1647 sizeof (GnomeVFSModuleCallbackFullAuthenticationOut) == out_size);
1649 #ifdef DEBUG
1650 # define NNIL(x) (x?x:"<Null>")
1651 g_warning (" InComing data 0x%x uri '%s' prot '%s' server '%s' object '%s' "
1652 "port %d auth_t '%s' user '%s' domain '%s' "
1653 "def user '%s', def domain '%s'",
1654 (int) in->flags, NNIL(in->uri), NNIL(in->protocol),
1655 NNIL(in->server), NNIL(in->object),
1656 (int) in->port, NNIL(in->authtype), NNIL(in->username), NNIL(in->domain),
1657 NNIL(in->default_user), NNIL(in->default_domain));
1658 # undef NNIL
1659 #endif
1661 ucbhelper::SimpleAuthenticationRequest::EntityType
1662 eDomain, eUserName, ePassword;
1663 ::rtl::OUString aHostName, aDomain, aUserName, aPassword;
1665 aHostName = GnomeToOUString( in->server );
1667 if (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_DOMAIN)
1669 aDomain = GnomeToOUString( in->domain );
1670 eDomain = ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY;
1671 if (!aDomain.getLength())
1672 aDomain = GnomeToOUString( in->default_domain );
1674 else // no underlying capability to display realm otherwise
1675 eDomain = ucbhelper::SimpleAuthenticationRequest::ENTITY_NA;
1677 aUserName = GnomeToOUString( in->username );
1678 if (!aUserName.getLength())
1679 aUserName = GnomeToOUString( in->default_user );
1680 eUserName = (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME) ?
1681 ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY :
1682 (aUserName.getLength() ?
1683 ucbhelper::SimpleAuthenticationRequest::ENTITY_FIXED :
1684 ucbhelper::SimpleAuthenticationRequest::ENTITY_NA);
1686 // No suggested password.
1687 ePassword = (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_PASSWORD) ?
1688 ucbhelper::SimpleAuthenticationRequest::ENTITY_MODIFY :
1689 ucbhelper::SimpleAuthenticationRequest::ENTITY_FIXED;
1691 // Really, really bad things happen if we don't provide
1692 // the same user/password as was entered last time if
1693 // we failed to authenticate - infinite looping / flickering
1694 // madness etc. [ nice infrastructure ! ]
1695 static rtl::OUString aLastUserName, aLastPassword;
1696 if (in->flags & GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_PREVIOUS_ATTEMPT_FAILED)
1698 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
1699 aUserName = aLastUserName;
1700 aPassword = aLastPassword;
1703 rtl::Reference< ucbhelper::SimpleAuthenticationRequest > xRequest
1704 = new ucbhelper::SimpleAuthenticationRequest (GnomeToOUString(in->uri),
1705 aHostName, eDomain, aDomain,
1706 eUserName, aUserName,
1707 ePassword, aPassword);
1709 xIH->handle( xRequest.get() );
1711 rtl::Reference< ucbhelper::InteractionContinuation > xSelection
1712 = xRequest->getSelection();
1714 if ( xSelection.is() ) {
1715 // Handler handled the request.
1716 uno::Reference< task::XInteractionAbort > xAbort(xSelection.get(), uno::UNO_QUERY );
1717 if ( !xAbort.is() ) {
1718 const rtl::Reference<
1719 ucbhelper::InteractionSupplyAuthentication > & xSupp
1720 = xRequest->getAuthenticationSupplier();
1722 aUserName = xSupp->getUserName();
1723 aDomain = xSupp->getRealm();
1724 aPassword = xSupp->getPassword();
1727 osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
1728 aLastUserName = aUserName;
1729 aLastPassword = aPassword;
1732 out->username = OUStringToGnome( aUserName );
1733 out->domain = OUStringToGnome( aDomain );
1734 out->password = OUStringToGnome( aPassword );
1735 out->save_password = xSupp->getRememberPasswordMode();
1737 #ifdef DEBUG
1738 g_warning ("Got valid user/domain/password '%s' '%s' '%s', %s password",
1739 out->username, out->domain, out->password,
1740 out->save_password ? "save" : "don't save");
1741 #endif
1743 else
1744 out->abort_auth = TRUE;
1746 else
1747 out->abort_auth = TRUE;
1750 static void
1751 vfs_authentication_old_callback (gconstpointer in_void,
1752 gsize in_size,
1753 gpointer out_void,
1754 gsize out_size,
1755 gpointer callback_data)
1757 #ifdef DEBUG
1758 g_warning ("Old authentication callback (%p) [ UNTESTED ] ...", callback_data);
1759 #endif
1760 const GnomeVFSModuleCallbackAuthenticationIn *in =
1761 (const GnomeVFSModuleCallbackAuthenticationIn *) in_void;
1762 GnomeVFSModuleCallbackAuthenticationOut *out =
1763 (GnomeVFSModuleCallbackAuthenticationOut *) out_void;
1765 g_return_if_fail (in != NULL && out != NULL);
1766 g_return_if_fail (sizeof (GnomeVFSModuleCallbackAuthenticationIn) == in_size &&
1767 sizeof (GnomeVFSModuleCallbackAuthenticationOut) == out_size);
1769 GnomeVFSModuleCallbackFullAuthenticationIn mapped_in = {
1770 (GnomeVFSModuleCallbackFullAuthenticationFlags)
1771 (GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_PASSWORD |
1772 GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_USERNAME |
1773 GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_NEED_DOMAIN),
1774 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
1775 GnomeVFSModuleCallbackFullAuthenticationOut mapped_out = { 0, 0, 0, 0, 0, 0, 0, 0 };
1777 // Map the old style input auth. data to the new style structure.
1778 if (in->previous_attempt_failed)
1779 mapped_in.flags = (GnomeVFSModuleCallbackFullAuthenticationFlags)
1780 (mapped_in.flags |
1781 GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION_PREVIOUS_ATTEMPT_FAILED);
1783 GnomeVFSURI *pURI = NULL;
1784 // Urk - parse all this from the URL ...
1785 mapped_in.uri = in->uri;
1786 if (in->uri)
1788 pURI = gnome_vfs_uri_new( in->uri );
1789 mapped_in.protocol = (char *) gnome_vfs_uri_get_scheme (pURI);
1790 mapped_in.server = (char *) gnome_vfs_uri_get_host_name (pURI);
1791 mapped_in.port = gnome_vfs_uri_get_host_port (pURI);
1792 mapped_in.username = (char *) gnome_vfs_uri_get_user_name (pURI);
1794 mapped_in.domain = in->realm;
1795 mapped_in.default_user = mapped_in.username;
1796 mapped_in.default_domain = mapped_in.domain;
1798 vfs_authentication_callback ((gconstpointer) &mapped_in,
1799 sizeof (mapped_in),
1800 (gpointer) &mapped_out,
1801 sizeof (mapped_out),
1802 callback_data);
1804 if (pURI)
1805 gnome_vfs_uri_unref (pURI);
1807 // Map the new style auth. out data to the old style out structure.
1808 out->username = mapped_out.username;
1809 out->password = mapped_out.password;
1810 g_free (mapped_out.domain);
1811 g_free (mapped_out.keyring);
1815 static void
1816 auth_destroy (gpointer data)
1818 task::XInteractionHandler *xIH;
1819 if( ( xIH = ( task::XInteractionHandler * )data ) )
1820 xIH->release();
1823 // This sucks, but gnome-vfs doesn't much like
1824 // repeated set / unsets - so we have to compensate.
1825 GPrivate *auth_queue = NULL;
1827 void auth_queue_destroy( gpointer data )
1829 GList *l;
1830 GQueue *vq = (GQueue *) data;
1832 for (l = vq->head; l; l = l->next)
1833 auth_destroy (l->data);
1834 g_queue_free (vq);
1838 static void
1839 refresh_auth( GQueue *vq )
1841 GList *l;
1843 gnome_vfs_module_callback_pop( GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION );
1844 gnome_vfs_module_callback_pop( GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION );
1846 for (l = vq->head; l; l = l->next) {
1847 if (l->data) {
1848 gnome_vfs_module_callback_push
1849 ( GNOME_VFS_MODULE_CALLBACK_AUTHENTICATION,
1850 vfs_authentication_old_callback, l->data, NULL );
1851 gnome_vfs_module_callback_push
1852 ( GNOME_VFS_MODULE_CALLBACK_FULL_AUTHENTICATION,
1853 vfs_authentication_callback, l->data, NULL );
1854 break;
1859 gvfs::Authentication::Authentication(
1860 const uno::Reference< ucb::XCommandEnvironment > & xEnv )
1862 GQueue *vq;
1863 uno::Reference< task::XInteractionHandler > xIH;
1865 if ( xEnv.is() )
1866 xIH = xEnv->getInteractionHandler();
1868 if ( xIH.is() )
1869 xIH->acquire();
1871 if( !(vq = (GQueue *)g_private_get( auth_queue ) ) ) {
1872 vq = g_queue_new();
1873 g_private_set( auth_queue, vq );
1876 g_queue_push_head( vq, (gpointer) xIH.get() );
1877 refresh_auth( vq );
1880 gvfs::Authentication::~Authentication()
1882 GQueue *vq;
1883 gpointer data;
1885 vq = (GQueue *)g_private_get( auth_queue );
1887 data = g_queue_pop_head( vq );
1888 auth_destroy (data);
1890 refresh_auth( vq );