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