xref: /trunk/main/basic/source/runtime/iosys.cxx (revision ffd38472365e95f6a578737bc9a5eb0fac624a86)
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& );
90     const String& GetInput() { return aText; }
91 };
92 
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 
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 }
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 }
138 IMPL_LINK_INLINE_END( SbiInputDialog, Cancel, Window *, pWindow )
139 
140 //////////////////////////////////////////////////////////////////////////
141 
142 SbiStream::SbiStream()
143     : pStrm( 0 )
144 {
145 }
146 
147 SbiStream::~SbiStream()
148 {
149     delete pStrm;
150 }
151 
152 // Ummappen eines SvStream-Fehlers auf einen StarBASIC-Code
153 
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 
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 
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         osl_freeSecurityHandle(aSecurity);
242         if( !bRet )
243         {
244             // No valid security! -> Secure mode!
245             return sal_True;
246         }
247 
248         Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
249         if( !xSMgr.is() )
250             return sal_True;
251         Reference< XBridgeFactory > xBridgeFac( xSMgr->createInstance
252             ( ::rtl::OUString::createFromAscii( "com.sun.star.bridge.BridgeFactory" ) ), UNO_QUERY );
253 
254         Sequence< Reference< XBridge > > aBridgeSeq;
255         sal_Int32 nBridgeCount = 0;
256         if( xBridgeFac.is() )
257         {
258             aBridgeSeq = xBridgeFac->getExistingBridges();
259             nBridgeCount = aBridgeSeq.getLength();
260         }
261 
262         if( nBridgeCount == 0 )
263         {
264             // No bridges -> local
265             bRetVal = sal_False;
266             return bRetVal;
267         }
268 
269         // Iterate through all bridges to find (portal) user property
270         const Reference< XBridge >* pBridges = aBridgeSeq.getConstArray();
271         bRetVal = sal_False;    // Now only sal_True if user different from portal user is found
272         sal_Int32 i;
273         for( i = 0 ; i < nBridgeCount ; i++ )
274         {
275             const Reference< XBridge >& rxBridge = pBridges[ i ];
276             ::rtl::OUString aDescription = rxBridge->getDescription();
277             ::rtl::OUString aPortalUser = findUserInDescription( aDescription );
278             if( !aPortalUser.isEmpty() )
279             {
280                 // User Found, compare to system user
281                 if( aPortalUser == aSystemUser )
282                 {
283                     // Same user -> system security is ok, bRetVal stays FALSE
284                     break;
285                 }
286                 else
287                 {
288                     // Different user -> Secure mode!
289                     bRetVal = sal_True;
290                     break;
291                 }
292             }
293         }
294         // No user found or PortalUser != SystemUser -> Secure mode! (Keep default value)
295     }
296 
297     return bRetVal;
298 #else
299     return sal_False;
300 #endif
301 }
302 
303 // Returns sal_True if UNO is available, otherwise the old file
304 // system implementation has to be used
305 // #89378 New semantic: Don't just ask for UNO but for UCB
306 sal_Bool hasUno( void )
307 {
308 #ifdef _USE_UNO
309     static sal_Bool bNeedInit = sal_True;
310     static sal_Bool bRetVal = sal_True;
311 
312     if( bNeedInit )
313     {
314         bNeedInit = sal_False;
315         Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
316         if( !xSMgr.is() )
317         {
318             // No service manager at all
319             bRetVal = sal_False;
320         }
321         else
322         {
323             Reference< XContentProviderManager > xManager( xSMgr->createInstance( ::rtl::OUString::createFromAscii
324                     ( "com.sun.star.ucb.UniversalContentBroker" ) ), UNO_QUERY );
325 
326             if ( !( xManager.is() && xManager->queryContentProvider( ::rtl::OUString::createFromAscii( "file:///" ) ).is() ) )
327             {
328                 // No UCB
329                 bRetVal = sal_False;
330             }
331         }
332     }
333     return bRetVal;
334 #else
335     return sal_False;
336 #endif
337 }
338 
339 
340 
341 #ifndef _OLD_FILE_IMPL
342 
343 class OslStream : public SvStream
344 {
345     File maFile;
346     short mnStrmMode;
347 
348 public:
349                     OslStream( const String& rName, short nStrmMode );
350                     ~OslStream();
351     virtual sal_uIntPtr GetData( void* pData, sal_uIntPtr nSize );
352     virtual sal_uIntPtr PutData( const void* pData, sal_uIntPtr nSize );
353     virtual sal_uIntPtr SeekPos( sal_uIntPtr nPos );
354     virtual void    FlushData();
355     virtual void    SetSize( sal_uIntPtr nSize );
356 };
357 
358 OslStream::OslStream( const String& rName, short nStrmMode )
359     : maFile( rName )
360     , mnStrmMode( nStrmMode )
361 {
362     sal_uInt32 nFlags;
363 
364     if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
365     {
366         nFlags = OpenFlag_Read | OpenFlag_Write;
367     }
368     else if( nStrmMode & STREAM_WRITE )
369     {
370         nFlags = OpenFlag_Write;
371     }
372     else //if( nStrmMode & STREAM_READ )
373     {
374         nFlags = OpenFlag_Read;
375     }
376 
377     FileBase::RC nRet = maFile.open( nFlags );
378     if( nRet == FileBase::E_NOENT && nFlags != OpenFlag_Read )
379     {
380         nFlags |= OpenFlag_Create;
381         nRet = maFile.open( nFlags );
382     }
383 
384     if( nRet != FileBase::E_None )
385     {
386         SetError( ERRCODE_IO_GENERAL );
387     }
388 }
389 
390 
391 OslStream::~OslStream()
392 {
393     maFile.close();
394 }
395 
396 sal_uIntPtr OslStream::GetData( void* pData, sal_uIntPtr nSize )
397 {
398     sal_uInt64 nBytesRead = nSize;
399     FileBase::RC nRet = FileBase::E_None;
400     nRet = maFile.read( pData, nBytesRead, nBytesRead );
401     return (sal_uIntPtr)nBytesRead;
402 }
403 
404 sal_uIntPtr OslStream::PutData( const void* pData, sal_uIntPtr nSize )
405 {
406     sal_uInt64 nBytesWritten;
407     FileBase::RC nRet = FileBase::E_None;
408     nRet = maFile.write( pData, (sal_uInt64)nSize, nBytesWritten );
409     return (sal_uIntPtr)nBytesWritten;
410 }
411 
412 sal_uIntPtr OslStream::SeekPos( sal_uIntPtr nPos )
413 {
414     FileBase::RC nRet;
415     if( nPos == STREAM_SEEK_TO_END )
416     {
417         nRet = maFile.setPos( Pos_End, 0 );
418     }
419     else
420     {
421         nRet = maFile.setPos( Pos_Absolut, (sal_uInt64)nPos );
422     }
423     sal_uInt64 nRealPos;
424     nRet = maFile.getPos( nRealPos );
425     return sal::static_int_cast<sal_uIntPtr>(nRealPos);
426 }
427 
428 void OslStream::FlushData()
429 {
430 }
431 
432 void OslStream::SetSize( sal_uIntPtr nSize )
433 {
434     FileBase::RC nRet = FileBase::E_None;
435     nRet = maFile.setSize( (sal_uInt64)nSize );
436 }
437 
438 #endif
439 
440 
441 #ifdef _USE_UNO
442 
443 class UCBStream : public SvStream
444 {
445     Reference< XInputStream >   xIS;
446     Reference< XOutputStream >  xOS;
447     Reference< XStream >        xS;
448     Reference< XSeekable >      xSeek;
449 public:
450                     UCBStream( Reference< XInputStream > & xIS );
451                     UCBStream( Reference< XOutputStream > & xOS );
452                     UCBStream( Reference< XStream > & xS );
453                     ~UCBStream();
454     virtual sal_uIntPtr GetData( void* pData, sal_uIntPtr nSize );
455     virtual sal_uIntPtr PutData( const void* pData, sal_uIntPtr nSize );
456     virtual sal_uIntPtr SeekPos( sal_uIntPtr nPos );
457     virtual void    FlushData();
458     virtual void    SetSize( sal_uIntPtr nSize );
459 };
460 
461 /*
462 sal_uIntPtr UCBErrorToSvStramError( ucb::IOErrorCode nError )
463 {
464     sal_uIntPtr eReturn = ERRCODE_IO_GENERAL;
465     switch( nError )
466     {
467         case ucb::IOErrorCode_ABORT:                eReturn = SVSTREAM_GENERALERROR; break;
468         case ucb::IOErrorCode_NOT_EXISTING:         eReturn = SVSTREAM_FILE_NOT_FOUND; break;
469         case ucb::IOErrorCode_NOT_EXISTING_PATH:    eReturn = SVSTREAM_PATH_NOT_FOUND; break;
470         case ucb::IOErrorCode_OUT_OF_FILE_HANDLES:  eReturn = SVSTREAM_TOO_MANY_OPEN_FILES; break;
471         case ucb::IOErrorCode_ACCESS_DENIED:        eReturn = SVSTREAM_ACCESS_DENIED; break;
472         case ucb::IOErrorCode_LOCKING_VIOLATION:    eReturn = SVSTREAM_SHARING_VIOLATION; break;
473 
474         case ucb::IOErrorCode_INVALID_ACCESS:       eReturn = SVSTREAM_INVALID_ACCESS; break;
475         case ucb::IOErrorCode_CANT_CREATE:          eReturn = SVSTREAM_CANNOT_MAKE; break;
476         case ucb::IOErrorCode_INVALID_PARAMETER:    eReturn = SVSTREAM_INVALID_PARAMETER; break;
477 
478         case ucb::IOErrorCode_CANT_READ:            eReturn = SVSTREAM_READ_ERROR; break;
479         case ucb::IOErrorCode_CANT_WRITE:           eReturn = SVSTREAM_WRITE_ERROR; break;
480         case ucb::IOErrorCode_CANT_SEEK:            eReturn = SVSTREAM_SEEK_ERROR; break;
481         case ucb::IOErrorCode_CANT_TELL:            eReturn = SVSTREAM_TELL_ERROR; break;
482 
483         case ucb::IOErrorCode_OUT_OF_MEMORY:        eReturn = SVSTREAM_OUTOFMEMORY; break;
484 
485         case SVSTREAM_FILEFORMAT_ERROR:             eReturn = SVSTREAM_FILEFORMAT_ERROR; break;
486         case ucb::IOErrorCode_WRONG_VERSION:        eReturn = SVSTREAM_WRONGVERSION;
487         case ucb::IOErrorCode_OUT_OF_DISK_SPACE:    eReturn = SVSTREAM_DISK_FULL; break;
488 
489         case ucb::IOErrorCode_BAD_CRC:              eReturn = ERRCODE_IO_BADCRC; break;
490     }
491     return eReturn;
492 }
493 */
494 
495 UCBStream::UCBStream( Reference< XInputStream > & rStm )
496     : xIS( rStm )
497     , xSeek( rStm, UNO_QUERY )
498 {
499 }
500 
501 UCBStream::UCBStream( Reference< XOutputStream > & rStm )
502     : xOS( rStm )
503     , xSeek( rStm, UNO_QUERY )
504 {
505 }
506 
507 UCBStream::UCBStream( Reference< XStream > & rStm )
508     : xS( rStm )
509     , xSeek( rStm, UNO_QUERY )
510 {
511 }
512 
513 
514 UCBStream::~UCBStream()
515 {
516     try
517     {
518         if( xIS.is() )
519             xIS->closeInput();
520         else if( xOS.is() )
521             xOS->closeOutput();
522         else if( xS.is() )
523         {
524             Reference< XInputStream > xIS_ = xS->getInputStream();
525             if( xIS_.is() )
526                 xIS_->closeInput();
527         }
528     }
529     catch( Exception & )
530     {
531         SetError( ERRCODE_IO_GENERAL );
532     }
533 }
534 
535 sal_uIntPtr UCBStream::GetData( void* pData, sal_uIntPtr nSize )
536 {
537     try
538     {
539         Reference< XInputStream > xISFromS;
540         if( xIS.is() )
541         {
542             Sequence<sal_Int8> aData;
543             nSize = xIS->readBytes( aData, nSize );
544             rtl_copyMemory( pData, aData.getConstArray(), nSize );
545             return nSize;
546         }
547         else if( xS.is() && (xISFromS = xS->getInputStream()).is() )
548         {
549             Sequence<sal_Int8> aData;
550             nSize = xISFromS->readBytes( aData, nSize );
551             rtl_copyMemory( pData, aData.getConstArray(), nSize );
552             return nSize;
553         }
554         else
555             SetError( ERRCODE_IO_GENERAL );
556     }
557     catch( Exception & )
558     {
559         SetError( ERRCODE_IO_GENERAL );
560     }
561     return 0;
562 }
563 
564 sal_uIntPtr UCBStream::PutData( const void* pData, sal_uIntPtr nSize )
565 {
566     try
567     {
568         Reference< XOutputStream > xOSFromS;
569         if( xOS.is() )
570         {
571             Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize );
572             xOS->writeBytes( aData );
573             return nSize;
574         }
575         else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
576         {
577             Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize );
578             xOSFromS->writeBytes( aData );
579             return nSize;
580         }
581         else
582             SetError( ERRCODE_IO_GENERAL );
583     }
584     catch( Exception & )
585     {
586         SetError( ERRCODE_IO_GENERAL );
587     }
588     return 0;
589 }
590 
591 sal_uIntPtr UCBStream::SeekPos( sal_uIntPtr nPos )
592 {
593     try
594     {
595         if( xSeek.is() )
596         {
597             sal_uIntPtr nLen = sal::static_int_cast<sal_uIntPtr>( xSeek->getLength() );
598             if( nPos > nLen )
599                 nPos = nLen;
600             xSeek->seek( nPos );
601             return nPos;
602         }
603         else
604             SetError( ERRCODE_IO_GENERAL );
605     }
606     catch( Exception & )
607     {
608         SetError( ERRCODE_IO_GENERAL );
609     }
610     return 0;
611 }
612 
613 void    UCBStream::FlushData()
614 {
615     try
616     {
617         Reference< XOutputStream > xOSFromS;
618         if( xOS.is() )
619             xOS->flush();
620         else if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
621             xOSFromS->flush();
622         else
623             SetError( ERRCODE_IO_GENERAL );
624     }
625     catch( Exception & )
626     {
627         SetError( ERRCODE_IO_GENERAL );
628     }
629 }
630 
631 void    UCBStream::SetSize( sal_uIntPtr nSize )
632 {
633     (void)nSize;
634 
635     DBG_ERROR( "not allowed to call from basic" );
636     SetError( ERRCODE_IO_GENERAL );
637 }
638 
639 #endif
640 
641 // Oeffnen eines Streams
642 SbError SbiStream::Open
643 ( short nCh, const ByteString& rName, short nStrmMode, short nFlags, short nL )
644 {
645     nMode   = nFlags;
646     nLen    = nL;
647     nChan   = nCh;
648     nLine   = 0;
649     nExpandOnWriteTo = 0;
650     if( ( nStrmMode & ( STREAM_READ|STREAM_WRITE ) ) == STREAM_READ )
651         nStrmMode |= STREAM_NOCREATE;
652     String aStr( rName, gsl_getSystemTextEncoding() );
653     String aNameStr = getFullPath( aStr );
654 
655 #ifdef _USE_UNO
656     if( hasUno() )
657     {
658         Reference< XMultiServiceFactory > xSMgr = getProcessServiceFactory();
659         if( xSMgr.is() )
660         {
661             Reference< XSimpleFileAccess >
662                 xSFI( xSMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY );
663             if( xSFI.is() )
664             {
665                 try
666                 {
667 
668                 // #??? For write access delete file if it already exists (not for appending)
669                 if( (nStrmMode & STREAM_WRITE) != 0 && !IsAppend() && !IsBinary() && !IsRandom() &&
670                     xSFI->exists( aNameStr ) && !xSFI->isFolder( aNameStr ) )
671                 {
672                     xSFI->kill( aNameStr );
673                 }
674 
675                 if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
676                 {
677                     Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
678                     pStrm = new UCBStream( xIS );
679                 }
680                 else if( nStrmMode & STREAM_WRITE )
681                 {
682                     Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
683                     pStrm = new UCBStream( xIS );
684                     // Open for writing is not implemented in ucb yet!!!
685                     //Reference< XOutputStream > xIS = xSFI->openFileWrite( aNameStr );
686                     //pStrm = new UCBStream( xIS );
687                 }
688                 else //if( nStrmMode & STREAM_READ )
689                 {
690                     Reference< XInputStream > xIS = xSFI->openFileRead( aNameStr );
691                     pStrm = new UCBStream( xIS );
692                 }
693 
694                 }
695                 catch( Exception & )
696                 {
697                     nError = ERRCODE_IO_GENERAL;
698                 }
699             }
700         }
701     }
702 
703 #endif
704     if( !pStrm )
705     {
706 #ifdef _OLD_FILE_IMPL
707         pStrm = new SvFileStream( aNameStr, nStrmMode );
708 #else
709         pStrm = new OslStream( aNameStr, nStrmMode );
710 #endif
711     }
712     if( IsAppend() )
713         pStrm->Seek( STREAM_SEEK_TO_END );
714     MapError();
715     if( nError )
716         delete pStrm, pStrm = NULL;
717     return nError;
718 }
719 
720 SbError SbiStream::Close()
721 {
722     if( pStrm )
723     {
724         if( !hasUno() )
725         {
726 #ifdef _OLD_FILE_IMPL
727             ((SvFileStream *)pStrm)->Close();
728 #endif
729         }
730         MapError();
731         delete pStrm;
732         pStrm = NULL;
733     }
734     nChan = 0;
735     return nError;
736 }
737 
738 SbError SbiStream::Read( ByteString& rBuf, sal_uInt16 n, bool bForceReadingPerByte )
739 {
740     nExpandOnWriteTo = 0;
741     if( !bForceReadingPerByte && IsText() )
742     {
743         pStrm->ReadLine( rBuf );
744         nLine++;
745     }
746     else
747     {
748         if( !n ) n = nLen;
749         if( !n )
750             return nError = SbERR_BAD_RECORD_LENGTH;
751         rBuf.Fill( n, ' ' );
752         pStrm->Read( (void*)rBuf.GetBuffer(), n );
753     }
754     MapError();
755     if( !nError && pStrm->IsEof() )
756         nError = SbERR_READ_PAST_EOF;
757     return nError;
758 }
759 
760 SbError SbiStream::Read( char& ch )
761 {
762     nExpandOnWriteTo = 0;
763     if( !aLine.Len() )
764     {
765         Read( aLine, 0 );
766         aLine += '\n';
767     }
768     ch = aLine.GetBuffer()[0];
769     aLine.Erase( 0, 1 );
770     return nError;
771 }
772 
773 void SbiStream::ExpandFile()
774 {
775     if ( nExpandOnWriteTo )
776     {
777         sal_uIntPtr nCur = pStrm->Seek(STREAM_SEEK_TO_END);
778         if( nCur < nExpandOnWriteTo )
779         {
780             sal_uIntPtr nDiff = nExpandOnWriteTo - nCur;
781             char c = 0;
782             while( nDiff-- )
783                 *pStrm << c;
784         }
785         else
786         {
787             pStrm->Seek( nExpandOnWriteTo );
788         }
789         nExpandOnWriteTo = 0;
790     }
791 }
792 
793 SbError SbiStream::Write( const ByteString& rBuf, sal_uInt16 n )
794 {
795     ExpandFile();
796     if( IsAppend() )
797         pStrm->Seek( STREAM_SEEK_TO_END );
798 
799     if( IsText() )
800     {
801         aLine += rBuf;
802         // Raus damit, wenn das Ende ein LF ist, aber CRLF vorher
803         // strippen, da der SvStrm ein CRLF anfuegt!
804         sal_uInt16 nLineLen = aLine.Len();
805         if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0A )
806         {
807             aLine.Erase( nLineLen );
808             if( nLineLen && aLine.GetBuffer()[ --nLineLen ] == 0x0D )
809                 aLine.Erase( nLineLen );
810             pStrm->WriteLines( aLine );
811             aLine.Erase();
812         }
813     }
814     else
815     {
816         if( !n ) n = nLen;
817         if( !n )
818             return nError = SbERR_BAD_RECORD_LENGTH;
819         pStrm->Write( rBuf.GetBuffer(), n );
820         MapError();
821     }
822     return nError;
823 }
824 
825 //////////////////////////////////////////////////////////////////////////
826 
827 // Zugriff auf das aktuelle I/O-System:
828 
829 SbiIoSystem* SbGetIoSystem()
830 {
831     SbiInstance* pInst = pINST;
832     return pInst ? pInst->GetIoSystem() : NULL;
833 }
834 
835 //////////////////////////////////////////////////////////////////////////
836 
837 SbiIoSystem::SbiIoSystem()
838 {
839     for( short i = 0; i < CHANNELS; i++ )
840         pChan[ i ] = NULL;
841     nChan  = 0;
842     nError = 0;
843 }
844 
845 SbiIoSystem::~SbiIoSystem()
846 {
847     Shutdown();
848 }
849 
850 SbError SbiIoSystem::GetError()
851 {
852     SbError n = nError; nError = 0;
853     return n;
854 }
855 
856 void SbiIoSystem::Open
857     ( short nCh, const ByteString& rName, short nMode, short nFlags, short nLen )
858 {
859     nError = 0;
860     if( nCh >= CHANNELS || !nCh )
861         nError = SbERR_BAD_CHANNEL;
862     else if( pChan[ nCh ] )
863         nError = SbERR_FILE_ALREADY_OPEN;
864     else
865     {
866         pChan[ nCh ] = new SbiStream;
867         nError = pChan[ nCh ]->Open( nCh, rName, nMode, nFlags, nLen );
868         if( nError )
869             delete pChan[ nCh ], pChan[ nCh ] = NULL;
870     }
871     nChan = 0;
872 }
873 
874 // Aktuellen Kanal schliessen
875 
876 void SbiIoSystem::Close()
877 {
878     if( !nChan )
879         nError = SbERR_BAD_CHANNEL;
880     else if( !pChan[ nChan ] )
881         nError = SbERR_BAD_CHANNEL;
882     else
883     {
884         nError = pChan[ nChan ]->Close();
885         delete pChan[ nChan ];
886         pChan[ nChan ] = NULL;
887     }
888     nChan = 0;
889 }
890 
891 // Shutdown nach Programmlauf
892 
893 void SbiIoSystem::Shutdown()
894 {
895     for( short i = 1; i < CHANNELS; i++ )
896     {
897         if( pChan[ i ] )
898         {
899             SbError n = pChan[ i ]->Close();
900             delete pChan[ i ];
901             pChan[ i ] = NULL;
902             if( n && !nError )
903                 nError = n;
904         }
905     }
906     nChan = 0;
907     // Noch was zu PRINTen?
908     if( aOut.Len() )
909     {
910         String aOutStr( aOut, gsl_getSystemTextEncoding() );
911 #if defined GCC
912         Window* pParent = Application::GetDefDialogParent();
913         MessBox( pParent, WinBits( WB_OK ), String(), aOutStr ).Execute();
914 #else
915         MessBox( GetpApp()->GetDefDialogParent(), WinBits( WB_OK ), String(), aOutStr ).Execute();
916 #endif
917     }
918     aOut.Erase();
919 }
920 
921 // Aus aktuellem Kanal lesen
922 
923 void SbiIoSystem::Read( ByteString& rBuf, short n )
924 {
925     if( !nChan )
926         ReadCon( rBuf );
927     else if( !pChan[ nChan ] )
928         nError = SbERR_BAD_CHANNEL;
929     else
930         nError = pChan[ nChan ]->Read( rBuf, n );
931 }
932 
933 char SbiIoSystem::Read()
934 {
935     char ch = ' ';
936     if( !nChan )
937     {
938         if( !aIn.Len() )
939         {
940             ReadCon( aIn );
941             aIn += '\n';
942         }
943         ch = aIn.GetBuffer()[0];
944         aIn.Erase( 0, 1 );
945     }
946     else if( !pChan[ nChan ] )
947         nError = SbERR_BAD_CHANNEL;
948     else
949         nError = pChan[ nChan ]->Read( ch );
950     return ch;
951 }
952 
953 void SbiIoSystem::Write( const ByteString& rBuf, short n )
954 {
955     if( !nChan )
956         WriteCon( rBuf );
957     else if( !pChan[ nChan ] )
958         nError = SbERR_BAD_CHANNEL;
959     else
960         nError = pChan[ nChan ]->Write( rBuf, n );
961 }
962 
963 short SbiIoSystem::NextChannel()
964 {
965     for( short i = 1; i < CHANNELS; i++ )
966     {
967         if( !pChan[ i ] )
968             return i;
969     }
970     nError = SbERR_TOO_MANY_FILES;
971     return CHANNELS;
972 }
973 
974 // nChannel == 0..CHANNELS-1
975 
976 SbiStream* SbiIoSystem::GetStream( short nChannel ) const
977 {
978     SbiStream* pRet = 0;
979     if( nChannel >= 0 && nChannel < CHANNELS )
980         pRet = pChan[ nChannel ];
981     return pRet;
982 }
983 
984 void SbiIoSystem::CloseAll(void)
985 {
986     for( short i = 1; i < CHANNELS; i++ )
987     {
988         if( pChan[ i ] )
989         {
990             SbError n = pChan[ i ]->Close();
991             delete pChan[ i ];
992             pChan[ i ] = NULL;
993             if( n && !nError )
994                 nError = n;
995         }
996     }
997 }
998 
999 /***************************************************************************
1000 *
1001 *   Console Support
1002 *
1003 ***************************************************************************/
1004 
1005 // Einlesen einer Zeile von der Console
1006 
1007 void SbiIoSystem::ReadCon( ByteString& rIn )
1008 {
1009     String aPromptStr( aPrompt, gsl_getSystemTextEncoding() );
1010     SbiInputDialog aDlg( NULL, aPromptStr );
1011     if( aDlg.Execute() )
1012         rIn = ByteString( aDlg.GetInput(), gsl_getSystemTextEncoding() );
1013     else
1014         nError = SbERR_USER_ABORT;
1015     aPrompt.Erase();
1016 }
1017 
1018 // Ausgabe einer MessageBox, wenn im Console-Puffer ein CR ist
1019 
1020 void SbiIoSystem::WriteCon( const ByteString& rText )
1021 {
1022     aOut += rText;
1023     sal_uInt16 n1 = aOut.Search( '\n' );
1024     sal_uInt16 n2 = aOut.Search( '\r' );
1025     if( n1 != STRING_NOTFOUND || n2 != STRING_NOTFOUND )
1026     {
1027         if( n1 == STRING_NOTFOUND ) n1 = n2;
1028         else
1029         if( n2 == STRING_NOTFOUND ) n2 = n1;
1030         if( n1 > n2 ) n1 = n2;
1031         ByteString s( aOut.Copy( 0, n1 ) );
1032         aOut.Erase( 0, n1 );
1033         while( aOut.GetBuffer()[0] == '\n' || aOut.GetBuffer()[0] == '\r' )
1034             aOut.Erase( 0, 1 );
1035         String aStr( s, gsl_getSystemTextEncoding() );
1036         {
1037             vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1038             if( !MessBox( GetpApp()->GetDefDialogParent(),
1039                         WinBits( WB_OK_CANCEL | WB_DEF_OK ),
1040                         String(), aStr ).Execute() )
1041                 nError = SbERR_USER_ABORT;
1042         }
1043     }
1044 }
1045