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