tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / extensions / source / update / check / updatecheckconfig.cxx
blob718a33539523473640135260f8c43aef5e1bff8e
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 "updatecheckconfig.hxx"
21 #include "updatecheck.hxx"
22 #include <com/sun/star/beans/PropertyValue.hpp>
23 #include <com/sun/star/beans/XPropertySet.hpp>
24 #include <com/sun/star/configuration/theDefaultProvider.hpp>
25 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
26 #include <cppuhelper/supportsservice.hxx>
27 #include <osl/security.hxx>
28 #include <osl/time.h>
29 #include <osl/diagnose.h>
30 #include <osl/file.hxx>
31 #include <sal/macros.h>
32 #include <o3tl/char16_t2wchar_t.hxx>
34 #ifdef _WIN32
35 #include <objbase.h>
36 #include <shlobj.h>
37 #endif
39 namespace container = css::container ;
40 namespace beans = css::beans ;
41 namespace lang = css::lang ;
42 namespace util = css::util ;
43 namespace uno = css::uno ;
45 #define LAST_CHECK "LastCheck"
46 #define UPDATE_VERSION "UpdateVersion"
47 #define UPDATE_BUILDID "UpdateBuildId"
48 #define UPDATE_DESCRIPTION "UpdateDescription"
49 #define DOWNLOAD_URL "DownloadURL"
50 #define IS_DIRECT_DOWNLOAD "IsDirectDownload"
51 #define OLD_VERSION "UpdateFoundFor"
52 #define AUTOCHECK_ENABLED "AutoCheckEnabled"
53 #define AUTODOWNLOAD_ENABLED "AutoDownloadEnabled"
54 #define CHECK_INTERVAL "CheckInterval"
55 #define LOCAL_FILE "LocalFile"
56 #define DOWNLOAD_SIZE "DownloadSize"
57 #define DOWNLOAD_PAUSED "DownloadPaused"
58 #define DOWNLOAD_DESTINATION "DownloadDestination"
59 #define RELEASE_NOTE "ReleaseNote"
61 #define PROPERTY_VERSION "Version"
63 const char * const aUpdateEntryProperties[] = {
64 UPDATE_VERSION,
65 UPDATE_BUILDID,
66 UPDATE_DESCRIPTION,
67 DOWNLOAD_URL,
68 IS_DIRECT_DOWNLOAD,
69 RELEASE_NOTE"1",
70 RELEASE_NOTE"2",
71 RELEASE_NOTE"3",
72 RELEASE_NOTE"4",
73 RELEASE_NOTE"5",
74 OLD_VERSION
77 const sal_uInt32 nUpdateEntryProperties = SAL_N_ELEMENTS(aUpdateEntryProperties);
79 css::uno::Any NamedValueByNameAccess::getValue(const char * pName)
81 const sal_Int32 nLen = m_rValues.getLength();
82 for( sal_Int32 n=0; n < nLen; ++n )
84 if( m_rValues[n].Name.equalsAscii( pName ) )
85 return m_rValues[n].Value;
87 return css::uno::Any();
90 bool
91 UpdateCheckROModel::isAutoCheckEnabled() const
93 return m_aNameAccess.getValue(AUTOCHECK_ENABLED).get<bool>();
96 bool
97 UpdateCheckROModel::isDownloadPaused() const
99 return m_aNameAccess.getValue(DOWNLOAD_PAUSED).get<bool>();
102 OUString
103 UpdateCheckROModel::getStringValue(const char * pStr) const
105 uno::Any aAny( m_aNameAccess.getValue(pStr) );
106 OUString aRet;
108 aAny >>= aRet;
110 return aRet;
113 OUString UpdateCheckROModel::getLocalFileName() const
115 return getStringValue(LOCAL_FILE);
118 sal_Int64 UpdateCheckROModel::getDownloadSize() const
120 uno::Any aAny( m_aNameAccess.getValue(DOWNLOAD_SIZE) );
121 sal_Int64 nRet = -1;
123 aAny >>= nRet;
124 return nRet;
127 OUString
128 UpdateCheckROModel::getUpdateEntryVersion() const
130 return getStringValue(OLD_VERSION);
133 void
134 UpdateCheckROModel::getUpdateEntry(UpdateInfo& rInfo) const
136 rInfo.BuildId = getStringValue(UPDATE_BUILDID);
137 rInfo.Version = getStringValue(UPDATE_VERSION);
138 rInfo.Description = getStringValue(UPDATE_DESCRIPTION);
140 bool isDirectDownload = false;
141 m_aNameAccess.getValue(IS_DIRECT_DOWNLOAD) >>= isDirectDownload;
143 rInfo.Sources.emplace_back(isDirectDownload, getStringValue(DOWNLOAD_URL));
145 for(sal_Int32 n=1; n < 6; ++n )
147 OUString aUStr = getStringValue(
148 OString(OString::Concat(RELEASE_NOTE) + OString::number(n)).getStr());
149 if( !aUStr.isEmpty() )
150 rInfo.ReleaseNotes.emplace_back(static_cast<sal_Int8>(n), aUStr);
154 OUString UpdateCheckConfig::getDownloadsDirectory()
156 OUString aRet;
158 #ifdef _WIN32
159 PWSTR szPath;
161 if (SHGetKnownFolderPath(FOLDERID_Downloads, 0, nullptr, &szPath) == S_OK)
163 aRet = o3tl::toU(szPath);
164 CoTaskMemFree(szPath);
165 osl::FileBase::getFileURLFromSystemPath( aRet, aRet );
167 #else
168 // This should become a desktop specific setting in some system backend ..
169 OUString aHomeDir;
170 osl::Security().getHomeDir( aHomeDir );
171 aRet = aHomeDir + "/Desktop";
173 // Set path to home directory when there is no /Desktop directory
174 osl::Directory aDocumentsDir( aRet );
175 if( osl::FileBase::E_None != aDocumentsDir.open() )
176 aRet = aHomeDir;
177 #endif
179 return aRet;
182 OUString UpdateCheckConfig::getAllUsersDirectory()
184 OUString aRet;
186 #ifdef _WIN32
187 PWSTR szPath = nullptr;
188 if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_PublicDocuments, KF_FLAG_CREATE, nullptr, &szPath)))
190 aRet = o3tl::toU(szPath);
191 osl::FileBase::getFileURLFromSystemPath( aRet, aRet );
193 CoTaskMemFree(szPath);
194 #else
195 osl::FileBase::getTempDirURL(aRet);
196 #endif
198 return aRet;
201 UpdateCheckConfig::UpdateCheckConfig( const uno::Reference<container::XNameContainer>& xContainer,
202 const uno::Reference<container::XNameContainer>& xAvailableUpdates,
203 const uno::Reference<container::XNameContainer>& xIgnoredUpdates,
204 const ::rtl::Reference< UpdateCheckConfigListener >& rListener ) :
205 m_xContainer( xContainer ),
206 m_xAvailableUpdates( xAvailableUpdates ),
207 m_xIgnoredUpdates( xIgnoredUpdates ),
208 m_rListener( rListener )
211 UpdateCheckConfig::~UpdateCheckConfig()
214 ::rtl::Reference< UpdateCheckConfig >
215 UpdateCheckConfig::get(
216 const uno::Reference<uno::XComponentContext>& xContext,
217 const ::rtl::Reference< UpdateCheckConfigListener >& rListener)
219 uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
220 css::configuration::theDefaultProvider::get( xContext ) );
222 beans::PropertyValue aProperty;
223 aProperty.Name = "nodepath";
224 aProperty.Value <<= u"org.openoffice.Office.Jobs/Jobs/UpdateCheck/Arguments"_ustr;
226 uno::Sequence< uno::Any > aArgumentList{ uno::Any(aProperty) };
228 uno::Reference< container::XNameContainer > xContainer(
229 xConfigProvider->createInstanceWithArguments(
230 u"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr, aArgumentList ),
231 uno::UNO_QUERY_THROW );
233 aProperty.Value <<= u"/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/IgnoredUpdates"_ustr;
234 aArgumentList = { uno::Any(aProperty) };
235 uno::Reference< container::XNameContainer > xIgnoredExt( xConfigProvider->createInstanceWithArguments( u"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr, aArgumentList ), uno::UNO_QUERY_THROW );
237 aProperty.Value <<= u"/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/AvailableUpdates"_ustr;
238 aArgumentList = { uno::Any(aProperty) };
239 uno::Reference< container::XNameContainer > xUpdateAvail( xConfigProvider->createInstanceWithArguments( u"com.sun.star.configuration.ConfigurationUpdateAccess"_ustr, aArgumentList ), uno::UNO_QUERY_THROW );
241 return new UpdateCheckConfig( xContainer, xUpdateAvail, xIgnoredExt, rListener );
244 bool
245 UpdateCheckConfig::isAutoCheckEnabled() const
247 bool nValue = false;
248 const_cast < UpdateCheckConfig *> (this)->getByName( u"" AUTOCHECK_ENABLED ""_ustr ) >>= nValue;
249 return nValue;
252 bool
253 UpdateCheckConfig::isAutoDownloadEnabled() const
255 bool nValue = false;
256 const_cast < UpdateCheckConfig *> (this)->getByName( u"" AUTODOWNLOAD_ENABLED ""_ustr ) >>= nValue;
257 return nValue;
260 OUString
261 UpdateCheckConfig::getUpdateEntryVersion() const
263 OUString aValue;
265 // getByName is defined as non const in XNameAccess
266 const_cast < UpdateCheckConfig *> (this)->getByName( u"" OLD_VERSION ""_ustr ) >>= aValue;
268 return aValue;
271 sal_Int64
272 UpdateCheckConfig::getLastChecked() const
274 sal_Int64 nValue = 0;
276 // getByName is defined as non const in XNameAccess
277 const_cast < UpdateCheckConfig *> (this)->getByName( u"" LAST_CHECK ""_ustr ) >>= nValue;
279 return nValue;
282 sal_Int64
283 UpdateCheckConfig::getCheckInterval() const
285 sal_Int64 nValue = 0;
287 // getByName is defined as non const in XNameAccess
288 const_cast < UpdateCheckConfig *> (this)->getByName( u"" CHECK_INTERVAL ""_ustr ) >>= nValue;
290 return nValue;
293 OUString
294 UpdateCheckConfig::getLocalFileName() const
296 OUString aName = u"" LOCAL_FILE ""_ustr;
297 OUString aRet;
299 if( m_xContainer->hasByName(aName) )
300 m_xContainer->getByName(aName) >>= aRet;
302 return aRet;
305 OUString
306 UpdateCheckConfig::getDownloadDestination() const
308 OUString aRet;
310 const_cast <UpdateCheckConfig *> (this)->getByName(u"" DOWNLOAD_DESTINATION ""_ustr) >>= aRet;
312 return aRet;
315 void
316 UpdateCheckConfig::storeLocalFileName(const OUString& rLocalFileName, sal_Int64 nFileSize)
318 const sal_uInt8 nItems = 2;
319 const OUString aNameList[nItems] = { u"" LOCAL_FILE ""_ustr, u"" DOWNLOAD_SIZE ""_ustr };
320 const uno::Any aValueList[nItems] = { uno::Any(rLocalFileName), uno::Any(nFileSize) };
322 for( sal_uInt8 i=0; i < nItems; ++i )
324 if( m_xContainer->hasByName(aNameList[i]) )
325 m_xContainer->replaceByName(aNameList[i], aValueList[i]);
326 else
327 m_xContainer->insertByName(aNameList[i], aValueList[i]);
330 commitChanges();
333 void
334 UpdateCheckConfig::clearLocalFileName()
336 const sal_uInt8 nItems = 2;
337 const OUString aNameList[nItems] = { u"" LOCAL_FILE ""_ustr, u"" DOWNLOAD_SIZE ""_ustr };
339 for(const auto & i : aNameList)
341 if( m_xContainer->hasByName(i) )
342 m_xContainer->removeByName(i);
345 commitChanges();
348 void
349 UpdateCheckConfig::storeDownloadPaused(bool paused)
351 replaceByName(u"" DOWNLOAD_PAUSED ""_ustr , uno::Any(paused));
352 commitChanges();
355 void
356 UpdateCheckConfig::updateLastChecked()
358 TimeValue systime;
359 osl_getSystemTime(&systime);
361 sal_Int64 lastCheck = systime.Seconds;
363 replaceByName(u"" LAST_CHECK ""_ustr, uno::Any(lastCheck));
366 void
367 UpdateCheckConfig::storeUpdateFound( const UpdateInfo& rInfo, const OUString& aCurrentBuild)
370 bool autoDownloadEnabled = isAutoDownloadEnabled();
372 uno::Any aValues[nUpdateEntryProperties] =
374 uno::Any(rInfo.Version),
375 uno::Any(rInfo.BuildId),
376 uno::Any(rInfo.Description),
377 uno::Any(rInfo.Sources[0].URL),
378 uno::Any(rInfo.Sources[0].IsDirect),
379 uno::Any(getReleaseNote(rInfo, 1, autoDownloadEnabled) ),
380 uno::Any(getReleaseNote(rInfo, 2, autoDownloadEnabled) ),
381 uno::Any(getReleaseNote(rInfo, 3, autoDownloadEnabled) ),
382 uno::Any(getReleaseNote(rInfo, 4, autoDownloadEnabled) ),
383 uno::Any(getReleaseNote(rInfo, 5, autoDownloadEnabled) ),
384 uno::Any(aCurrentBuild)
387 OUString aName;
388 for( sal_uInt32 n=0; n < nUpdateEntryProperties; ++n )
390 aName = OUString::createFromAscii(aUpdateEntryProperties[n]);
392 if( m_xContainer->hasByName(aName) )
393 m_xContainer->replaceByName(aName, aValues[n]);
394 else
395 m_xContainer->insertByName(aName,aValues[n]);
398 commitChanges();
401 void
402 UpdateCheckConfig::clearUpdateFound()
404 OUString aName;
406 for(const char* aUpdateEntryProperty : aUpdateEntryProperties)
408 aName = OUString::createFromAscii(aUpdateEntryProperty);
410 try {
411 if( m_xContainer->hasByName(aName) )
412 m_xContainer->removeByName(aName);
413 } catch(const lang::WrappedTargetException& ) {
414 // Can not remove value, probably in share layer
415 OSL_ASSERT(false);
416 m_xContainer->replaceByName(aName, uno::Any(OUString()));
420 /* As we have removed UpdateVersionFound from the shared configuration
421 * existing entries in the user layer do not have a oor operation and
422 * thus are completely ignored (which also means they can not be removed).
425 commitChanges();
428 uno::Type SAL_CALL
429 UpdateCheckConfig::getElementType()
431 return m_xContainer->getElementType();
434 sal_Bool SAL_CALL
435 UpdateCheckConfig::hasElements()
437 return m_xContainer->hasElements();
440 uno::Any SAL_CALL
441 UpdateCheckConfig::getByName( const OUString& aName )
443 uno::Any aValue = m_xContainer->getByName( aName );
445 // Provide dynamic default value
446 if( aName == DOWNLOAD_DESTINATION )
448 OUString aStr;
449 aValue >>= aStr;
451 if( aStr.isEmpty() )
452 aValue <<= getDownloadsDirectory();
454 return aValue;
457 uno::Sequence< OUString > SAL_CALL
458 UpdateCheckConfig::getElementNames()
460 return m_xContainer->getElementNames();
463 sal_Bool SAL_CALL
464 UpdateCheckConfig::hasByName( const OUString& aName )
466 return m_xContainer->hasByName( aName );
469 void SAL_CALL
470 UpdateCheckConfig::replaceByName( const OUString& aName, const uno::Any& aElement )
472 return m_xContainer->replaceByName( aName, aElement );
475 // XChangesBatch
477 void SAL_CALL
478 UpdateCheckConfig::commitChanges()
480 uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY);
481 if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() )
483 util::ChangesSet aChangesSet = xChangesBatch->getPendingChanges();
484 xChangesBatch->commitChanges();
486 if( m_rListener.is() )
488 const sal_Int32 nChanges = aChangesSet.getLength();
489 OUString aString;
491 for( sal_Int32 i=0; i<nChanges; ++i )
493 aChangesSet[i].Accessor >>= aString;
494 if( aString.endsWith(AUTOCHECK_ENABLED "']") )
496 bool bEnabled = false;
497 aChangesSet[i].Element >>= bEnabled;
498 m_rListener->autoCheckStatusChanged(bEnabled);
500 else if( aString.endsWith(CHECK_INTERVAL "']") )
502 m_rListener->autoCheckIntervalChanged();
508 xChangesBatch.set( m_xAvailableUpdates, uno::UNO_QUERY );
509 if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() )
511 xChangesBatch->commitChanges();
513 xChangesBatch.set( m_xIgnoredUpdates, uno::UNO_QUERY );
514 if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() )
516 xChangesBatch->commitChanges();
520 sal_Bool SAL_CALL
521 UpdateCheckConfig::hasPendingChanges( )
523 uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY);
524 if( xChangesBatch.is() )
525 return xChangesBatch->hasPendingChanges();
527 return false;
530 uno::Sequence< util::ElementChange > SAL_CALL
531 UpdateCheckConfig::getPendingChanges( )
533 uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY);
534 if( xChangesBatch.is() )
535 return xChangesBatch->getPendingChanges();
537 return uno::Sequence< util::ElementChange >();
540 bool UpdateCheckConfig::storeExtensionVersion( const OUString& rExtensionName,
541 const OUString& rVersion )
543 bool bNotify = true;
545 if ( m_xAvailableUpdates->hasByName( rExtensionName ) )
546 uno::Reference< beans::XPropertySet >( m_xAvailableUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->setPropertyValue( u"" PROPERTY_VERSION ""_ustr, uno::Any( rVersion ) );
547 else
549 uno::Reference< beans::XPropertySet > elem( uno::Reference< lang::XSingleServiceFactory >( m_xAvailableUpdates, uno::UNO_QUERY_THROW )->createInstance(), uno::UNO_QUERY_THROW );
550 elem->setPropertyValue( u"" PROPERTY_VERSION ""_ustr, uno::Any( rVersion ) );
551 m_xAvailableUpdates->insertByName( rExtensionName, uno::Any( elem ) );
554 if ( m_xIgnoredUpdates->hasByName( rExtensionName ) )
556 OUString aIgnoredVersion;
557 uno::Any aValue( uno::Reference< beans::XPropertySet >( m_xIgnoredUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->getPropertyValue( u"" PROPERTY_VERSION ""_ustr ) );
558 aValue >>= aIgnoredVersion;
559 if ( aIgnoredVersion.isEmpty() ) // no version means ignore all updates
560 bNotify = false;
561 else if ( aIgnoredVersion == rVersion ) // the user wanted to ignore this update
562 bNotify = false;
565 commitChanges();
567 return bNotify;
570 bool UpdateCheckConfig::checkExtensionVersion( const OUString& rExtensionName,
571 const OUString& rVersion )
573 if ( m_xAvailableUpdates->hasByName( rExtensionName ) )
575 OUString aStoredVersion;
576 uno::Any aValue( uno::Reference< beans::XPropertySet >( m_xAvailableUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->getPropertyValue( u"" PROPERTY_VERSION ""_ustr ) );
577 aValue >>= aStoredVersion;
579 if ( m_xIgnoredUpdates->hasByName( rExtensionName ) )
581 OUString aIgnoredVersion;
582 uno::Any aValue2( uno::Reference< beans::XPropertySet >( m_xIgnoredUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->getPropertyValue( u"" PROPERTY_VERSION ""_ustr ) );
583 aValue2 >>= aIgnoredVersion;
584 if ( aIgnoredVersion.isEmpty() ) // no version means ignore all updates
585 return false;
586 else if ( aIgnoredVersion == aStoredVersion ) // the user wanted to ignore this update
587 return false;
588 // TODO: else delete ignored entry?
590 if ( isVersionGreater( rVersion, aStoredVersion ) )
591 return true;
592 else
594 m_xAvailableUpdates->removeByName( rExtensionName );
595 commitChanges();
599 return false;
602 OUString UpdateCheckConfig::getSubVersion( const OUString& rVersion,
603 sal_Int32 *nIndex )
605 while ( *nIndex < rVersion.getLength() && rVersion[*nIndex] == '0')
607 ++*nIndex;
610 return rVersion.getToken( 0, '.', *nIndex );
613 /// checks if the second version string is greater than the first one
614 bool UpdateCheckConfig::isVersionGreater( const OUString& rVersion1,
615 const OUString& rVersion2 )
617 for ( sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0; )
619 OUString sSub1( getSubVersion( rVersion1, &i1 ) );
620 OUString sSub2( getSubVersion( rVersion2, &i2 ) );
622 if ( sSub1.getLength() < sSub2.getLength() ) {
623 return true;
624 } else if ( sSub1.getLength() > sSub2.getLength() ) {
625 return false;
626 } else if ( sSub1 < sSub2 ) {
627 return true;
628 } else if ( sSub1 > sSub2 ) {
629 return false;
632 return false;
635 OUString SAL_CALL
636 UpdateCheckConfig::getImplementationName()
638 return u"vnd.sun.UpdateCheckConfig"_ustr;
641 sal_Bool SAL_CALL
642 UpdateCheckConfig::supportsService(OUString const & serviceName)
644 return cppu::supportsService(this, serviceName);
647 uno::Sequence< OUString > SAL_CALL
648 UpdateCheckConfig::getSupportedServiceNames()
650 return { u"com.sun.star.setup.UpdateCheckConfig"_ustr };
653 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
654 extensions_update_UpdateCheckConfig_get_implementation(
655 css::uno::XComponentContext* context , css::uno::Sequence<css::uno::Any> const&)
657 return cppu::acquire(UpdateCheckConfig::get(context, *UpdateCheck::get()).get());
661 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */