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