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 12 : SbiStream::SbiStream()
129 12 : : pStrm( 0 )
130 : {
131 12 : }
132 :
133 24 : SbiStream::~SbiStream()
134 : {
135 12 : delete pStrm;
136 12 : }
137 :
138 : // map an SvStream-error to StarBASIC-code
139 :
140 24 : void SbiStream::MapError()
141 : {
142 24 : if( pStrm )
143 : {
144 24 : switch( pStrm->GetError() )
145 : {
146 : case SVSTREAM_OK:
147 24 : nError = 0;
148 24 : 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 24 : }
173 :
174 : // TODO: Code is copied from daemons2/source/uno/asciiEncoder.cxx
175 :
176 0 : OUString findUserInDescription( const 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 0 : 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 : osl_freeSecurityHandle(aSecurity);
220 0 : if( !bRet )
221 : {
222 : // No valid security! -> Secure mode!
223 0 : return true;
224 : }
225 :
226 0 : Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
227 0 : Reference< XBridgeFactory2 > xBridgeFac( BridgeFactory::create(xContext) );
228 :
229 0 : Sequence< Reference< XBridge > > aBridgeSeq = xBridgeFac->getExistingBridges();
230 0 : sal_Int32 nBridgeCount = aBridgeSeq.getLength();
231 :
232 0 : if( nBridgeCount == 0 )
233 : {
234 : // No bridges -> local
235 0 : bRetVal = false;
236 0 : return bRetVal;
237 : }
238 :
239 : // Iterate through all bridges to find (portal) user property
240 0 : const Reference< XBridge >* pBridges = aBridgeSeq.getConstArray();
241 0 : bRetVal = false; // Now only sal_True if user different from portal user is found
242 : sal_Int32 i;
243 0 : for( i = 0 ; i < nBridgeCount ; i++ )
244 : {
245 0 : const Reference< XBridge >& rxBridge = pBridges[ i ];
246 0 : OUString aDescription = rxBridge->getDescription();
247 0 : OUString aPortalUser = findUserInDescription( aDescription );
248 0 : if( !aPortalUser.isEmpty() )
249 : {
250 : // User Found, compare to system user
251 0 : if( aPortalUser == aSystemUser )
252 : {
253 : // Same user -> system security is ok, bRetVal stays FALSE
254 0 : break;
255 : }
256 : else
257 : {
258 : // Different user -> Secure mode!
259 0 : bRetVal = true;
260 0 : break;
261 : }
262 : }
263 0 : }
264 : // No user found or PortalUser != SystemUser -> Secure mode! (Keep default value)
265 : }
266 :
267 0 : return bRetVal;
268 : }
269 :
270 : // Returns sal_True if UNO is available, otherwise the old file
271 : // system implementation has to be used
272 : // #89378 New semantic: Don't just ask for UNO but for UCB
273 46 : bool hasUno( void )
274 : {
275 : static bool bNeedInit = true;
276 : static bool bRetVal = true;
277 :
278 46 : if( bNeedInit )
279 : {
280 2 : bNeedInit = false;
281 2 : Reference< XComponentContext > xContext = comphelper::getProcessComponentContext();
282 2 : if( !xContext.is() )
283 : {
284 : // No service manager at all
285 0 : bRetVal = false;
286 : }
287 : else
288 : {
289 2 : Reference< XUniversalContentBroker > xManager = UniversalContentBroker::create(xContext);
290 :
291 2 : if ( !( xManager->queryContentProvider( OUString("file:///" ) ).is() ) )
292 : {
293 : // No UCB
294 0 : bRetVal = false;
295 2 : }
296 2 : }
297 : }
298 46 : return bRetVal;
299 : }
300 :
301 :
302 :
303 : class OslStream : public SvStream
304 : {
305 : osl::File maFile;
306 :
307 : public:
308 : OslStream( const OUString& rName, short nStrmMode );
309 : ~OslStream();
310 : virtual sal_uIntPtr GetData( void* pData, sal_uIntPtr nSize );
311 : virtual sal_uIntPtr PutData( const void* pData, sal_uIntPtr nSize );
312 : virtual sal_uIntPtr SeekPos( sal_uIntPtr nPos );
313 : virtual void FlushData();
314 : virtual void SetSize( sal_uIntPtr nSize );
315 : };
316 :
317 0 : OslStream::OslStream( const OUString& rName, short nStrmMode )
318 0 : : maFile( rName )
319 : {
320 : sal_uInt32 nFlags;
321 :
322 0 : if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
323 : {
324 0 : nFlags = osl_File_OpenFlag_Read | osl_File_OpenFlag_Write;
325 : }
326 0 : else if( nStrmMode & STREAM_WRITE )
327 : {
328 0 : nFlags = osl_File_OpenFlag_Write;
329 : }
330 : else //if( nStrmMode & STREAM_READ )
331 : {
332 0 : nFlags = osl_File_OpenFlag_Read;
333 : }
334 :
335 0 : osl::FileBase::RC nRet = maFile.open( nFlags );
336 0 : if( nRet == osl::FileBase::E_NOENT && nFlags != osl_File_OpenFlag_Read )
337 : {
338 0 : nFlags |= osl_File_OpenFlag_Create;
339 0 : nRet = maFile.open( nFlags );
340 : }
341 :
342 0 : if( nRet != osl::FileBase::E_None )
343 : {
344 0 : SetError( ERRCODE_IO_GENERAL );
345 : }
346 0 : }
347 :
348 :
349 0 : OslStream::~OslStream()
350 : {
351 0 : maFile.close();
352 0 : }
353 :
354 0 : sal_uIntPtr OslStream::GetData( void* pData, sal_uIntPtr nSize )
355 : {
356 0 : sal_uInt64 nBytesRead = nSize;
357 0 : maFile.read( pData, nBytesRead, nBytesRead );
358 0 : return (sal_uIntPtr)nBytesRead;
359 : }
360 :
361 0 : sal_uIntPtr OslStream::PutData( const void* pData, sal_uIntPtr nSize )
362 : {
363 : sal_uInt64 nBytesWritten;
364 0 : maFile.write( pData, (sal_uInt64)nSize, nBytesWritten );
365 0 : return (sal_uIntPtr)nBytesWritten;
366 : }
367 :
368 0 : sal_uIntPtr OslStream::SeekPos( sal_uIntPtr nPos )
369 : {
370 0 : ::osl::FileBase::RC rc = ::osl::FileBase::E_None;
371 0 : if( nPos == STREAM_SEEK_TO_END )
372 : {
373 0 : rc = maFile.setPos( osl_Pos_End, 0 );
374 : }
375 : else
376 : {
377 0 : rc = maFile.setPos( osl_Pos_Absolut, (sal_uInt64)nPos );
378 : }
379 : OSL_VERIFY(rc == ::osl::FileBase::E_None);
380 0 : sal_uInt64 nRealPos(0);
381 0 : maFile.getPos( nRealPos );
382 0 : return sal::static_int_cast<sal_uIntPtr>(nRealPos);
383 : }
384 :
385 0 : void OslStream::FlushData()
386 : {
387 0 : }
388 :
389 0 : void OslStream::SetSize( sal_uIntPtr nSize )
390 : {
391 0 : maFile.setSize( (sal_uInt64)nSize );
392 0 : }
393 :
394 :
395 : class UCBStream : public SvStream
396 : {
397 : Reference< XInputStream > xIS;
398 : Reference< XStream > xS;
399 : Reference< XSeekable > xSeek;
400 : public:
401 : UCBStream( Reference< XInputStream > & xIS );
402 : UCBStream( Reference< XStream > & xS );
403 : ~UCBStream();
404 : virtual sal_uIntPtr GetData( void* pData, sal_uIntPtr nSize );
405 : virtual sal_uIntPtr PutData( const void* pData, sal_uIntPtr nSize );
406 : virtual sal_uIntPtr SeekPos( sal_uIntPtr nPos );
407 : virtual void FlushData();
408 : virtual void SetSize( sal_uIntPtr nSize );
409 : };
410 :
411 0 : UCBStream::UCBStream( Reference< XInputStream > & rStm )
412 : : xIS( rStm )
413 0 : , xSeek( rStm, UNO_QUERY )
414 : {
415 0 : }
416 :
417 12 : UCBStream::UCBStream( Reference< XStream > & rStm )
418 : : xS( rStm )
419 12 : , xSeek( rStm, UNO_QUERY )
420 : {
421 12 : }
422 :
423 :
424 36 : UCBStream::~UCBStream()
425 : {
426 : try
427 : {
428 12 : if( xIS.is() )
429 : {
430 0 : xIS->closeInput();
431 : }
432 12 : else if( xS.is() )
433 : {
434 12 : Reference< XInputStream > xIS_ = xS->getInputStream();
435 12 : if( xIS_.is() )
436 : {
437 12 : xIS_->closeInput();
438 12 : }
439 : }
440 : }
441 0 : catch(const Exception & )
442 : {
443 0 : SetError( ERRCODE_IO_GENERAL );
444 : }
445 24 : }
446 :
447 0 : sal_uIntPtr UCBStream::GetData( void* pData, sal_uIntPtr nSize )
448 : {
449 : try
450 : {
451 0 : Reference< XInputStream > xISFromS;
452 0 : if( xIS.is() )
453 : {
454 0 : Sequence<sal_Int8> aData;
455 0 : nSize = xIS->readBytes( aData, nSize );
456 0 : memcpy( pData, aData.getConstArray(), nSize );
457 0 : return nSize;
458 : }
459 0 : else if( xS.is() && (xISFromS = xS->getInputStream()).is() )
460 : {
461 0 : Sequence<sal_Int8> aData;
462 0 : nSize = xISFromS->readBytes( aData, nSize );
463 0 : memcpy(pData, aData.getConstArray(), nSize );
464 0 : return nSize;
465 : }
466 : else
467 : {
468 0 : SetError( ERRCODE_IO_GENERAL );
469 0 : }
470 : }
471 0 : catch(const Exception & )
472 : {
473 0 : SetError( ERRCODE_IO_GENERAL );
474 : }
475 0 : return 0;
476 : }
477 :
478 183 : sal_uIntPtr UCBStream::PutData( const void* pData, sal_uIntPtr nSize )
479 : {
480 : try
481 : {
482 183 : Reference< XOutputStream > xOSFromS;
483 183 : if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
484 : {
485 183 : Sequence<sal_Int8> aData( (const sal_Int8 *)pData, nSize );
486 183 : xOSFromS->writeBytes( aData );
487 183 : return nSize;
488 : }
489 : else
490 : {
491 0 : SetError( ERRCODE_IO_GENERAL );
492 0 : }
493 : }
494 0 : catch(const Exception & )
495 : {
496 0 : SetError( ERRCODE_IO_GENERAL );
497 : }
498 0 : return 0;
499 : }
500 :
501 0 : sal_uIntPtr UCBStream::SeekPos( sal_uIntPtr nPos )
502 : {
503 : try
504 : {
505 0 : if( xSeek.is() )
506 : {
507 0 : sal_uIntPtr nLen = sal::static_int_cast<sal_uIntPtr>( xSeek->getLength() );
508 0 : if( nPos > nLen )
509 : {
510 0 : nPos = nLen;
511 : }
512 0 : xSeek->seek( nPos );
513 0 : return nPos;
514 : }
515 : else
516 : {
517 0 : SetError( ERRCODE_IO_GENERAL );
518 : }
519 : }
520 0 : catch(const Exception & )
521 : {
522 0 : SetError( ERRCODE_IO_GENERAL );
523 : }
524 0 : return 0;
525 : }
526 :
527 0 : void UCBStream::FlushData()
528 : {
529 : try
530 : {
531 0 : Reference< XOutputStream > xOSFromS;
532 0 : if( xS.is() && (xOSFromS = xS->getOutputStream()).is() )
533 : {
534 0 : xOSFromS->flush();
535 : }
536 : else
537 : {
538 0 : SetError( ERRCODE_IO_GENERAL );
539 0 : }
540 : }
541 0 : catch(const Exception & )
542 : {
543 0 : SetError( ERRCODE_IO_GENERAL );
544 : }
545 0 : }
546 :
547 0 : void UCBStream::SetSize( sal_uIntPtr nSize )
548 : {
549 : (void)nSize;
550 :
551 : SAL_WARN("basic", "UCBStream::SetSize not allowed to call from basic" );
552 0 : SetError( ERRCODE_IO_GENERAL );
553 0 : }
554 :
555 :
556 12 : SbError SbiStream::Open
557 : ( short nCh, const OString& rName, short nStrmMode, short nFlags, short nL )
558 : {
559 12 : nMode = nFlags;
560 12 : nLen = nL;
561 12 : nChan = nCh;
562 12 : nLine = 0;
563 12 : nExpandOnWriteTo = 0;
564 12 : if( ( nStrmMode & ( STREAM_READ|STREAM_WRITE ) ) == STREAM_READ )
565 : {
566 0 : nStrmMode |= STREAM_NOCREATE;
567 : }
568 12 : OUString aStr(OStringToOUString(rName, osl_getThreadTextEncoding()));
569 24 : OUString aNameStr = getFullPath( aStr );
570 :
571 12 : if( hasUno() )
572 : {
573 12 : Reference< XSimpleFileAccess3 > xSFI( SimpleFileAccess::create( comphelper::getProcessComponentContext() ) );
574 : try
575 : {
576 :
577 : // #??? For write access delete file if it already exists (not for appending)
578 48 : if( (nStrmMode & STREAM_WRITE) != 0 && !IsAppend() && !IsBinary() &&
579 24 : xSFI->exists( aNameStr ) && !xSFI->isFolder( aNameStr ) )
580 : {
581 0 : xSFI->kill( aNameStr );
582 : }
583 :
584 12 : if( (nStrmMode & (STREAM_READ | STREAM_WRITE)) == (STREAM_READ | STREAM_WRITE) )
585 : {
586 0 : Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
587 0 : pStrm = new UCBStream( xIS );
588 : }
589 12 : else if( nStrmMode & STREAM_WRITE )
590 : {
591 12 : Reference< XStream > xIS = xSFI->openFileReadWrite( aNameStr );
592 12 : pStrm = new UCBStream( xIS );
593 : }
594 : else //if( nStrmMode & STREAM_READ )
595 : {
596 0 : Reference< XInputStream > xIS = xSFI->openFileRead( aNameStr );
597 0 : pStrm = new UCBStream( xIS );
598 : }
599 :
600 : }
601 0 : catch(const Exception & )
602 : {
603 0 : nError = ERRCODE_IO_GENERAL;
604 12 : }
605 : }
606 :
607 12 : if( !pStrm )
608 : {
609 0 : pStrm = new OslStream( aNameStr, nStrmMode );
610 : }
611 12 : if( IsAppend() )
612 : {
613 0 : pStrm->Seek( STREAM_SEEK_TO_END );
614 : }
615 12 : MapError();
616 12 : if( nError )
617 : {
618 0 : delete pStrm, pStrm = NULL;
619 : }
620 24 : return nError;
621 : }
622 :
623 12 : SbError SbiStream::Close()
624 : {
625 12 : if( pStrm )
626 : {
627 12 : MapError();
628 12 : delete pStrm;
629 12 : pStrm = NULL;
630 : }
631 12 : nChan = 0;
632 12 : return nError;
633 : }
634 :
635 0 : SbError SbiStream::Read(OString& rBuf, sal_uInt16 n, bool bForceReadingPerByte)
636 : {
637 0 : nExpandOnWriteTo = 0;
638 0 : if( !bForceReadingPerByte && IsText() )
639 : {
640 0 : pStrm->ReadLine(rBuf);
641 0 : nLine++;
642 : }
643 : else
644 : {
645 0 : if( !n )
646 : {
647 0 : n = nLen;
648 : }
649 0 : if( !n )
650 : {
651 0 : return nError = SbERR_BAD_RECORD_LENGTH;
652 : }
653 0 : OStringBuffer aBuffer(read_uInt8s_ToOString(*pStrm, n));
654 : //Pad it out with ' ' to the requested length on short read
655 0 : sal_Int32 nRequested = sal::static_int_cast<sal_Int32>(n);
656 0 : comphelper::string::padToLength(aBuffer, nRequested, ' ');
657 0 : rBuf = aBuffer.makeStringAndClear();
658 : }
659 0 : MapError();
660 0 : if( !nError && pStrm->IsEof() )
661 : {
662 0 : nError = SbERR_READ_PAST_EOF;
663 : }
664 0 : return nError;
665 : }
666 :
667 0 : SbError SbiStream::Read( char& ch )
668 : {
669 0 : nExpandOnWriteTo = 0;
670 0 : if (aLine.isEmpty())
671 : {
672 0 : Read( aLine, 0 );
673 0 : aLine = aLine + OString('\n');
674 : }
675 0 : ch = aLine[0];
676 0 : aLine = aLine.copy(1);
677 0 : return nError;
678 : }
679 :
680 183 : void SbiStream::ExpandFile()
681 : {
682 183 : if ( nExpandOnWriteTo )
683 : {
684 0 : sal_uIntPtr nCur = pStrm->Seek(STREAM_SEEK_TO_END);
685 0 : if( nCur < nExpandOnWriteTo )
686 : {
687 0 : sal_uIntPtr nDiff = nExpandOnWriteTo - nCur;
688 0 : char c = 0;
689 0 : while( nDiff-- )
690 : {
691 0 : *pStrm << c;
692 : }
693 : }
694 : else
695 : {
696 0 : pStrm->Seek( nExpandOnWriteTo );
697 : }
698 0 : nExpandOnWriteTo = 0;
699 : }
700 183 : }
701 :
702 : namespace
703 : {
704 92 : void WriteLines(SvStream &rStream, const OString& rStr)
705 : {
706 92 : OString aStr(convertLineEnd(rStr, rStream.GetLineDelimiter()) );
707 92 : write_uInt8s_FromOString(rStream, aStr);
708 92 : endl( rStream );
709 92 : }
710 : }
711 :
712 183 : SbError SbiStream::Write( const OString& rBuf, sal_uInt16 n )
713 : {
714 183 : ExpandFile();
715 183 : if( IsAppend() )
716 : {
717 0 : pStrm->Seek( STREAM_SEEK_TO_END );
718 : }
719 183 : if( IsText() )
720 : {
721 183 : aLine = aLine + rBuf;
722 : // Get it out, if the end is an LF, but strip CRLF before,
723 : // because the SvStrm adds a CRLF!
724 183 : sal_Int32 nLineLen = aLine.getLength();
725 183 : if (nLineLen && aLine[--nLineLen] == 0x0A)
726 : {
727 92 : aLine = aLine.copy(0, nLineLen);
728 92 : if (nLineLen && aLine[--nLineLen] == 0x0D)
729 : {
730 0 : aLine = aLine.copy(0, nLineLen);
731 : }
732 92 : WriteLines(*pStrm, aLine);
733 92 : aLine = OString();
734 : }
735 : }
736 : else
737 : {
738 0 : if( !n )
739 : {
740 0 : n = nLen;
741 : }
742 0 : if( !n )
743 : {
744 0 : return nError = SbERR_BAD_RECORD_LENGTH;
745 : }
746 0 : pStrm->Write(rBuf.getStr(), n);
747 0 : MapError();
748 : }
749 183 : return nError;
750 : }
751 :
752 :
753 :
754 0 : SbiIoSystem* SbGetIoSystem()
755 : {
756 0 : SbiInstance* pInst = GetSbData()->pInst;
757 0 : return pInst ? pInst->GetIoSystem() : NULL;
758 : }
759 :
760 :
761 54 : SbiIoSystem::SbiIoSystem()
762 : {
763 13878 : for( short i = 0; i < CHANNELS; i++ )
764 : {
765 13824 : pChan[ i ] = NULL;
766 : }
767 54 : nChan = 0;
768 54 : nError = 0;
769 54 : }
770 :
771 108 : SbiIoSystem::~SbiIoSystem()
772 : {
773 54 : Shutdown();
774 54 : }
775 :
776 320 : SbError SbiIoSystem::GetError()
777 : {
778 320 : SbError n = nError; nError = 0;
779 320 : return n;
780 : }
781 :
782 12 : void SbiIoSystem::Open(short nCh, const OString& rName, short nMode, short nFlags, short nLen)
783 : {
784 12 : nError = 0;
785 12 : if( nCh >= CHANNELS || !nCh )
786 : {
787 0 : nError = SbERR_BAD_CHANNEL;
788 : }
789 12 : else if( pChan[ nCh ] )
790 : {
791 0 : nError = SbERR_FILE_ALREADY_OPEN;
792 : }
793 : else
794 : {
795 12 : pChan[ nCh ] = new SbiStream;
796 12 : nError = pChan[ nCh ]->Open( nCh, rName, nMode, nFlags, nLen );
797 12 : if( nError )
798 : {
799 0 : delete pChan[ nCh ], pChan[ nCh ] = NULL;
800 : }
801 : }
802 12 : nChan = 0;
803 12 : }
804 :
805 :
806 11 : void SbiIoSystem::Close()
807 : {
808 11 : if( !nChan )
809 : {
810 0 : nError = SbERR_BAD_CHANNEL;
811 : }
812 11 : else if( !pChan[ nChan ] )
813 : {
814 0 : nError = SbERR_BAD_CHANNEL;
815 : }
816 : else
817 : {
818 11 : nError = pChan[ nChan ]->Close();
819 11 : delete pChan[ nChan ];
820 11 : pChan[ nChan ] = NULL;
821 : }
822 11 : nChan = 0;
823 11 : }
824 :
825 :
826 54 : void SbiIoSystem::Shutdown()
827 : {
828 13824 : for( short i = 1; i < CHANNELS; i++ )
829 : {
830 13770 : if( pChan[ i ] )
831 : {
832 1 : SbError n = pChan[ i ]->Close();
833 1 : delete pChan[ i ];
834 1 : pChan[ i ] = NULL;
835 1 : if( n && !nError )
836 : {
837 0 : nError = n;
838 : }
839 : }
840 : }
841 54 : nChan = 0;
842 : // anything left to PRINT?
843 54 : if( !aOut.isEmpty() )
844 : {
845 0 : OUString aOutStr(OStringToOUString(aOut, osl_getThreadTextEncoding()));
846 : #if defined __GNUC__
847 0 : Window* pParent = Application::GetDefDialogParent();
848 0 : MessBox( pParent, WinBits( WB_OK ), OUString(), aOutStr ).Execute();
849 : #else
850 : MessBox( GetpApp()->GetDefDialogParent(), WinBits( WB_OK ), OUString(), aOutStr ).Execute();
851 : #endif
852 : }
853 54 : aOut = OString();
854 54 : }
855 :
856 :
857 0 : void SbiIoSystem::Read(OString& rBuf, short n)
858 : {
859 0 : if( !nChan )
860 : {
861 0 : ReadCon( rBuf );
862 : }
863 0 : else if( !pChan[ nChan ] )
864 : {
865 0 : nError = SbERR_BAD_CHANNEL;
866 : }
867 : else
868 : {
869 0 : nError = pChan[ nChan ]->Read( rBuf, n );
870 : }
871 0 : }
872 :
873 0 : char SbiIoSystem::Read()
874 : {
875 0 : char ch = ' ';
876 0 : if( !nChan )
877 : {
878 0 : if( aIn.isEmpty() )
879 : {
880 0 : ReadCon( aIn );
881 0 : aIn = aIn + OString('\n');
882 : }
883 0 : ch = aIn[0];
884 0 : aIn = aIn.copy(1);
885 : }
886 0 : else if( !pChan[ nChan ] )
887 : {
888 0 : nError = SbERR_BAD_CHANNEL;
889 : }
890 : else
891 : {
892 0 : nError = pChan[ nChan ]->Read( ch );
893 : }
894 0 : return ch;
895 : }
896 :
897 183 : void SbiIoSystem::Write(const OString& rBuf, short n)
898 : {
899 183 : if( !nChan )
900 : {
901 0 : WriteCon( rBuf );
902 : }
903 183 : else if( !pChan[ nChan ] )
904 : {
905 0 : nError = SbERR_BAD_CHANNEL;
906 : }
907 : else
908 : {
909 183 : nError = pChan[ nChan ]->Write( rBuf, n );
910 : }
911 183 : }
912 :
913 : // nChannel == 0..CHANNELS-1
914 :
915 33 : SbiStream* SbiIoSystem::GetStream( short nChannel ) const
916 : {
917 33 : SbiStream* pRet = 0;
918 33 : if( nChannel >= 0 && nChannel < CHANNELS )
919 : {
920 33 : pRet = pChan[ nChannel ];
921 : }
922 33 : return pRet;
923 : }
924 :
925 0 : void SbiIoSystem::CloseAll(void)
926 : {
927 0 : for( short i = 1; i < CHANNELS; i++ )
928 : {
929 0 : if( pChan[ i ] )
930 : {
931 0 : SbError n = pChan[ i ]->Close();
932 0 : delete pChan[ i ];
933 0 : pChan[ i ] = NULL;
934 0 : if( n && !nError )
935 : {
936 0 : nError = n;
937 : }
938 : }
939 : }
940 0 : }
941 :
942 : /***************************************************************************
943 : *
944 : * Console Support
945 : *
946 : ***************************************************************************/
947 :
948 :
949 0 : void SbiIoSystem::ReadCon(OString& rIn)
950 : {
951 0 : OUString aPromptStr(OStringToOUString(aPrompt, osl_getThreadTextEncoding()));
952 0 : SbiInputDialog aDlg( NULL, aPromptStr );
953 0 : if( aDlg.Execute() )
954 : {
955 0 : rIn = OUStringToOString(aDlg.GetInput(), osl_getThreadTextEncoding());
956 : }
957 : else
958 : {
959 0 : nError = SbERR_USER_ABORT;
960 : }
961 0 : aPrompt = OString();
962 0 : }
963 :
964 : // output of a MessageBox, if theres a CR in the console-buffer
965 :
966 0 : void SbiIoSystem::WriteCon(const OString& rText)
967 : {
968 0 : aOut += rText;
969 0 : sal_Int32 n1 = aOut.indexOf('\n');
970 0 : sal_Int32 n2 = aOut.indexOf('\r');
971 0 : if( n1 != -1 || n2 != -1 )
972 : {
973 0 : if( n1 == -1 )
974 : {
975 0 : n1 = n2;
976 : }
977 0 : else if( n2 == -1 )
978 : {
979 0 : n2 = n1;
980 : }
981 0 : if( n1 > n2 )
982 : {
983 0 : n1 = n2;
984 : }
985 0 : OString s(aOut.copy(0, n1));
986 0 : aOut = aOut.copy(n1);
987 0 : while (aOut[0] == '\n' || aOut[0] == '\r')
988 : {
989 0 : aOut = aOut.copy(1);
990 : }
991 0 : OUString aStr(OStringToOUString(s, osl_getThreadTextEncoding()));
992 : {
993 0 : SolarMutexGuard aSolarGuard;
994 0 : if( !MessBox( GetpApp()->GetDefDialogParent(),
995 : WinBits( WB_OK_CANCEL | WB_DEF_OK ),
996 0 : OUString(), aStr ).Execute() )
997 : {
998 0 : nError = SbERR_USER_ABORT;
999 0 : }
1000 0 : }
1001 : }
1002 429 : }
1003 :
1004 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|