xref: /AOO41X/main/basic/source/runtime/iosys.cxx (revision 0848378beb0d0fcd9a9bf3cafa6204dbc20d39f7)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basic.hxx"
26 #include <vcl/dialog.hxx>
27 #include <vcl/edit.hxx>
28 #ifndef _SV_BUTTON_HXX //autogen
29 #include <vcl/button.hxx>
30 #endif
31 #include <vcl/msgbox.hxx>
32 #include <vcl/svapp.hxx>
33 #include <osl/security.h>
34 #include <osl/file.hxx>
35 #include <tools/urlobj.hxx>
36 #include <vos/mutex.hxx>
37 
38 #include "runtime.hxx"
39 
40 #ifdef _USE_UNO
41 
42 // <-- encoding
43 #include <sal/alloca.h>
44 
45 #include <ctype.h>
46 #include <rtl/byteseq.hxx>
47 #include <rtl/textenc.h>
48 #include <rtl/ustrbuf.hxx>
49 #include <rtl/textenc.h>
50 #include <rtl/ustrbuf.hxx>
51 // encoding -->
52 #include <comphelper/processfactory.hxx>
53 
54 #include <com/sun/star/uno/Sequence.hxx>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
57 #include <com/sun/star/ucb/XContentProvider.hpp>
58 #include <com/sun/star/ucb/XContentProviderManager.hpp>
59 #include <com/sun/star/io/XInputStream.hpp>
60 #include <com/sun/star/io/XOutputStream.hpp>
61 #include <com/sun/star/io/XStream.hpp>
62 #include <com/sun/star/io/XSeekable.hpp>
63 #include <com/sun/star/bridge/XBridge.hpp>
64 #include <com/sun/star/bridge/XBridgeFactory.hpp>
65 
66 using namespace comphelper;
67 using namespace osl;
68 using namespace com::sun::star::uno;
69 using namespace com::sun::star::lang;
70 using namespace com::sun::star::ucb;
71 using namespace com::sun::star::io;
72 using namespace com::sun::star::bridge;
73 
74 #endif /* _USE_UNO */
75 
76 #include "iosys.hxx"
77 #include "sbintern.hxx"
78 
79 // Der Input-Dialog:
80 
81 class SbiInputDialog : public ModalDialog {
82     Edit aInput;
83     OKButton aOk;
84     CancelButton aCancel;
85     String aText;
86     DECL_LINK( Ok, Window * );
87     DECL_LINK( Cancel, Window * );
88 public:
89     SbiInputDialog( Window*, const String& );
GetInput()90     const String& GetInput() { return aText; }
91 };
92 
SbiInputDialog(Window * pParent,const String & rPrompt)93 SbiInputDialog::SbiInputDialog( Window* pParent, const String& rPrompt )
94             :ModalDialog( pParent, WB_3DLOOK | WB_MOVEABLE | WB_CLOSEABLE ),
95              aInput( this, WB_3DLOOK | WB_LEFT | WB_BORDER ),
96              aOk( this ), aCancel( this )
97 {
98     SetText( rPrompt );
99     aOk.SetClickHdl( LINK( this, SbiInputDialog, Ok ) );
100     aCancel.SetClickHdl( LINK( this, SbiInputDialog, Cancel ) );
101     SetMapMode( MapMode( MAP_APPFONT ) );
102 
103     Point aPt = LogicToPixel( Point( 50, 50 ) );
104     Size  aSz = LogicToPixel( Size( 145, 65 ) );
105     SetPosSizePixel( aPt, aSz );
106     aPt = LogicToPixel( Point( 10, 10 ) );
107     aSz = LogicToPixel( Size( 120, 12 ) );
108     aInput.SetPosSizePixel( aPt, aSz );
109     aPt = LogicToPixel( Point( 15, 30 ) );
110     aSz = LogicToPixel( Size( 45, 15) );
111     aOk.SetPosSizePixel( aPt, aSz );
112     aPt = LogicToPixel( Point( 80, 30 ) );
113     aSz = LogicToPixel( Size( 45, 15) );
114     aCancel.SetPosSizePixel( aPt, aSz );
115 
116     aInput.Show();
117     aOk.Show();
118     aCancel.Show();
119 }
120 
IMPL_LINK_INLINE_START(SbiInputDialog,Ok,Window *,pWindow)121 IMPL_LINK_INLINE_START( SbiInputDialog, Ok, Window *, pWindow )
122 {
123     (void)pWindow;
124 
125     aText = aInput.GetText();
126     EndDialog( 1 );
127     return 0;
128 }
IMPL_LINK_INLINE_END(SbiInputDialog,Ok,Window *,pWindow)129 IMPL_LINK_INLINE_END( SbiInputDialog, Ok, Window *, pWindow )
130 
131 IMPL_LINK_INLINE_START( SbiInputDialog, Cancel, Window *, pWindow )
132 {
133     (void)pWindow;
134 
135     EndDialog( 0 );
136     return 0;
137 }
IMPL_LINK_INLINE_END(SbiInputDialog,Cancel,Window *,pWindow)138 IMPL_LINK_INLINE_END( SbiInputDialog, Cancel, Window *, pWindow )
139 
140 //////////////////////////////////////////////////////////////////////////
141 
142 SbiStream::SbiStream()
143     : pStrm( 0 )
144 {
145 }
146 
~SbiStream()147 SbiStream::~SbiStream()
148 {
149     delete pStrm;
150 }
151 
152 // Ummappen eines SvStream-Fehlers auf einen StarBASIC-Code
153 
MapError()154 void SbiStream::MapError()
155 {
156     if( pStrm )
157      switch( pStrm->GetError() )
158      {
159         case SVSTREAM_OK:
160             nError = 0; break;
161         case SVSTREAM_FILE_NOT_FOUND:
162             nError = SbERR_FILE_NOT_FOUND; break;
163         case SVSTREAM_PATH_NOT_FOUND:
164             nError = SbERR_PATH_NOT_FOUND; break;
165         case SVSTREAM_TOO_MANY_OPEN_FILES:
166             nError = SbERR_TOO_MANY_FILES; break;
167         case SVSTREAM_ACCESS_DENIED:
168             nError = SbERR_ACCESS_DENIED; break;
169         case SVSTREAM_INVALID_PARAMETER:
170             nError = SbERR_BAD_ARGUMENT; break;
171         case SVSTREAM_OUTOFMEMORY:
172             nError = SbERR_NO_MEMORY; break;
173         default:
174             nError = SbERR_IO_ERROR; break;
175     }
176 }
177 
178 #ifdef _USE_UNO
179 
180 // TODO: Code is copied from daemons2/source/uno/asciiEncoder.cxx
181 
findUserInDescription(const::rtl::OUString & aDescription)182 ::rtl::OUString findUserInDescription( const ::rtl::OUString& aDescription )
183 {
184     ::rtl::OUString user;
185 
186     sal_Int32 index;
187     sal_Int32 lastIndex = 0;
188 
189     do
190     {
191         index = aDescription.indexOf((sal_Unicode) ',', lastIndex);
192         ::rtl::OUString token = (index == -1) ? aDescription.copy(lastIndex) : aDescription.copy(lastIndex, index - lastIndex);
193 
194         lastIndex = index + 1;
195 
196         sal_Int32 eindex = token.indexOf((sal_Unicode)'=');
197         ::rtl::OUString left = token.copy(0, eindex).toAsciiLowerCase().trim();
198         ::rtl::OUString right = INetURLObject::decode( token.copy(eindex + 1).trim(), '%',
199                             INetURLObject::DECODE_WITH_CHARSET );
200 
201         if(left.equals(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("user"))))
202         {
203             user = right;
204             break;
205         }
206     }
207     while(index != -1);
208 
209     return user;
210 }
211 
212 #endif
213 
214 
215 // Hack for #83750
216 sal_Bool runsInSetup( void );
217 
needSecurityRestrictions(void)218 sal_Bool needSecurityRestrictions( void )
219 {
220 #ifdef _USE_UNO
221     static sal_Bool bNeedInit = sal_True;
222     static sal_Bool bRetVal = sal_True;
223 
224     if( bNeedInit )
225     {
226         // Hack for #83750, use internal flag until
227         // setup provides own service manager
228         if( runsInSetup() )
229         {
230             // Setup is not critical
231             bRetVal = sal_False;
232             return bRetVal;
233         }
234 
235         bNeedInit = sal_False;
236 
237         // Get system user to compare to portal user
238         oslSecurity aSecurity = osl_getCurrentSecurity();
239         ::rtl::OUString aSystemUser;
240         sal_Bool bRet = osl_getUserName( aSecurity, &aSystemUser.pData );
241         if( !bRet )
242         {
243             // No valid security! -> Secure mode!
244             return sal_True;
245         }
246 
247         Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
248         if( !xSMgr.is() )
249             return sal_True;
250         Reference< XBridgeFactory > xBridgeFac( xSMgr->createInstance
251             ( ::rtl::OUString::createFromAscii( "com.sun.star.bridge.BridgeFactory" ) ), UNO_QUERY );
252 
253         Sequence< Reference< XBridge > > aBridgeSeq;
254         sal_Int32 nBridgeCount = 0;
255         if( xBridgeFac.is() )
256         {
257             aBridgeSeq = xBridgeFac->getExistingBridges();
258             nBridgeCount = aBridgeSeq.getLength();
259         }
260 
261         if( nBridgeCount == 0 )
262         {
263             // No bridges -> local
264             bRetVal = sal_False;
265             return bRetVal;
266         }
267 
268         // Iterate through all bridges to find (portal) user property
269         const Reference< XBridge >* pBridges = aBridgeSeq.getConstArray();
270         bRetVal = sal_False;    // Now only sal_True if user different from portal user is found
271         sal_Int32 i;
272         for( i = 0 ; i < nBridgeCount ; i++ )
273         {
274             const Reference< XBridge >& rxBridge = pBridges[ i ];
275             ::rtl::OUString aDescription = rxBridge->getDescription();
276             ::rtl::OUString aPortalUser = findUserInDescription( aDescription );
277             if( !aPortalUser.isEmpty() )
278             {
279                 // User Found, compare to system user
280                 if( aPortalUser == aSystemUser )
281                 {
282                     // Same user -> system security is ok, bRetVal stays FALSE
283                     break;
284                 }
285                 else
286                 {
287                     // Different user -> Secure mode!
288                     bRetVal = sal_True;
289                     break;
290                 }
291             }
292         }
293         // No user found or PortalUser != SystemUser -> Secure mode! (Keep default value)
294     }
295 
296     return bRetVal;
297 #else
298     return sal_False;
299 #endif
300 }
301 
302 // Returns sal_True if UNO is available, otherwise the old file
303 // system implementation has to be used
304 // #89378 New semantic: Don't just ask for UNO but for UCB
hasUno(void)305 sal_Bool hasUno( void )
306 {
307 #ifdef _USE_UNO
308     static sal_Bool bNeedInit = sal_True;
309     static sal_Bool bRetVal = sal_True;
310 
311     if( bNeedInit )
312     {
313         bNeedInit = sal_False;
314         Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
315         if( !xSMgr.is() )
316         {
317             // No service manager at all
318             bRetVal = sal_False;
319         }
320         else
321         {
322             Reference< XContentProviderManager > xManager( xSMgr->createInstance( ::rtl::OUString::createFromAscii
323                     ( "com.sun.star.ucb.UniversalContentBroker" ) ), UNO_QUERY );
324 
325             if ( !( xManager.is() && xManager->queryContentProvider( ::rtl::OUString::createFromAscii( "file:///" ) ).is() ) )
326             {
327                 // No UCB
328                 bRetVal = sal_False;
329             }
330         }
331     }
332     return bRetVal;
333 #else
334     return sal_False;
335 #endif
336 }
337 
338 
339 
340 #ifndef _OLD_FILE_IMPL
341 
342 class OslStream : public SvStream
343 {
344     File maFile;
345     short mnStrmMode;
346 
347 public:
348                     OslStream( const String& rName, short nStrmMode );
349                     ~OslStream();
350     virtual sal_uIntPtr GetData( void* pData, sal_uIntPtr nSize );
351     virtual sal_uIntPtr PutData( const void* pData, sal_uIntPtr nSize );
352     virtual sal_uIntPtr SeekPos( sal_uIntPtr nPos );
353     virtual void    FlushData();
354     virtual void    SetSize( sal_uIntPtr nSize );
355 };
356 
OslStream(const String & rName,short nStrmMode)357 OslStream::OslStream( const String& rName, short nStrmMode )
358     : maFile( rName )
359     , mnStrmMode( nStrmMode )
360 {
361     sal_uInt32 nFlags;
362 
363     if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
364     {
365         nFlags = OpenFlag_Read | OpenFlag_Write;
366     }
367     else if( nStrmMode & STREAM_WRITE )
368     {
369         nFlags = OpenFlag_Write;
370     }
371     else //if( nStrmMode & STREAM_READ )
372     {
373         nFlags = OpenFlag_Read;
374     }
375 
376     FileBase::RC nRet = maFile.open( nFlags );
377     if( nRet == FileBase::E_NOENT && nFlags != OpenFlag_Read )
378     {
379         nFlags |= OpenFlag_Create;
380         nRet = maFile.open( nFlags );
381     }
382 
383     if( nRet != FileBase::E_None )
384     {
385         SetError( ERRCODE_IO_GENERAL );
386     }
387 }
388 
389 
~OslStream()390 OslStream::~OslStream()
391 {
392     maFile.close();
393 }
394 
GetData(void * pData,sal_uIntPtr nSize)395 sal_uIntPtr OslStream::GetData( void* pData, sal_uIntPtr nSize )
396 {
397     sal_uInt64 nBytesRead = nSize;
398     FileBase::RC nRet = FileBase::E_None;
399     nRet = maFile.read( pData, nBytesRead, nBytesRead );
400     return (sal_uIntPtr)nBytesRead;
401 }
402 
PutData(const void * pData,sal_uIntPtr nSize)403 sal_uIntPtr OslStream::PutData( const void* pData, sal_uIntPtr nSize )
404 {
405     sal_uInt64 nBytesWritten;
406     FileBase::RC nRet = FileBase::E_None;
407     nRet = maFile.write( pData, (sal_uInt64)nSize, nBytesWritten );
408     return (sal_uIntPtr)nBytesWritten;
409 }
410 
SeekPos(sal_uIntPtr nPos)411 sal_uIntPtr OslStream::SeekPos( sal_uIntPtr nPos )
412 {
413     FileBase::RC nRet;
414     if( nPos == STREAM_SEEK_TO_END )
415     {
416         nRet = maFile.setPos( Pos_End, 0 );
417     }
418     else
419     {
420         nRet = maFile.setPos( Pos_Absolut, (sal_uInt64)nPos );
421     }
422     sal_uInt64 nRealPos;
423     nRet = maFile.getPos( nRealPos );
424     return sal::static_int_cast<sal_uIntPtr>(nRealPos);
425 }
426 
FlushData()427 void OslStream::FlushData()
428 {
429 }
430 
SetSize(sal_uIntPtr nSize)431 void OslStream::SetSize( sal_uIntPtr nSize )
432 {
433     FileBase::RC nRet = FileBase::E_None;
434     nRet = maFile.setSize( (sal_uInt64)nSize );
435 }
436 
437 #endif
438 
439 
440 #ifdef _USE_UNO
441 
442 class UCBStream : public SvStream
443 {
444     Reference< XInputStream >   xIS;
445     Reference< XOutputStream >  xOS;
446     Reference< XStream >        xS;
447     Reference< XSeekable >      xSeek;
448 public:
449                     UCBStream( Reference< XInputStream > & xIS );
450                     UCBStream( Reference< XOutputStream > & xOS );
451                     UCBStream( Reference< XStream > & xS );
452                     ~UCBStream();
453     virtual sal_uIntPtr GetData( void* pData, sal_uIntPtr nSize );
454     virtual sal_uIntPtr PutData( const void* pData, sal_uIntPtr nSize );
455     virtual sal_uIntPtr SeekPos( sal_uIntPtr nPos );
456     virtual void    FlushData();
457     virtual void    SetSize( sal_uIntPtr nSize );
458 };
459 
460 /*
461 sal_uIntPtr UCBErrorToSvStramError( ucb::IOErrorCode nError )
462 {
463     sal_uIntPtr eReturn = ERRCODE_IO_GENERAL;
464     switch( nError )
465     {
466         case ucb::IOErrorCode_ABORT:                eReturn = SVSTREAM_GENERALERROR; break;
467         case ucb::IOErrorCode_NOT_EXISTING:         eReturn = SVSTREAM_FILE_NOT_FOUND; break;
468         case ucb::IOErrorCode_NOT_EXISTING_PATH:    eReturn = SVSTREAM_PATH_NOT_FOUND; break;
469         case ucb::IOErrorCode_OUT_OF_FILE_HANDLES:  eReturn = SVSTREAM_TOO_MANY_OPEN_FILES; break;
470         case ucb::IOErrorCode_ACCESS_DENIED:        eReturn = SVSTREAM_ACCESS_DENIED; break;
471         case ucb::IOErrorCode_LOCKING_VIOLATION:    eReturn = SVSTREAM_SHARING_VIOLATION; break;
472 
473         case ucb::IOErrorCode_INVALID_ACCESS:       eReturn = SVSTREAM_INVALID_ACCESS; break;
474         case ucb::IOErrorCode_CANT_CREATE:          eReturn = SVSTREAM_CANNOT_MAKE; break;
475         case ucb::IOErrorCode_INVALID_PARAMETER:    eReturn = SVSTREAM_INVALID_PARAMETER; break;
476 
477         case ucb::IOErrorCode_CANT_READ:            eReturn = SVSTREAM_READ_ERROR; break;
478         case ucb::IOErrorCode_CANT_WRITE:           eReturn = SVSTREAM_WRITE_ERROR; break;
479         case ucb::IOErrorCode_CANT_SEEK:            eReturn = SVSTREAM_SEEK_ERROR; break;
480         case ucb::IOErrorCode_CANT_TELL:            eReturn = SVSTREAM_TELL_ERROR; break;
481 
482         case ucb::IOErrorCode_OUT_OF_MEMORY:        eReturn = SVSTREAM_OUTOFMEMORY; break;
483 
484         case SVSTREAM_FILEFORMAT_ERROR:             eReturn = SVSTREAM_FILEFORMAT_ERROR; break;
485         case ucb::IOErrorCode_WRONG_VERSION:        eReturn = SVSTREAM_WRONGVERSION;
486         case ucb::IOErrorCode_OUT_OF_DISK_SPACE:    eReturn = SVSTREAM_DISK_FULL; break;
487 
488         case ucb::IOErrorCode_BAD_CRC:              eReturn = ERRCODE_IO_BADCRC; break;
489     }
490     return eReturn;
491 }
492 */
493 
UCBStream(Reference<XInputStream> & rStm)494 UCBStream::UCBStream( Reference< XInputStream > & rStm )
495     : xIS( rStm )
496     , xSeek( rStm, UNO_QUERY )
497 {
498 }
499 
UCBStream(Reference<XOutputStream> & rStm)500 UCBStream::UCBStream( Reference< XOutputStream > & rStm )
501     : xOS( rStm )
502     , xSeek( rStm, UNO_QUERY )
503 {
504 }
505 
UCBStream(Reference<XStream> & rStm)506 UCBStream::UCBStream( Reference< XStream > & rStm )
507     : xS( rStm )
508     , xSeek( rStm, UNO_QUERY )
509 {
510 }
511 
512 
~UCBStream()513 UCBStream::~UCBStream()
514 {
515     try
516     {
517         if( xIS.is() )
518             xIS->closeInput();
519         else if( xOS.is() )
520             xOS->closeOutput();
521         else if( xS.is() )
522         {
523             Reference< XInputStream > xIS_ = xS->getInputStream();
524             if( xIS_.is() )
525                 xIS_->closeInput();
526         }
527     }
528     catch( Exception & )
529     {
530         SetError( ERRCODE_IO_GENERAL );
531     }
532 }
533 
GetData(void * pData,sal_uIntPtr nSize)534 sal_uIntPtr UCBStream::GetData( void* pData, sal_uIntPtr nSize )
535 {
536     try
537     {
538         Reference< XInputStream > xISFromS;
539         if( xIS.is() )
540         {
541             Sequence<sal_Int8> aData;
542             nSize = xIS->readBytes( aData, nSize );
543             rtl_copyMemory( pData, aData.getConstArray(), nSize );
544             return nSize;
545         }
546         else if( xS.is() && (xISFromS = xS->getInputStream()).is() )
547         {
548             Sequence<sal_Int8> aData;
549             nSize = xISFromS->readBytes( aData, nSize );
550             rtl_copyMemory( pData, aData.getConstArray(), nSize );
551             return nSize;
552         }
553         else
554             SetError( ERRCODE_IO_GENERAL );
555     }
556     catch( Exception & )
557     {
558         SetError( ERRCODE_IO_GENERAL );
559     }
560     return 0;
561 }
562 
PutData(const void * pData,sal_uIntPtr nSize)563 sal_uIntPtr UCBStream::PutData( const void* pData, sal_uIntPtr nSize )
564 {
565     try
566     {
567         Reference< XOutputStream > xOSFromS;
568         if( xOS.is() )
569         {
570             Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize );
571             xOS->writeBytes( aData );
572             return nSize;
573         }
574         else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
575         {
576             Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize );
577             xOSFromS->writeBytes( aData );
578             return nSize;
579         }
580         else
581             SetError( ERRCODE_IO_GENERAL );
582     }
583     catch( Exception & )
584     {
585         SetError( ERRCODE_IO_GENERAL );
586     }
587     return 0;
588 }
589 
SeekPos(sal_uIntPtr nPos)590 sal_uIntPtr UCBStream::SeekPos( sal_uIntPtr nPos )
591 {
592     try
593     {
594         if( xSeek.is() )
595         {
596             sal_uIntPtr nLen = sal::static_int_cast<sal_uIntPtr>( xSeek->getLength() );
597             if( nPos > nLen )
598                 nPos = nLen;
599             xSeek->seek( nPos );
600             return nPos;
601         }
602         else
603             SetError( ERRCODE_IO_GENERAL );
604     }
605     catch( Exception & )
606     {
607         SetError( ERRCODE_IO_GENERAL );
608     }
609     return 0;
610 }
611 
FlushData()612 void    UCBStream::FlushData()
613 {
614     try
615     {
616         Reference< XOutputStream > xOSFromS;
617         if( xOS.is() )
618             xOS->flush();
619         else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
620             xOSFromS->flush();
621         else
622             SetError( ERRCODE_IO_GENERAL );
623     }
624     catch( Exception & )
625     {
626         SetError( ERRCODE_IO_GENERAL );
627     }
628 }
629 
SetSize(sal_uIntPtr nSize)630 void    UCBStream::SetSize( sal_uIntPtr nSize )
631 {
632     (void)nSize;
633 
634     DBG_ERROR( "not allowed to call from basic" );
635     SetError( ERRCODE_IO_GENERAL );
636 }
637 
638 #endif
639 
640 // Oeffnen eines Streams
Open(short nCh,const ByteString & rName,short nStrmMode,short nFlags,short nL)641 SbError SbiStream::Open
642 ( short nCh, const ByteString& rName, short nStrmMode, short nFlags, short nL )
643 {
644     nMode   = nFlags;
645     nLen    = nL;
646     nChan   = nCh;
647     nLine   = 0;
648     nExpandOnWriteTo = 0;
649     if( ( nStrmMode & ( STREAM_READ|STREAM_WRITE ) ) == STREAM_READ )
650         nStrmMode |= STREAM_NOCREATE;
651     String aStr( rName, gsl_getSystemTextEncoding() );
652     String aNameStr = getFullPath( aStr );
653 
654 #ifdef _USE_UNO
655     if( hasUno() )
656     {
657         Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
658         if( xSMgr.is() )
659         {
660             Reference< XSimpleFileAccess >
661                 xSFI( xSMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY );
662             if( xSFI.is() )
663             {
664                 try
665                 {
666 
667                 // #??? For write access delete file if it already exists (not for appending)
668                 if( (nStrmMode & STREAM_WRITE) != 0 && !IsAppend() && !IsBinary() &&
669                     xSFI->exists( aNameStr ) && !xSFI->isFolder( aNameStr ) )
670                 {
671                     xSFI->kill( aNameStr );
672                 }
673 
674                 if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
675                 {
676                     Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
677                     pStrm = new UCBStream( xIS );
678                 }
679                 else if( nStrmMode & STREAM_WRITE )
680                 {
681                     Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
682                     pStrm = new UCBStream( xIS );
683                     // Open for writing is not implemented in ucb yet!!!
684                     //Reference< XOutputStream > xIS = xSFI->openFileWrite( aNameStr );
685                     //pStrm = new UCBStream( xIS );
686                 }
687                 else //if( nStrmMode & STREAM_READ )
688                 {
689                     Reference< XInputStream > xIS = xSFI->openFileRead( aNameStr );
690                     pStrm = new UCBStream( xIS );
691                 }
692 
693                 }
694                 catch( Exception & )
695                 {
696                     nError = ERRCODE_IO_GENERAL;
697                 }
698             }
699         }
700     }
701 
702 #endif
703     if( !pStrm )
704     {
705 #ifdef _OLD_FILE_IMPL
706         pStrm = new SvFileStream( aNameStr, nStrmMode );
707 #else
708         pStrm = new OslStream( aNameStr, nStrmMode );
709 #endif
710     }
711     if( IsAppend() )
712         pStrm->Seek( STREAM_SEEK_TO_END );
713     MapError();
714     if( nError )
715         delete pStrm, pStrm = NULL;
716     return nError;
717 }
718 
Close()719 SbError SbiStream::Close()
720 {
721     if( pStrm )
722     {
723         if( !hasUno() )
724         {
725 #ifdef _OLD_FILE_IMPL
726             ((SvFileStream *)pStrm)->Close();
727 #endif
728         }
729         MapError();
730         delete pStrm;
731         pStrm = NULL;
732     }
733     nChan = 0;
734     return nError;
735 }
736 
Read(ByteString & rBuf,sal_uInt16 n,bool bForceReadingPerByte)737 SbError SbiStream::Read( ByteString& rBuf, sal_uInt16 n, bool bForceReadingPerByte )
738 {
739     nExpandOnWriteTo = 0;
740     if( !bForceReadingPerByte && IsText() )
741     {
742         pStrm->ReadLine( rBuf );
743         nLine++;
744     }
745     else
746     {
747         if( !n ) n = nLen;
748         if( !n )
749             return nError = SbERR_BAD_RECORD_LENGTH;
750         rBuf.Fill( n, ' ' );
751         pStrm->Read( (void*)rBuf.GetBuffer(), n );
752     }
753     MapError();
754     if( !nError && pStrm->IsEof() )
755         nError = SbERR_READ_PAST_EOF;
756     return nError;
757 }
758 
Read(char & ch)759 SbError SbiStream::Read( char& ch )
760 {
761     nExpandOnWriteTo = 0;
762     if( !aLine.Len() )
763     {
764         Read( aLine, 0 );
765         aLine += '\n';
766     }
767     ch = aLine.GetBuffer()[0];
768     aLine.Erase( 0, 1 );
769     return nError;
770 }
771 
ExpandFile()772 void SbiStream::ExpandFile()
773 {
774     if ( nExpandOnWriteTo )
775     {
776         sal_uIntPtr nCur = pStrm->Seek(STREAM_SEEK_TO_END);
777         if( nCur < nExpandOnWriteTo )
778         {
779             sal_uIntPtr nDiff = nExpandOnWriteTo - nCur;
780             char c = 0;
781             while( nDiff-- )
782                 *pStrm << c;
783         }
784         else
785         {
786             pStrm->Seek( nExpandOnWriteTo );
787         }
788         nExpandOnWriteTo = 0;
789     }
790 }
791 
Write(const ByteString & rBuf,sal_uInt16 n)792 SbError SbiStream::Write( const ByteString& rBuf, sal_uInt16 n )
793 {
794     ExpandFile();
795     if( IsAppend() )
796         pStrm->Seek( STREAM_SEEK_TO_END );
797 
798     if( IsText() )
799     {
800         aLine += rBuf;
801         // Raus damit, wenn das Ende ein LF ist, aber CRLF vorher
802         // strippen, da der SvStrm ein CRLF anfuegt!
803         sal_uInt16 nLineLen = aLine.Len();
804         if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0A )
805         {
806             aLine.Erase( nLineLen );
807             if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0D )
808                 aLine.Erase( nLineLen );
809             pStrm->WriteLines( aLine );
810             aLine.Erase();
811         }
812     }
813     else
814     {
815         if( !n ) n = nLen;
816         if( !n )
817             return nError = SbERR_BAD_RECORD_LENGTH;
818         pStrm->Write( rBuf.GetBuffer(), n );
819         MapError();
820     }
821     return nError;
822 }
823 
824 //////////////////////////////////////////////////////////////////////////
825 
826 // Zugriff auf das aktuelle I/O-System:
827 
SbGetIoSystem()828 SbiIoSystem* SbGetIoSystem()
829 {
830     SbiInstance* pInst = pINST;
831     return pInst ? pInst->GetIoSystem() : NULL;
832 }
833 
834 //////////////////////////////////////////////////////////////////////////
835 
SbiIoSystem()836 SbiIoSystem::SbiIoSystem()
837 {
838     for( short i = 0; i < CHANNELS; i++ )
839         pChan[ i ] = NULL;
840     nChan  = 0;
841     nError = 0;
842 }
843 
~SbiIoSystem()844 SbiIoSystem::~SbiIoSystem()
845 {
846     Shutdown();
847 }
848 
GetError()849 SbError SbiIoSystem::GetError()
850 {
851     SbError n = nError; nError = 0;
852     return n;
853 }
854 
Open(short nCh,const ByteString & rName,short nMode,short nFlags,short nLen)855 void SbiIoSystem::Open
856     ( short nCh, const ByteString& rName, short nMode, short nFlags, short nLen )
857 {
858     nError = 0;
859     if( nCh >= CHANNELS || !nCh )
860         nError = SbERR_BAD_CHANNEL;
861     else if( pChan[ nCh ] )
862         nError = SbERR_FILE_ALREADY_OPEN;
863     else
864     {
865         pChan[ nCh ] = new SbiStream;
866         nError = pChan[ nCh ]->Open( nCh, rName, nMode, nFlags, nLen );
867         if( nError )
868             delete pChan[ nCh ], pChan[ nCh ] = NULL;
869     }
870     nChan = 0;
871 }
872 
873 // Aktuellen Kanal schliessen
874 
Close()875 void SbiIoSystem::Close()
876 {
877     if( !nChan )
878         nError = SbERR_BAD_CHANNEL;
879     else if( !pChan[ nChan ] )
880         nError = SbERR_BAD_CHANNEL;
881     else
882     {
883         nError = pChan[ nChan ]->Close();
884         delete pChan[ nChan ];
885         pChan[ nChan ] = NULL;
886     }
887     nChan = 0;
888 }
889 
890 // Shutdown nach Programmlauf
891 
Shutdown()892 void SbiIoSystem::Shutdown()
893 {
894     for( short i = 1; i < CHANNELS; i++ )
895     {
896         if( pChan[ i ] )
897         {
898             SbError n = pChan[ i ]->Close();
899             delete pChan[ i ];
900             pChan[ i ] = NULL;
901             if( n && !nError )
902                 nError = n;
903         }
904     }
905     nChan = 0;
906     // Noch was zu PRINTen?
907     if( aOut.Len() )
908     {
909         String aOutStr( aOut, gsl_getSystemTextEncoding() );
910 #if defined GCC
911         Window* pParent = Application::GetDefDialogParent();
912         MessBox( pParent, WinBits( WB_OK ), String(), aOutStr ).Execute();
913 #else
914         MessBox( GetpApp()->GetDefDialogParent(), WinBits( WB_OK ), String(), aOutStr ).Execute();
915 #endif
916     }
917     aOut.Erase();
918 }
919 
920 // Aus aktuellem Kanal lesen
921 
Read(ByteString & rBuf,short n)922 void SbiIoSystem::Read( ByteString& rBuf, short n )
923 {
924     if( !nChan )
925         ReadCon( rBuf );
926     else if( !pChan[ nChan ] )
927         nError = SbERR_BAD_CHANNEL;
928     else
929         nError = pChan[ nChan ]->Read( rBuf, n );
930 }
931 
Read()932 char SbiIoSystem::Read()
933 {
934     char ch = ' ';
935     if( !nChan )
936     {
937         if( !aIn.Len() )
938         {
939             ReadCon( aIn );
940             aIn += '\n';
941         }
942         ch = aIn.GetBuffer()[0];
943         aIn.Erase( 0, 1 );
944     }
945     else if( !pChan[ nChan ] )
946         nError = SbERR_BAD_CHANNEL;
947     else
948         nError = pChan[ nChan ]->Read( ch );
949     return ch;
950 }
951 
Write(const ByteString & rBuf,short n)952 void SbiIoSystem::Write( const ByteString& rBuf, short n )
953 {
954     if( !nChan )
955         WriteCon( rBuf );
956     else if( !pChan[ nChan ] )
957         nError = SbERR_BAD_CHANNEL;
958     else
959         nError = pChan[ nChan ]->Write( rBuf, n );
960 }
961 
NextChannel()962 short SbiIoSystem::NextChannel()
963 {
964     for( short i = 1; i < CHANNELS; i++ )
965     {
966         if( !pChan[ i ] )
967             return i;
968     }
969     nError = SbERR_TOO_MANY_FILES;
970     return CHANNELS;
971 }
972 
973 // nChannel == 0..CHANNELS-1
974 
GetStream(short nChannel) const975 SbiStream* SbiIoSystem::GetStream( short nChannel ) const
976 {
977     SbiStream* pRet = 0;
978     if( nChannel >= 0 && nChannel < CHANNELS )
979         pRet = pChan[ nChannel ];
980     return pRet;
981 }
982 
CloseAll(void)983 void SbiIoSystem::CloseAll(void)
984 {
985     for( short i = 1; i < CHANNELS; i++ )
986     {
987         if( pChan[ i ] )
988         {
989             SbError n = pChan[ i ]->Close();
990             delete pChan[ i ];
991             pChan[ i ] = NULL;
992             if( n && !nError )
993                 nError = n;
994         }
995     }
996 }
997 
998 /***************************************************************************
999 *
1000 *   Console Support
1001 *
1002 ***************************************************************************/
1003 
1004 // Einlesen einer Zeile von der Console
1005 
ReadCon(ByteString & rIn)1006 void SbiIoSystem::ReadCon( ByteString& rIn )
1007 {
1008     String aPromptStr( aPrompt, gsl_getSystemTextEncoding() );
1009     SbiInputDialog aDlg( NULL, aPromptStr );
1010     if( aDlg.Execute() )
1011         rIn = ByteString( aDlg.GetInput(), gsl_getSystemTextEncoding() );
1012     else
1013         nError = SbERR_USER_ABORT;
1014     aPrompt.Erase();
1015 }
1016 
1017 // Ausgabe einer MessageBox, wenn im Console-Puffer ein CR ist
1018 
WriteCon(const ByteString & rText)1019 void SbiIoSystem::WriteCon( const ByteString& rText )
1020 {
1021     aOut += rText;
1022     sal_uInt16 n1 = aOut.Search( '\n' );
1023     sal_uInt16 n2 = aOut.Search( '\r' );
1024     if( n1 != STRING_NOTFOUND || n2 != STRING_NOTFOUND )
1025     {
1026         if( n1 == STRING_NOTFOUND ) n1 = n2;
1027         else
1028         if( n2 == STRING_NOTFOUND ) n2 = n1;
1029         if( n1 > n2 ) n1 = n2;
1030         ByteString s( aOut.Copy( 0, n1 ) );
1031         aOut.Erase( 0, n1 );
1032         while( aOut.GetBuffer()[0] == '\n' || aOut.GetBuffer()[0] == '\r' )
1033             aOut.Erase( 0, 1 );
1034         String aStr( s, gsl_getSystemTextEncoding() );
1035         {
1036             vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1037             if( !MessBox( GetpApp()->GetDefDialogParent(),
1038                         WinBits( WB_OK_CANCEL | WB_DEF_OK ),
1039                         String(), aStr ).Execute() )
1040                 nError = SbERR_USER_ABORT;
1041         }
1042     }
1043 }
1044 
1045