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