Avoid potential negative array index access to cached text.
[LibreOffice.git] / extensions / source / scanner / scanunx.cxx
blob0db920c4c9517c005f573789b345ee1a26850f3a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "scanner.hxx"
21 #include "sanedlg.hxx"
22 #include <o3tl/safeint.hxx>
23 #include <osl/thread.hxx>
24 #include <sal/log.hxx>
25 #include <utility>
26 #include <vcl/svapp.hxx>
27 #include <memory>
29 #include <com/sun/star/scanner/ScannerException.hpp>
31 BitmapTransporter::BitmapTransporter()
33 SAL_INFO("extensions.scanner", "BitmapTransporter");
37 BitmapTransporter::~BitmapTransporter()
39 SAL_INFO("extensions.scanner", "~BitmapTransporter");
43 css::awt::Size BitmapTransporter::getSize()
45 osl::MutexGuard aGuard( m_aProtector );
46 css::awt::Size aRet;
48 // ensure that there is at least a header
49 int nLen = m_aStream.TellEnd();
50 if( nLen > 15 )
52 int nPreviousPos = m_aStream.Tell();
53 m_aStream.Seek( 4 );
54 m_aStream.ReadInt32( aRet.Width ).ReadInt32( aRet.Height );
55 m_aStream.Seek( nPreviousPos );
57 else
58 aRet.Width = aRet.Height = 0;
61 return aRet;
65 Sequence< sal_Int8 > BitmapTransporter::getDIB()
67 osl::MutexGuard aGuard( m_aProtector );
68 int nPreviousPos = m_aStream.Tell();
70 // create return value
71 int nBytes = m_aStream.TellEnd();
72 m_aStream.Seek( 0 );
74 Sequence< sal_Int8 > aValue( nBytes );
75 m_aStream.ReadBytes( aValue.getArray(), nBytes );
76 m_aStream.Seek( nPreviousPos );
78 return aValue;
81 namespace {
83 struct SaneHolder
85 Sane m_aSane;
86 Reference< css::awt::XBitmap > m_xBitmap;
87 osl::Mutex m_aProtector;
88 ScanError m_nError;
89 bool m_bBusy;
91 SaneHolder() : m_nError(ScanError_ScanErrorNone), m_bBusy(false) {}
94 typedef std::vector< std::shared_ptr<SaneHolder> > sanevec;
95 class allSanes
97 private:
98 int mnRefCount;
99 public:
100 sanevec m_aSanes;
101 allSanes() : mnRefCount(0) {}
102 void acquire();
103 void release();
106 void allSanes::acquire()
108 ++mnRefCount;
111 void allSanes::release()
113 // was unused, now because of i99835: "Scanning interface not SANE API
114 // compliant" destroy all SaneHolder to get Sane Dtor called
115 --mnRefCount;
116 if (!mnRefCount)
117 m_aSanes.clear();
120 struct theSaneProtector : public rtl::Static<osl::Mutex, theSaneProtector> {};
121 struct theSanes : public rtl::Static<allSanes, theSanes> {};
123 class ScannerThread : public osl::Thread
125 std::shared_ptr<SaneHolder> m_pHolder;
126 Reference< css::lang::XEventListener > m_xListener;
127 ScannerManager* m_pManager; // just for the disposing call
129 public:
130 virtual void SAL_CALL run() override;
131 virtual void SAL_CALL onTerminated() override { delete this; }
132 public:
133 ScannerThread( std::shared_ptr<SaneHolder> pHolder,
134 const Reference< css::lang::XEventListener >& listener,
135 ScannerManager* pManager );
136 virtual ~ScannerThread() override;
141 ScannerThread::ScannerThread(std::shared_ptr<SaneHolder> pHolder,
142 const Reference< css::lang::XEventListener >& listener,
143 ScannerManager* pManager)
144 : m_pHolder(std::move( pHolder )), m_xListener( listener ), m_pManager( pManager )
146 SAL_INFO("extensions.scanner", "ScannerThread");
150 ScannerThread::~ScannerThread()
152 SAL_INFO("extensions.scanner", "~ScannerThread");
156 void ScannerThread::run()
158 osl_setThreadName("ScannerThread");
160 osl::MutexGuard aGuard( m_pHolder->m_aProtector );
161 rtl::Reference<BitmapTransporter> pTransporter = new BitmapTransporter;
163 m_pHolder->m_xBitmap = pTransporter;
165 m_pHolder->m_bBusy = true;
166 if( m_pHolder->m_aSane.IsOpen() )
168 int nOption = m_pHolder->m_aSane.GetOptionByName( "preview" );
169 if( nOption != -1 )
170 m_pHolder->m_aSane.SetOptionValue( nOption, false );
172 m_pHolder->m_nError =
173 m_pHolder->m_aSane.Start( *pTransporter ) ?
174 ScanError_ScanErrorNone : ScanError_ScanCanceled;
176 else
177 m_pHolder->m_nError = ScanError_ScannerNotAvailable;
180 Reference< XInterface > xXInterface( static_cast< OWeakObject* >( m_pManager ) );
181 m_xListener->disposing( css::lang::EventObject(xXInterface) );
182 m_pHolder->m_bBusy = false;
186 void ScannerManager::AcquireData()
188 osl::MutexGuard aGuard( theSaneProtector::get() );
189 theSanes::get().acquire();
193 void ScannerManager::ReleaseData()
195 osl::MutexGuard aGuard( theSaneProtector::get() );
196 theSanes::get().release();
200 css::awt::Size ScannerManager::getSize()
202 css::awt::Size aRet;
203 aRet.Width = aRet.Height = 0;
204 return aRet;
208 Sequence< sal_Int8 > ScannerManager::getDIB()
210 return Sequence< sal_Int8 >();
214 Sequence< ScannerContext > ScannerManager::getAvailableScanners()
216 osl::MutexGuard aGuard( theSaneProtector::get() );
217 sanevec &rSanes = theSanes::get().m_aSanes;
219 if( rSanes.empty() )
221 auto pSaneHolder = std::make_shared<SaneHolder>();
222 if( Sane::IsSane() )
223 rSanes.push_back( pSaneHolder );
226 if( Sane::IsSane() )
228 Sequence< ScannerContext > aRet{ { /* ScannerName */ "SANE", /* InternalData */ 0 } };
229 return aRet;
232 return Sequence< ScannerContext >();
236 sal_Bool ScannerManager::configureScannerAndScan( ScannerContext& scanner_context,
237 const Reference< css::lang::XEventListener >& listener )
239 bool bRet;
240 bool bScan;
242 osl::MutexGuard aGuard( theSaneProtector::get() );
243 sanevec &rSanes = theSanes::get().m_aSanes;
245 SAL_INFO("extensions.scanner", "ScannerManager::configureScanner");
247 if( scanner_context.InternalData < 0 || o3tl::make_unsigned(scanner_context.InternalData) >= rSanes.size() )
248 throw ScannerException(
249 "Scanner does not exist",
250 Reference< XScannerManager >( this ),
251 ScanError_InvalidContext
254 std::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
255 if( pHolder->m_bBusy )
256 throw ScannerException(
257 "Scanner is busy",
258 Reference< XScannerManager >( this ),
259 ScanError_ScanInProgress
262 pHolder->m_bBusy = true;
263 SaneDlg aDlg(Application::GetFrameWeld(mxDialogParent), pHolder->m_aSane, listener.is());
264 bRet = aDlg.run();
265 bScan = aDlg.getDoScan();
266 pHolder->m_bBusy = false;
268 if ( bScan )
269 startScan( scanner_context, listener );
271 return bRet;
275 void ScannerManager::startScan( const ScannerContext& scanner_context,
276 const Reference< css::lang::XEventListener >& listener )
278 osl::MutexGuard aGuard( theSaneProtector::get() );
279 sanevec &rSanes = theSanes::get().m_aSanes;
281 SAL_INFO("extensions.scanner", "ScannerManager::startScan");
283 if( scanner_context.InternalData < 0 || o3tl::make_unsigned(scanner_context.InternalData) >= rSanes.size() )
284 throw ScannerException(
285 "Scanner does not exist",
286 Reference< XScannerManager >( this ),
287 ScanError_InvalidContext
289 std::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
290 if( pHolder->m_bBusy )
291 throw ScannerException(
292 "Scanner is busy",
293 Reference< XScannerManager >( this ),
294 ScanError_ScanInProgress
296 pHolder->m_bBusy = true;
298 ScannerThread* pThread = new ScannerThread( pHolder, listener, this );
299 pThread->create();
303 ScanError ScannerManager::getError( const ScannerContext& scanner_context )
305 osl::MutexGuard aGuard( theSaneProtector::get() );
306 sanevec &rSanes = theSanes::get().m_aSanes;
308 if( scanner_context.InternalData < 0 || o3tl::make_unsigned(scanner_context.InternalData) >= rSanes.size() )
309 throw ScannerException(
310 "Scanner does not exist",
311 Reference< XScannerManager >( this ),
312 ScanError_InvalidContext
315 std::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
317 return pHolder->m_nError;
321 Reference< css::awt::XBitmap > ScannerManager::getBitmap( const ScannerContext& scanner_context )
323 osl::MutexGuard aGuard( theSaneProtector::get() );
324 sanevec &rSanes = theSanes::get().m_aSanes;
326 if( scanner_context.InternalData < 0 || o3tl::make_unsigned(scanner_context.InternalData) >= rSanes.size() )
327 throw ScannerException(
328 "Scanner does not exist",
329 Reference< XScannerManager >( this ),
330 ScanError_InvalidContext
332 std::shared_ptr<SaneHolder> pHolder = rSanes[scanner_context.InternalData];
334 osl::MutexGuard aProtGuard( pHolder->m_aProtector );
336 Reference< css::awt::XBitmap > xRet( pHolder->m_xBitmap );
337 pHolder->m_xBitmap.clear();
339 return xRet;
342 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */