xref: /trunk/main/basic/source/runtime/iosys.cxx (revision c91758c7)
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 		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
hasUno(void)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 
OslStream(const String & rName,short nStrmMode)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 
~OslStream()391 OslStream::~OslStream()
392 {
393     maFile.close();
394 }
395 
GetData(void * pData,sal_uIntPtr nSize)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 
PutData(const void * pData,sal_uIntPtr nSize)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 
SeekPos(sal_uIntPtr nPos)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 
FlushData()428 void OslStream::FlushData()
429 {
430 }
431 
SetSize(sal_uIntPtr nSize)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 
UCBStream(Reference<XInputStream> & rStm)495 UCBStream::UCBStream( Reference< XInputStream > & rStm )
496 	: xIS( rStm )
497 	, xSeek( rStm, UNO_QUERY )
498 {
499 }
500 
UCBStream(Reference<XOutputStream> & rStm)501 UCBStream::UCBStream( Reference< XOutputStream > & rStm )
502 	: xOS( rStm )
503 	, xSeek( rStm, UNO_QUERY )
504 {
505 }
506 
UCBStream(Reference<XStream> & rStm)507 UCBStream::UCBStream( Reference< XStream > & rStm )
508 	: xS( rStm )
509 	, xSeek( rStm, UNO_QUERY )
510 {
511 }
512 
513 
~UCBStream()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 
GetData(void * pData,sal_uIntPtr nSize)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 
PutData(const void * pData,sal_uIntPtr nSize)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 
SeekPos(sal_uIntPtr nPos)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 
FlushData()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 
SetSize(sal_uIntPtr nSize)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
Open(short nCh,const ByteString & rName,short nStrmMode,short nFlags,short nL)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 
Close()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 
Read(ByteString & rBuf,sal_uInt16 n,bool bForceReadingPerByte)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 
Read(char & ch)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 
ExpandFile()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 
Write(const ByteString & rBuf,sal_uInt16 n)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 
SbGetIoSystem()829 SbiIoSystem* SbGetIoSystem()
830 {
831 	SbiInstance* pInst = pINST;
832 	return pInst ? pInst->GetIoSystem() : NULL;
833 }
834 
835 //////////////////////////////////////////////////////////////////////////
836 
SbiIoSystem()837 SbiIoSystem::SbiIoSystem()
838 {
839 	for( short i = 0; i < CHANNELS; i++ )
840 		pChan[ i ] = NULL;
841 	nChan  = 0;
842 	nError = 0;
843 }
844 
~SbiIoSystem()845 SbiIoSystem::~SbiIoSystem()
846 {
847 	Shutdown();
848 }
849 
GetError()850 SbError SbiIoSystem::GetError()
851 {
852 	SbError n = nError; nError = 0;
853 	return n;
854 }
855 
Open(short nCh,const ByteString & rName,short nMode,short nFlags,short nLen)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 
Close()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 
Shutdown()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 
Read(ByteString & rBuf,short n)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 
Read()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 
Write(const ByteString & rBuf,short n)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 
NextChannel()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 
GetStream(short nChannel) const976 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 
CloseAll(void)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 
ReadCon(ByteString & rIn)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 
WriteCon(const ByteString & rText)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 
1046