1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <vcl/dialog.hxx>
22 #include <vcl/edit.hxx>
23 #include <vcl/button.hxx>
24 #include <vcl/msgbox.hxx>
25 #include <vcl/svapp.hxx>
26 #include <osl/security.h>
27 #include <osl/file.hxx>
28 #include <tools/urlobj.hxx>
29 #include <osl/mutex.hxx>
31 #include "runtime.hxx"
33 #include <sal/alloca.h>
36 #include <rtl/byteseq.hxx>
37 #include <rtl/textenc.h>
38 #include <rtl/strbuf.hxx>
39 #include <rtl/ustrbuf.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <comphelper/string.hxx>
44 #include <com/sun/star/bridge/BridgeFactory.hpp>
45 #include <com/sun/star/bridge/XBridge.hpp>
46 #include <com/sun/star/uno/Sequence.hxx>
47 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
48 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
49 #include <com/sun/star/ucb/UniversalContentBroker.hpp>
50 #include <com/sun/star/ucb/XContentProvider.hpp>
51 #include <com/sun/star/ucb/XContentProviderManager.hpp>
52 #include <com/sun/star/io/XInputStream.hpp>
53 #include <com/sun/star/io/XOutputStream.hpp>
54 #include <com/sun/star/io/XStream.hpp>
55 #include <com/sun/star/io/XSeekable.hpp>
57 using namespace com::sun::star::uno
;
58 using namespace com::sun::star::lang
;
59 using namespace com::sun::star::ucb
;
60 using namespace com::sun::star::io
;
61 using namespace com::sun::star::bridge
;
64 #include "sbintern.hxx"
68 class SbiInputDialog
: public ModalDialog
{
73 DECL_LINK( Ok
, Window
* );
74 DECL_LINK( Cancel
, Window
* );
76 SbiInputDialog( Window
*, const OUString
& );
77 const OUString
& GetInput() { return aText
; }
80 SbiInputDialog::SbiInputDialog( Window
* pParent
, const OUString
& rPrompt
)
81 :ModalDialog( pParent
, WB_3DLOOK
| WB_MOVEABLE
| WB_CLOSEABLE
),
82 aInput( this, WB_3DLOOK
| WB_LEFT
| WB_BORDER
),
83 aOk( this ), aCancel( this )
86 aOk
.SetClickHdl( LINK( this, SbiInputDialog
, Ok
) );
87 aCancel
.SetClickHdl( LINK( this, SbiInputDialog
, Cancel
) );
88 SetMapMode( MapMode( MAP_APPFONT
) );
90 Point aPt
= LogicToPixel( Point( 50, 50 ) );
91 Size aSz
= LogicToPixel( Size( 145, 65 ) );
92 SetPosSizePixel( aPt
, aSz
);
93 aPt
= LogicToPixel( Point( 10, 10 ) );
94 aSz
= LogicToPixel( Size( 120, 12 ) );
95 aInput
.SetPosSizePixel( aPt
, aSz
);
96 aPt
= LogicToPixel( Point( 15, 30 ) );
97 aSz
= LogicToPixel( Size( 45, 15) );
98 aOk
.SetPosSizePixel( aPt
, aSz
);
99 aPt
= LogicToPixel( Point( 80, 30 ) );
100 aSz
= LogicToPixel( Size( 45, 15) );
101 aCancel
.SetPosSizePixel( aPt
, aSz
);
108 IMPL_LINK_INLINE_START( SbiInputDialog
, Ok
, Window
*, pWindow
)
112 aText
= aInput
.GetText();
116 IMPL_LINK_INLINE_END( SbiInputDialog
, Ok
, Window
*, pWindow
)
118 IMPL_LINK_INLINE_START( SbiInputDialog
, Cancel
, Window
*, pWindow
)
125 IMPL_LINK_INLINE_END( SbiInputDialog
, Cancel
, Window
*, pWindow
)
128 SbiStream::SbiStream()
133 SbiStream::~SbiStream()
138 // map an SvStream-error to StarBASIC-code
140 void SbiStream::MapError()
144 switch( pStrm
->GetError() )
149 case SVSTREAM_FILE_NOT_FOUND
:
150 nError
= SbERR_FILE_NOT_FOUND
;
152 case SVSTREAM_PATH_NOT_FOUND
:
153 nError
= SbERR_PATH_NOT_FOUND
;
155 case SVSTREAM_TOO_MANY_OPEN_FILES
:
156 nError
= SbERR_TOO_MANY_FILES
;
158 case SVSTREAM_ACCESS_DENIED
:
159 nError
= SbERR_ACCESS_DENIED
;
161 case SVSTREAM_INVALID_PARAMETER
:
162 nError
= SbERR_BAD_ARGUMENT
;
164 case SVSTREAM_OUTOFMEMORY
:
165 nError
= SbERR_NO_MEMORY
;
168 nError
= SbERR_IO_ERROR
;
174 // TODO: Code is copied from daemons2/source/uno/asciiEncoder.cxx
176 OUString
findUserInDescription( const OUString
& aDescription
)
181 sal_Int32 lastIndex
= 0;
185 index
= aDescription
.indexOf((sal_Unicode
) ',', lastIndex
);
186 OUString token
= (index
== -1) ? aDescription
.copy(lastIndex
) : aDescription
.copy(lastIndex
, index
- lastIndex
);
188 lastIndex
= index
+ 1;
190 sal_Int32 eindex
= token
.indexOf((sal_Unicode
)'=');
191 OUString left
= token
.copy(0, eindex
).toAsciiLowerCase().trim();
192 OUString right
= INetURLObject::decode( token
.copy(eindex
+ 1).trim(), '%',
193 INetURLObject::DECODE_WITH_CHARSET
);
206 bool needSecurityRestrictions( void )
208 static bool bNeedInit
= true;
209 static bool bRetVal
= true;
215 // Get system user to compare to portal user
216 oslSecurity aSecurity
= osl_getCurrentSecurity();
217 OUString aSystemUser
;
218 sal_Bool bRet
= osl_getUserName( aSecurity
, &aSystemUser
.pData
);
219 osl_freeSecurityHandle(aSecurity
);
222 // No valid security! -> Secure mode!
226 Reference
< XComponentContext
> xContext
= comphelper::getProcessComponentContext();
227 Reference
< XBridgeFactory2
> xBridgeFac( BridgeFactory::create(xContext
) );
229 Sequence
< Reference
< XBridge
> > aBridgeSeq
= xBridgeFac
->getExistingBridges();
230 sal_Int32 nBridgeCount
= aBridgeSeq
.getLength();
232 if( nBridgeCount
== 0 )
234 // No bridges -> local
239 // Iterate through all bridges to find (portal) user property
240 const Reference
< XBridge
>* pBridges
= aBridgeSeq
.getConstArray();
241 bRetVal
= false; // Now only sal_True if user different from portal user is found
243 for( i
= 0 ; i
< nBridgeCount
; i
++ )
245 const Reference
< XBridge
>& rxBridge
= pBridges
[ i
];
246 OUString aDescription
= rxBridge
->getDescription();
247 OUString aPortalUser
= findUserInDescription( aDescription
);
248 if( !aPortalUser
.isEmpty() )
250 // User Found, compare to system user
251 if( aPortalUser
== aSystemUser
)
253 // Same user -> system security is ok, bRetVal stays FALSE
258 // Different user -> Secure mode!
264 // No user found or PortalUser != SystemUser -> Secure mode! (Keep default value)
270 // Returns sal_True if UNO is available, otherwise the old file
271 // system implementation has to be used
272 // #89378 New semantic: Don't just ask for UNO but for UCB
275 static bool bNeedInit
= true;
276 static bool bRetVal
= true;
281 Reference
< XComponentContext
> xContext
= comphelper::getProcessComponentContext();
284 // No service manager at all
289 Reference
< XUniversalContentBroker
> xManager
= UniversalContentBroker::create(xContext
);
291 if ( !( xManager
->queryContentProvider( OUString("file:///" ) ).is() ) )
303 class OslStream
: public SvStream
308 OslStream( const OUString
& rName
, short nStrmMode
);
310 virtual sal_uIntPtr
GetData( void* pData
, sal_uIntPtr nSize
);
311 virtual sal_uIntPtr
PutData( const void* pData
, sal_uIntPtr nSize
);
312 virtual sal_uIntPtr
SeekPos( sal_uIntPtr nPos
);
313 virtual void FlushData();
314 virtual void SetSize( sal_uIntPtr nSize
);
317 OslStream::OslStream( const OUString
& rName
, short nStrmMode
)
322 if( (nStrmMode
& (STREAM_READ
| STREAM_WRITE
)) == (STREAM_READ
| STREAM_WRITE
) )
324 nFlags
= osl_File_OpenFlag_Read
| osl_File_OpenFlag_Write
;
326 else if( nStrmMode
& STREAM_WRITE
)
328 nFlags
= osl_File_OpenFlag_Write
;
330 else //if( nStrmMode & STREAM_READ )
332 nFlags
= osl_File_OpenFlag_Read
;
335 osl::FileBase::RC nRet
= maFile
.open( nFlags
);
336 if( nRet
== osl::FileBase::E_NOENT
&& nFlags
!= osl_File_OpenFlag_Read
)
338 nFlags
|= osl_File_OpenFlag_Create
;
339 nRet
= maFile
.open( nFlags
);
342 if( nRet
!= osl::FileBase::E_None
)
344 SetError( ERRCODE_IO_GENERAL
);
349 OslStream::~OslStream()
354 sal_uIntPtr
OslStream::GetData( void* pData
, sal_uIntPtr nSize
)
356 sal_uInt64 nBytesRead
= nSize
;
357 maFile
.read( pData
, nBytesRead
, nBytesRead
);
358 return (sal_uIntPtr
)nBytesRead
;
361 sal_uIntPtr
OslStream::PutData( const void* pData
, sal_uIntPtr nSize
)
363 sal_uInt64 nBytesWritten
;
364 maFile
.write( pData
, (sal_uInt64
)nSize
, nBytesWritten
);
365 return (sal_uIntPtr
)nBytesWritten
;
368 sal_uIntPtr
OslStream::SeekPos( sal_uIntPtr nPos
)
370 ::osl::FileBase::RC rc
= ::osl::FileBase::E_None
;
371 if( nPos
== STREAM_SEEK_TO_END
)
373 rc
= maFile
.setPos( osl_Pos_End
, 0 );
377 rc
= maFile
.setPos( osl_Pos_Absolut
, (sal_uInt64
)nPos
);
379 OSL_VERIFY(rc
== ::osl::FileBase::E_None
);
380 sal_uInt64
nRealPos(0);
381 maFile
.getPos( nRealPos
);
382 return sal::static_int_cast
<sal_uIntPtr
>(nRealPos
);
385 void OslStream::FlushData()
389 void OslStream::SetSize( sal_uIntPtr nSize
)
391 maFile
.setSize( (sal_uInt64
)nSize
);
395 class UCBStream
: public SvStream
397 Reference
< XInputStream
> xIS
;
398 Reference
< XStream
> xS
;
399 Reference
< XSeekable
> xSeek
;
401 UCBStream( Reference
< XInputStream
> & xIS
);
402 UCBStream( Reference
< XStream
> & xS
);
404 virtual sal_uIntPtr
GetData( void* pData
, sal_uIntPtr nSize
);
405 virtual sal_uIntPtr
PutData( const void* pData
, sal_uIntPtr nSize
);
406 virtual sal_uIntPtr
SeekPos( sal_uIntPtr nPos
);
407 virtual void FlushData();
408 virtual void SetSize( sal_uIntPtr nSize
);
411 UCBStream::UCBStream( Reference
< XInputStream
> & rStm
)
413 , xSeek( rStm
, UNO_QUERY
)
417 UCBStream::UCBStream( Reference
< XStream
> & rStm
)
419 , xSeek( rStm
, UNO_QUERY
)
424 UCBStream::~UCBStream()
434 Reference
< XInputStream
> xIS_
= xS
->getInputStream();
441 catch(const Exception
& )
443 SetError( ERRCODE_IO_GENERAL
);
447 sal_uIntPtr
UCBStream::GetData( void* pData
, sal_uIntPtr nSize
)
451 Reference
< XInputStream
> xISFromS
;
454 Sequence
<sal_Int8
> aData
;
455 nSize
= xIS
->readBytes( aData
, nSize
);
456 memcpy( pData
, aData
.getConstArray(), nSize
);
459 else if( xS
.is() && (xISFromS
= xS
->getInputStream()).is() )
461 Sequence
<sal_Int8
> aData
;
462 nSize
= xISFromS
->readBytes( aData
, nSize
);
463 memcpy(pData
, aData
.getConstArray(), nSize
);
468 SetError( ERRCODE_IO_GENERAL
);
471 catch(const Exception
& )
473 SetError( ERRCODE_IO_GENERAL
);
478 sal_uIntPtr
UCBStream::PutData( const void* pData
, sal_uIntPtr nSize
)
482 Reference
< XOutputStream
> xOSFromS
;
483 if( xS
.is() && (xOSFromS
= xS
->getOutputStream()).is() )
485 Sequence
<sal_Int8
> aData( (const sal_Int8
*)pData
, nSize
);
486 xOSFromS
->writeBytes( aData
);
491 SetError( ERRCODE_IO_GENERAL
);
494 catch(const Exception
& )
496 SetError( ERRCODE_IO_GENERAL
);
501 sal_uIntPtr
UCBStream::SeekPos( sal_uIntPtr nPos
)
507 sal_uIntPtr nLen
= sal::static_int_cast
<sal_uIntPtr
>( xSeek
->getLength() );
517 SetError( ERRCODE_IO_GENERAL
);
520 catch(const Exception
& )
522 SetError( ERRCODE_IO_GENERAL
);
527 void UCBStream::FlushData()
531 Reference
< XOutputStream
> xOSFromS
;
532 if( xS
.is() && (xOSFromS
= xS
->getOutputStream()).is() )
538 SetError( ERRCODE_IO_GENERAL
);
541 catch(const Exception
& )
543 SetError( ERRCODE_IO_GENERAL
);
547 void UCBStream::SetSize( sal_uIntPtr nSize
)
551 SAL_WARN("basic", "UCBStream::SetSize not allowed to call from basic" );
552 SetError( ERRCODE_IO_GENERAL
);
556 SbError
SbiStream::Open
557 ( short nCh
, const OString
& rName
, short nStrmMode
, short nFlags
, short nL
)
563 nExpandOnWriteTo
= 0;
564 if( ( nStrmMode
& ( STREAM_READ
|STREAM_WRITE
) ) == STREAM_READ
)
566 nStrmMode
|= STREAM_NOCREATE
;
568 OUString
aStr(OStringToOUString(rName
, osl_getThreadTextEncoding()));
569 OUString aNameStr
= getFullPath( aStr
);
573 Reference
< XSimpleFileAccess3
> xSFI( SimpleFileAccess::create( comphelper::getProcessComponentContext() ) );
577 // #??? For write access delete file if it already exists (not for appending)
578 if( (nStrmMode
& STREAM_WRITE
) != 0 && !IsAppend() && !IsBinary() &&
579 xSFI
->exists( aNameStr
) && !xSFI
->isFolder( aNameStr
) )
581 xSFI
->kill( aNameStr
);
584 if( (nStrmMode
& (STREAM_READ
| STREAM_WRITE
)) == (STREAM_READ
| STREAM_WRITE
) )
586 Reference
< XStream
> xIS
= xSFI
->openFileReadWrite( aNameStr
);
587 pStrm
= new UCBStream( xIS
);
589 else if( nStrmMode
& STREAM_WRITE
)
591 Reference
< XStream
> xIS
= xSFI
->openFileReadWrite( aNameStr
);
592 pStrm
= new UCBStream( xIS
);
594 else //if( nStrmMode & STREAM_READ )
596 Reference
< XInputStream
> xIS
= xSFI
->openFileRead( aNameStr
);
597 pStrm
= new UCBStream( xIS
);
601 catch(const Exception
& )
603 nError
= ERRCODE_IO_GENERAL
;
609 pStrm
= new OslStream( aNameStr
, nStrmMode
);
613 pStrm
->Seek( STREAM_SEEK_TO_END
);
618 delete pStrm
, pStrm
= NULL
;
623 SbError
SbiStream::Close()
635 SbError
SbiStream::Read(OString
& rBuf
, sal_uInt16 n
, bool bForceReadingPerByte
)
637 nExpandOnWriteTo
= 0;
638 if( !bForceReadingPerByte
&& IsText() )
640 pStrm
->ReadLine(rBuf
);
651 return nError
= SbERR_BAD_RECORD_LENGTH
;
653 OStringBuffer
aBuffer(read_uInt8s_ToOString(*pStrm
, n
));
654 //Pad it out with ' ' to the requested length on short read
655 sal_Int32 nRequested
= sal::static_int_cast
<sal_Int32
>(n
);
656 comphelper::string::padToLength(aBuffer
, nRequested
, ' ');
657 rBuf
= aBuffer
.makeStringAndClear();
660 if( !nError
&& pStrm
->IsEof() )
662 nError
= SbERR_READ_PAST_EOF
;
667 SbError
SbiStream::Read( char& ch
)
669 nExpandOnWriteTo
= 0;
673 aLine
= aLine
+ OString('\n');
676 aLine
= aLine
.copy(1);
680 void SbiStream::ExpandFile()
682 if ( nExpandOnWriteTo
)
684 sal_uIntPtr nCur
= pStrm
->Seek(STREAM_SEEK_TO_END
);
685 if( nCur
< nExpandOnWriteTo
)
687 sal_uIntPtr nDiff
= nExpandOnWriteTo
- nCur
;
696 pStrm
->Seek( nExpandOnWriteTo
);
698 nExpandOnWriteTo
= 0;
704 void WriteLines(SvStream
&rStream
, const OString
& rStr
)
706 OString
aStr(convertLineEnd(rStr
, rStream
.GetLineDelimiter()) );
707 write_uInt8s_FromOString(rStream
, aStr
);
712 SbError
SbiStream::Write( const OString
& rBuf
, sal_uInt16 n
)
717 pStrm
->Seek( STREAM_SEEK_TO_END
);
721 aLine
= aLine
+ rBuf
;
722 // Get it out, if the end is an LF, but strip CRLF before,
723 // because the SvStrm adds a CRLF!
724 sal_Int32 nLineLen
= aLine
.getLength();
725 if (nLineLen
&& aLine
[--nLineLen
] == 0x0A)
727 aLine
= aLine
.copy(0, nLineLen
);
728 if (nLineLen
&& aLine
[--nLineLen
] == 0x0D)
730 aLine
= aLine
.copy(0, nLineLen
);
732 WriteLines(*pStrm
, aLine
);
744 return nError
= SbERR_BAD_RECORD_LENGTH
;
746 pStrm
->Write(rBuf
.getStr(), n
);
754 SbiIoSystem
* SbGetIoSystem()
756 SbiInstance
* pInst
= GetSbData()->pInst
;
757 return pInst
? pInst
->GetIoSystem() : NULL
;
761 SbiIoSystem::SbiIoSystem()
763 for( short i
= 0; i
< CHANNELS
; i
++ )
771 SbiIoSystem::~SbiIoSystem()
776 SbError
SbiIoSystem::GetError()
778 SbError n
= nError
; nError
= 0;
782 void SbiIoSystem::Open(short nCh
, const OString
& rName
, short nMode
, short nFlags
, short nLen
)
785 if( nCh
>= CHANNELS
|| !nCh
)
787 nError
= SbERR_BAD_CHANNEL
;
789 else if( pChan
[ nCh
] )
791 nError
= SbERR_FILE_ALREADY_OPEN
;
795 pChan
[ nCh
] = new SbiStream
;
796 nError
= pChan
[ nCh
]->Open( nCh
, rName
, nMode
, nFlags
, nLen
);
799 delete pChan
[ nCh
], pChan
[ nCh
] = NULL
;
806 void SbiIoSystem::Close()
810 nError
= SbERR_BAD_CHANNEL
;
812 else if( !pChan
[ nChan
] )
814 nError
= SbERR_BAD_CHANNEL
;
818 nError
= pChan
[ nChan
]->Close();
819 delete pChan
[ nChan
];
820 pChan
[ nChan
] = NULL
;
826 void SbiIoSystem::Shutdown()
828 for( short i
= 1; i
< CHANNELS
; i
++ )
832 SbError n
= pChan
[ i
]->Close();
842 // anything left to PRINT?
843 if( !aOut
.isEmpty() )
845 OUString
aOutStr(OStringToOUString(aOut
, osl_getThreadTextEncoding()));
847 Window
* pParent
= Application::GetDefDialogParent();
848 MessBox( pParent
, WinBits( WB_OK
), OUString(), aOutStr
).Execute();
850 MessBox( GetpApp()->GetDefDialogParent(), WinBits( WB_OK
), OUString(), aOutStr
).Execute();
857 void SbiIoSystem::Read(OString
& rBuf
, short n
)
863 else if( !pChan
[ nChan
] )
865 nError
= SbERR_BAD_CHANNEL
;
869 nError
= pChan
[ nChan
]->Read( rBuf
, n
);
873 char SbiIoSystem::Read()
881 aIn
= aIn
+ OString('\n');
886 else if( !pChan
[ nChan
] )
888 nError
= SbERR_BAD_CHANNEL
;
892 nError
= pChan
[ nChan
]->Read( ch
);
897 void SbiIoSystem::Write(const OString
& rBuf
, short n
)
903 else if( !pChan
[ nChan
] )
905 nError
= SbERR_BAD_CHANNEL
;
909 nError
= pChan
[ nChan
]->Write( rBuf
, n
);
913 // nChannel == 0..CHANNELS-1
915 SbiStream
* SbiIoSystem::GetStream( short nChannel
) const
918 if( nChannel
>= 0 && nChannel
< CHANNELS
)
920 pRet
= pChan
[ nChannel
];
925 void SbiIoSystem::CloseAll(void)
927 for( short i
= 1; i
< CHANNELS
; i
++ )
931 SbError n
= pChan
[ i
]->Close();
942 /***************************************************************************
946 ***************************************************************************/
949 void SbiIoSystem::ReadCon(OString
& rIn
)
951 OUString
aPromptStr(OStringToOUString(aPrompt
, osl_getThreadTextEncoding()));
952 SbiInputDialog
aDlg( NULL
, aPromptStr
);
955 rIn
= OUStringToOString(aDlg
.GetInput(), osl_getThreadTextEncoding());
959 nError
= SbERR_USER_ABORT
;
964 // output of a MessageBox, if theres a CR in the console-buffer
966 void SbiIoSystem::WriteCon(const OString
& rText
)
969 sal_Int32 n1
= aOut
.indexOf('\n');
970 sal_Int32 n2
= aOut
.indexOf('\r');
971 if( n1
!= -1 || n2
!= -1 )
985 OString
s(aOut
.copy(0, n1
));
986 aOut
= aOut
.copy(n1
);
987 while (aOut
[0] == '\n' || aOut
[0] == '\r')
991 OUString
aStr(OStringToOUString(s
, osl_getThreadTextEncoding()));
993 SolarMutexGuard aSolarGuard
;
994 if( !MessBox( GetpApp()->GetDefDialogParent(),
995 WinBits( WB_OK_CANCEL
| WB_DEF_OK
),
996 OUString(), aStr
).Execute() )
998 nError
= SbERR_USER_ABORT
;
1004 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */