/src/libreoffice/connectivity/source/drivers/file/FConnection.cxx
Line | Count | Source (jump to first uncovered line) |
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 <sal/config.h> |
21 | | |
22 | | #include <comphelper/processfactory.hxx> |
23 | | #include <comphelper/servicehelper.hxx> |
24 | | #include <file/FConnection.hxx> |
25 | | #include <file/FDatabaseMetaData.hxx> |
26 | | #include <file/FDriver.hxx> |
27 | | #include <file/FStatement.hxx> |
28 | | #include <file/FPreparedStatement.hxx> |
29 | | #include <com/sun/star/container/XChild.hpp> |
30 | | #include <com/sun/star/ucb/ContentCreationException.hpp> |
31 | | #include <com/sun/star/ucb/XContent.hpp> |
32 | | #include <com/sun/star/ucb/XContentIdentifier.hpp> |
33 | | #include <tools/urlobj.hxx> |
34 | | #include <file/FCatalog.hxx> |
35 | | #include <comphelper/configuration.hxx> |
36 | | #include <unotools/pathoptions.hxx> |
37 | | #include <ucbhelper/content.hxx> |
38 | | #include <connectivity/dbcharset.hxx> |
39 | | #include <connectivity/dbexception.hxx> |
40 | | #include <o3tl/any.hxx> |
41 | | #include <osl/thread.h> |
42 | | #include <strings.hrc> |
43 | | |
44 | | using namespace connectivity::file; |
45 | | using namespace dbtools; |
46 | | |
47 | | using namespace com::sun::star::uno; |
48 | | using namespace com::sun::star::lang; |
49 | | using namespace com::sun::star::beans; |
50 | | using namespace com::sun::star::sdbc; |
51 | | using namespace com::sun::star::sdbcx; |
52 | | using namespace com::sun::star::container; |
53 | | using namespace com::sun::star::ucb; |
54 | | using namespace ::ucbhelper; |
55 | | typedef connectivity::OMetaConnection OConnection_BASE; |
56 | | |
57 | | OConnection::OConnection(OFileDriver* _pDriver) |
58 | 9.91k | : m_pDriver(_pDriver) |
59 | 9.91k | , m_bAutoCommit(false) |
60 | 9.91k | , m_bReadOnly(false) |
61 | 9.91k | , m_bShowDeleted(false) |
62 | 9.91k | , m_bCaseSensitiveExtension( true ) |
63 | 9.91k | , m_bCheckSQL92(false) |
64 | 9.91k | , m_bDefaultTextEncoding(false) |
65 | 9.91k | { |
66 | 9.91k | m_nTextEncoding = RTL_TEXTENCODING_DONTKNOW; |
67 | 9.91k | } |
68 | | |
69 | | OConnection::~OConnection() |
70 | 9.91k | { |
71 | 9.91k | if(!isClosed( )) |
72 | 0 | close(); |
73 | 9.91k | } |
74 | | |
75 | | bool OConnection::matchesExtension( const OUString& _rExt ) const |
76 | 39.2k | { |
77 | 39.2k | if ( isCaseSensitiveExtension() ) |
78 | 39.2k | return ( getExtension() == _rExt ); |
79 | | |
80 | 0 | OUString sMyExtension( getExtension().toAsciiLowerCase() ); |
81 | 0 | OUString sExt( _rExt.toAsciiLowerCase() ); |
82 | |
|
83 | 0 | return sMyExtension == sExt; |
84 | 39.2k | } |
85 | | |
86 | | |
87 | | void OConnection::construct(const OUString& url,const Sequence< PropertyValue >& info) |
88 | 9.91k | { |
89 | 9.91k | osl_atomic_increment( &m_refCount ); |
90 | | |
91 | 9.91k | OUString aExt; |
92 | 9.91k | const PropertyValue *pIter = info.getConstArray(); |
93 | 9.91k | const PropertyValue *pEnd = pIter + info.getLength(); |
94 | 29.7k | for(;pIter != pEnd;++pIter) |
95 | 19.8k | { |
96 | 19.8k | if( pIter->Name == "Extension" ) |
97 | 9.91k | OSL_VERIFY( pIter->Value >>= aExt ); |
98 | 9.91k | else if( pIter->Name == "CharSet" ) |
99 | 9.91k | { |
100 | 9.91k | if (auto const numeric = o3tl::tryAccess<sal_uInt16>(pIter->Value)) |
101 | 9.91k | { |
102 | 9.91k | m_nTextEncoding = *numeric; |
103 | 9.91k | } |
104 | 0 | else |
105 | 0 | { |
106 | 0 | OUString sIanaName; |
107 | 0 | OSL_VERIFY( pIter->Value >>= sIanaName ); |
108 | |
|
109 | 0 | ::dbtools::OCharsetMap aLookupIanaName; |
110 | 0 | ::dbtools::OCharsetMap::const_iterator aLookup = aLookupIanaName.findIanaName(sIanaName); |
111 | 0 | if (aLookup != aLookupIanaName.end()) |
112 | 0 | m_nTextEncoding = (*aLookup).getEncoding(); |
113 | 0 | else |
114 | 0 | m_nTextEncoding = RTL_TEXTENCODING_DONTKNOW; |
115 | 0 | } |
116 | 9.91k | } |
117 | 0 | else if( pIter->Name == "ShowDeleted" ) |
118 | 0 | { |
119 | 0 | OSL_VERIFY( pIter->Value >>= m_bShowDeleted ); |
120 | 0 | } |
121 | 0 | else if( pIter->Name == "EnableSQL92Check" ) |
122 | 0 | { |
123 | 0 | pIter->Value >>= m_bCheckSQL92; |
124 | 0 | } |
125 | 19.8k | } // for(;pIter != pEnd;++pIter) |
126 | | |
127 | 9.91k | { |
128 | 9.91k | sal_Int32 nLen = url.indexOf(':'); |
129 | 9.91k | nLen = url.indexOf(':',nLen+1); |
130 | 9.91k | OUString aDSN(url.copy(nLen+1)); |
131 | | |
132 | 9.91k | OUString aFileName = aDSN; |
133 | 9.91k | INetURLObject aURL; |
134 | 9.91k | aURL.SetSmartProtocol(INetProtocol::File); |
135 | 9.91k | if (!comphelper::IsFuzzing()) |
136 | 0 | { |
137 | 0 | SvtPathOptions aPathOptions; |
138 | 0 | aFileName = aPathOptions.SubstituteVariable(aFileName); |
139 | 0 | } |
140 | | |
141 | 9.91k | aURL.SetSmartURL(aFileName); |
142 | | |
143 | 9.91k | setURL(aURL.GetMainURL(INetURLObject::DecodeMechanism::NONE)); |
144 | 9.91k | } |
145 | | |
146 | 9.91k | if ( m_nTextEncoding == RTL_TEXTENCODING_DONTKNOW ) |
147 | 0 | { |
148 | | //m_nTextEncoding = osl_getTextEncodingFromLocale(NULL); |
149 | 0 | m_nTextEncoding = osl_getThreadTextEncoding(); |
150 | 0 | m_bDefaultTextEncoding = true; |
151 | 0 | } |
152 | | |
153 | 9.91k | if ( !aExt.isEmpty() ) |
154 | 9.91k | m_aFilenameExtension = aExt; |
155 | | |
156 | 9.91k | try |
157 | 9.91k | { |
158 | 9.91k | ::ucbhelper::Content aFile; |
159 | 9.91k | try |
160 | 9.91k | { |
161 | 9.91k | aFile = ::ucbhelper::Content(getURL(), Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext()); |
162 | 9.91k | } |
163 | 9.91k | catch(ContentCreationException& e) |
164 | 9.91k | { |
165 | 0 | throwUrlNotValid(getURL(),e.Message); |
166 | 0 | } |
167 | | |
168 | | // set fields to fetch |
169 | 9.91k | Sequence< OUString > aProps { u"Title"_ustr }; |
170 | | |
171 | 9.91k | try |
172 | 9.91k | { |
173 | 9.91k | if (aFile.isFolder()) |
174 | 9.91k | { |
175 | 9.91k | m_xDir = aFile.createDynamicCursor(aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ); |
176 | 9.91k | m_xContent = aFile.get(); |
177 | 9.91k | } |
178 | 0 | else if (aFile.isDocument()) |
179 | 0 | { |
180 | 0 | Reference<XContent> xParent(Reference<XChild>(aFile.get(),UNO_QUERY_THROW)->getParent(),UNO_QUERY_THROW); |
181 | 0 | Reference<XContentIdentifier> xIdent = xParent->getIdentifier(); |
182 | 0 | m_xContent = std::move(xParent); |
183 | |
|
184 | 0 | ::ucbhelper::Content aParent(xIdent->getContentIdentifier(), Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext()); |
185 | 0 | m_xDir = aParent.createDynamicCursor(aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ); |
186 | 0 | } |
187 | 0 | else |
188 | 0 | { |
189 | 0 | OSL_FAIL("OConnection::construct: ::ucbhelper::Content is neither a folder nor a document! How's that?!"); |
190 | 0 | throw SQLException(); |
191 | 0 | } |
192 | 9.91k | } |
193 | 9.91k | catch(Exception& e) // an exception is thrown when no file exists |
194 | 9.91k | { |
195 | 0 | throwUrlNotValid(getURL(),e.Message); |
196 | 0 | } |
197 | 9.91k | if(!m_xDir.is() || !m_xContent.is()) |
198 | 0 | throwUrlNotValid(getURL(),OUString()); |
199 | | |
200 | 9.91k | if (m_aFilenameExtension.indexOf('*') >= 0 || m_aFilenameExtension.indexOf('?') >= 0) |
201 | 0 | throw SQLException(); |
202 | 9.91k | } |
203 | 9.91k | catch(const Exception&) |
204 | 9.91k | { |
205 | 0 | osl_atomic_decrement( &m_refCount ); |
206 | 0 | throw; |
207 | 0 | } |
208 | | |
209 | 9.91k | osl_atomic_decrement( &m_refCount ); |
210 | 9.91k | } |
211 | | // XServiceInfo |
212 | | |
213 | | IMPLEMENT_SERVICE_INFO(OConnection, u"com.sun.star.sdbc.drivers.file.Connection"_ustr, u"com.sun.star.sdbc.Connection"_ustr) |
214 | | |
215 | | |
216 | | Reference< XStatement > SAL_CALL OConnection::createStatement( ) |
217 | 0 | { |
218 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
219 | 0 | checkDisposed(OConnection_BASE::rBHelper.bDisposed); |
220 | | |
221 | |
|
222 | 0 | Reference< XStatement > xReturn = new OStatement(this); |
223 | 0 | m_aStatements.push_back(WeakReferenceHelper(xReturn)); |
224 | 0 | return xReturn; |
225 | 0 | } |
226 | | |
227 | | Reference< XPreparedStatement > SAL_CALL OConnection::prepareStatement( const OUString& sql ) |
228 | 0 | { |
229 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
230 | 0 | checkDisposed(OConnection_BASE::rBHelper.bDisposed); |
231 | | |
232 | |
|
233 | 0 | rtl::Reference<OPreparedStatement> pStmt = new OPreparedStatement(this); |
234 | 0 | pStmt->construct(sql); |
235 | 0 | m_aStatements.push_back(WeakReferenceHelper(*pStmt)); |
236 | 0 | return pStmt; |
237 | 0 | } |
238 | | |
239 | | Reference< XPreparedStatement > SAL_CALL OConnection::prepareCall( const OUString& /*sql*/ ) |
240 | 0 | { |
241 | 0 | throwFeatureNotImplementedSQLException( u"XConnection::prepareCall"_ustr, *this ); |
242 | 0 | } |
243 | | |
244 | | OUString SAL_CALL OConnection::nativeSQL( const OUString& sql ) |
245 | 0 | { |
246 | 0 | return sql; |
247 | 0 | } |
248 | | |
249 | | void SAL_CALL OConnection::setAutoCommit( sal_Bool autoCommit ) |
250 | 0 | { |
251 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
252 | 0 | checkDisposed(OConnection_BASE::rBHelper.bDisposed); |
253 | |
|
254 | 0 | m_bAutoCommit = autoCommit; |
255 | 0 | } |
256 | | |
257 | | sal_Bool SAL_CALL OConnection::getAutoCommit( ) |
258 | 0 | { |
259 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
260 | 0 | checkDisposed(OConnection_BASE::rBHelper.bDisposed); |
261 | |
|
262 | 0 | return m_bAutoCommit; |
263 | 0 | } |
264 | | |
265 | | void SAL_CALL OConnection::commit( ) |
266 | 0 | { |
267 | 0 | } |
268 | | |
269 | | void SAL_CALL OConnection::rollback( ) |
270 | 0 | { |
271 | 0 | } |
272 | | |
273 | | sal_Bool SAL_CALL OConnection::isClosed( ) |
274 | 9.91k | { |
275 | 9.91k | ::osl::MutexGuard aGuard( m_aMutex ); |
276 | | |
277 | 9.91k | return OConnection_BASE::rBHelper.bDisposed; |
278 | 9.91k | } |
279 | | |
280 | | Reference< XDatabaseMetaData > SAL_CALL OConnection::getMetaData( ) |
281 | 0 | { |
282 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
283 | 0 | checkDisposed(OConnection_BASE::rBHelper.bDisposed); |
284 | | |
285 | |
|
286 | 0 | Reference< XDatabaseMetaData > xMetaData = m_xMetaData; |
287 | 0 | if(!xMetaData.is()) |
288 | 0 | { |
289 | 0 | xMetaData = new ODatabaseMetaData(this); |
290 | 0 | m_xMetaData = xMetaData; |
291 | 0 | } |
292 | |
|
293 | 0 | return xMetaData; |
294 | 0 | } |
295 | | |
296 | | void SAL_CALL OConnection::setReadOnly( sal_Bool readOnly ) |
297 | 0 | { |
298 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
299 | 0 | checkDisposed(OConnection_BASE::rBHelper.bDisposed); |
300 | | |
301 | |
|
302 | 0 | m_bReadOnly = readOnly; |
303 | 0 | } |
304 | | |
305 | | sal_Bool SAL_CALL OConnection::isReadOnly( ) |
306 | 0 | { |
307 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
308 | 0 | checkDisposed(OConnection_BASE::rBHelper.bDisposed); |
309 | | |
310 | |
|
311 | 0 | return m_bReadOnly; |
312 | 0 | } |
313 | | |
314 | | void SAL_CALL OConnection::setCatalog( const OUString& /*catalog*/ ) |
315 | 0 | { |
316 | 0 | throwFeatureNotImplementedSQLException( u"XConnection::setCatalog"_ustr, *this ); |
317 | 0 | } |
318 | | |
319 | | OUString SAL_CALL OConnection::getCatalog( ) |
320 | 0 | { |
321 | 0 | return OUString(); |
322 | 0 | } |
323 | | |
324 | | void SAL_CALL OConnection::setTransactionIsolation( sal_Int32 /*level*/ ) |
325 | 0 | { |
326 | 0 | throwFeatureNotImplementedSQLException( u"XConnection::setTransactionIsolation"_ustr, *this ); |
327 | 0 | } |
328 | | |
329 | | sal_Int32 SAL_CALL OConnection::getTransactionIsolation( ) |
330 | 0 | { |
331 | 0 | return 0; |
332 | 0 | } |
333 | | |
334 | | Reference< XNameAccess > SAL_CALL OConnection::getTypeMap( ) |
335 | 0 | { |
336 | 0 | return nullptr; |
337 | 0 | } |
338 | | |
339 | | void SAL_CALL OConnection::setTypeMap( const Reference< XNameAccess >& /*typeMap*/ ) |
340 | 0 | { |
341 | 0 | } |
342 | | |
343 | | // XCloseable |
344 | | void SAL_CALL OConnection::close( ) |
345 | 0 | { |
346 | 0 | { |
347 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
348 | 0 | checkDisposed(OConnection_BASE::rBHelper.bDisposed); |
349 | |
|
350 | 0 | } |
351 | 0 | dispose(); |
352 | 0 | } |
353 | | |
354 | | // XWarningsSupplier |
355 | | Any SAL_CALL OConnection::getWarnings( ) |
356 | 0 | { |
357 | 0 | return Any(); |
358 | 0 | } |
359 | | |
360 | | void SAL_CALL OConnection::clearWarnings( ) |
361 | 0 | { |
362 | 0 | } |
363 | | |
364 | | void OConnection::disposing() |
365 | 9.91k | { |
366 | 9.91k | ::osl::MutexGuard aGuard(m_aMutex); |
367 | 9.91k | OConnection_BASE::disposing(); |
368 | | |
369 | 9.91k | m_xDir.clear(); |
370 | 9.91k | m_xContent.clear(); |
371 | 9.91k | m_xCatalog.clear(); |
372 | 9.91k | } |
373 | | |
374 | | Reference< XTablesSupplier > OConnection::createCatalog() |
375 | 0 | { |
376 | 0 | ::osl::MutexGuard aGuard( m_aMutex ); |
377 | 0 | rtl::Reference< connectivity::sdbcx::OCatalog > xTab = m_xCatalog.get(); |
378 | 0 | if(!xTab.is()) |
379 | 0 | { |
380 | 0 | xTab = new OFileCatalog(this); |
381 | 0 | m_xCatalog = xTab.get(); |
382 | 0 | } |
383 | 0 | return xTab; |
384 | 0 | } |
385 | | |
386 | | Reference< XDynamicResultSet > OConnection::getDir() const |
387 | 98.0k | { |
388 | 98.0k | Reference<XDynamicResultSet> xContent; |
389 | 98.0k | Sequence< OUString > aProps { u"Title"_ustr }; |
390 | 98.0k | try |
391 | 98.0k | { |
392 | 98.0k | Reference<XContentIdentifier> xIdent = getContent()->getIdentifier(); |
393 | 98.0k | ::ucbhelper::Content aParent(xIdent->getContentIdentifier(), Reference< XCommandEnvironment >(), comphelper::getProcessComponentContext()); |
394 | 98.0k | xContent = aParent.createDynamicCursor(aProps, ::ucbhelper::INCLUDE_DOCUMENTS_ONLY ); |
395 | 98.0k | } |
396 | 98.0k | catch(Exception&) |
397 | 98.0k | { |
398 | 0 | } |
399 | 98.0k | return xContent; |
400 | 98.0k | } |
401 | | |
402 | | sal_Int64 SAL_CALL OConnection::getSomething( const Sequence< sal_Int8 >& rId ) |
403 | 0 | { |
404 | 0 | return comphelper::getSomethingImpl(rId, this); |
405 | 0 | } |
406 | | |
407 | | const Sequence< sal_Int8 > & OConnection::getUnoTunnelId() |
408 | 0 | { |
409 | 0 | static const comphelper::UnoIdInit implId; |
410 | 0 | return implId.getSeq(); |
411 | 0 | } |
412 | | |
413 | | void OConnection::throwUrlNotValid(const OUString & _rsUrl,const OUString & _rsMessage) |
414 | 0 | { |
415 | 0 | XConnection* context = this; |
416 | 0 | css::uno::Any next; |
417 | 0 | if (!_rsMessage.isEmpty()) |
418 | 0 | next <<= SQLException(_rsMessage, context, OUString(), 0, Any()); |
419 | 0 | SQLException aError( |
420 | 0 | getResources().getResourceStringWithSubstitution(STR_NO_VALID_FILE_URL, "$URL$", _rsUrl), |
421 | 0 | context, u"S1000"_ustr, 0, next); |
422 | |
|
423 | 0 | throw aError; |
424 | 0 | } |
425 | | |
426 | | |
427 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |