xref: /trunk/main/basic/source/runtime/iosys.cxx (revision 0848378b)
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 		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
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 
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 
390 OslStream::~OslStream()
391 {
392     maFile.close();
393 }
394 
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 
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 
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 
427 void OslStream::FlushData()
428 {
429 }
430 
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 
494 UCBStream::UCBStream( Reference< XInputStream > & rStm )
495 	: xIS( rStm )
496 	, xSeek( rStm, UNO_QUERY )
497 {
498 }
499 
500 UCBStream::UCBStream( Reference< XOutputStream > & rStm )
501 	: xOS( rStm )
502 	, xSeek( rStm, UNO_QUERY )
503 {
504 }
505 
506 UCBStream::UCBStream( Reference< XStream > & rStm )
507 	: xS( rStm )
508 	, xSeek( rStm, UNO_QUERY )
509 {
510 }
511 
512 
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 
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 
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 
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 
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 
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
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 
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 
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 
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 
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 
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 
828 SbiIoSystem* SbGetIoSystem()
829 {
830 	SbiInstance* pInst = pINST;
831 	return pInst ? pInst->GetIoSystem() : NULL;
832 }
833 
834 //////////////////////////////////////////////////////////////////////////
835 
836 SbiIoSystem::SbiIoSystem()
837 {
838 	for( short i = 0; i < CHANNELS; i++ )
839 		pChan[ i ] = NULL;
840 	nChan  = 0;
841 	nError = 0;
842 }
843 
844 SbiIoSystem::~SbiIoSystem()
845 {
846 	Shutdown();
847 }
848 
849 SbError SbiIoSystem::GetError()
850 {
851 	SbError n = nError; nError = 0;
852 	return n;
853 }
854 
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 
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 
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 
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 
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 
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 
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 
975 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 
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 
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 
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