bump product version to 6.3.0.0.beta1
[LibreOffice.git] / extensions / source / update / check / updatecheckconfig.cxx
blob973729216c2fad462f70b314d675b19e0c9c6fac
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 <com/sun/star/beans/PropertyValue.hpp>
22 #include <com/sun/star/beans/XPropertyState.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/file.hxx>
30 #include <sal/macros.h>
31 #include <o3tl/char16_t2wchar_t.hxx>
33 #ifdef _WIN32
34 #include <objbase.h>
35 #include <shlobj.h>
36 #endif
38 namespace container = com::sun::star::container ;
39 namespace beans = com::sun::star::beans ;
40 namespace lang = com::sun::star::lang ;
41 namespace util = com::sun::star::util ;
42 namespace uno = com::sun::star::uno ;
44 #define LAST_CHECK "LastCheck"
45 #define UPDATE_VERSION "UpdateVersion"
46 #define UPDATE_BUILDID "UpdateBuildId"
47 #define UPDATE_DESCRIPTION "UpdateDescription"
48 #define DOWNLOAD_URL "DownloadURL"
49 #define IS_DIRECT_DOWNLOAD "IsDirectDownload"
50 #define OLD_VERSION "UpdateFoundFor"
51 #define AUTOCHECK_ENABLED "AutoCheckEnabled"
52 #define AUTODOWNLOAD_ENABLED "AutoDownloadEnabled"
53 #define CHECK_INTERVAL "CheckInterval"
54 #define LOCAL_FILE "LocalFile"
55 #define DOWNLOAD_SIZE "DownloadSize"
56 #define DOWNLOAD_PAUSED "DownloadPaused"
57 #define DOWNLOAD_DESTINATION "DownloadDestination"
58 #define RELEASE_NOTE "ReleaseNote"
60 #define PROPERTY_VERSION "Version"
62 static const sal_Char * const aUpdateEntryProperties[] = {
63 UPDATE_VERSION,
64 UPDATE_BUILDID,
65 UPDATE_DESCRIPTION,
66 DOWNLOAD_URL,
67 IS_DIRECT_DOWNLOAD,
68 RELEASE_NOTE"1",
69 RELEASE_NOTE"2",
70 RELEASE_NOTE"3",
71 RELEASE_NOTE"4",
72 RELEASE_NOTE"5",
73 OLD_VERSION
76 static const sal_uInt32 nUpdateEntryProperties = SAL_N_ELEMENTS(aUpdateEntryProperties);
78 NamedValueByNameAccess::~NamedValueByNameAccess()
82 css::uno::Any NamedValueByNameAccess::getValue(const sal_Char * pName)
84 const sal_Int32 nLen = m_rValues.getLength();
85 for( sal_Int32 n=0; n < nLen; ++n )
87 if( m_rValues[n].Name.equalsAscii( pName ) )
88 return m_rValues[n].Value;
90 return css::uno::Any();
93 bool
94 UpdateCheckROModel::isAutoCheckEnabled() const
96 return m_aNameAccess.getValue(AUTOCHECK_ENABLED).get<bool>();
99 bool
100 UpdateCheckROModel::isDownloadPaused() const
102 return m_aNameAccess.getValue(DOWNLOAD_PAUSED).get<bool>();
105 OUString
106 UpdateCheckROModel::getStringValue(const sal_Char * pStr) const
108 uno::Any aAny( m_aNameAccess.getValue(pStr) );
109 OUString aRet;
111 aAny >>= aRet;
113 return aRet;
116 OUString UpdateCheckROModel::getLocalFileName() const
118 return getStringValue(LOCAL_FILE);
121 sal_Int64 UpdateCheckROModel::getDownloadSize() const
123 uno::Any aAny( m_aNameAccess.getValue(DOWNLOAD_SIZE) );
124 sal_Int64 nRet = -1;
126 aAny >>= nRet;
127 return nRet;
130 OUString
131 UpdateCheckROModel::getUpdateEntryVersion() const
133 return getStringValue(OLD_VERSION);
136 void
137 UpdateCheckROModel::getUpdateEntry(UpdateInfo& rInfo) const
139 rInfo.BuildId = getStringValue(UPDATE_BUILDID);
140 rInfo.Version = getStringValue(UPDATE_VERSION);
141 rInfo.Description = getStringValue(UPDATE_DESCRIPTION);
143 bool isDirectDownload = false;
144 m_aNameAccess.getValue(IS_DIRECT_DOWNLOAD) >>= isDirectDownload;
146 rInfo.Sources.push_back( DownloadSource( isDirectDownload, getStringValue(DOWNLOAD_URL) ) );
148 for(sal_Int32 n=1; n < 6; ++n )
150 OUString aUStr = getStringValue(
151 OString(OStringLiteral(RELEASE_NOTE) + OString::number(n)).getStr());
152 if( !aUStr.isEmpty() )
153 rInfo.ReleaseNotes.push_back(ReleaseNote(static_cast<sal_Int8>(n), aUStr));
157 OUString UpdateCheckConfig::getDownloadsDirectory()
159 OUString aRet;
161 #ifdef _WIN32
162 PWSTR szPath;
164 if (SHGetKnownFolderPath(FOLDERID_Downloads, 0, nullptr, &szPath) == S_OK)
166 aRet = o3tl::toU(szPath);
167 CoTaskMemFree(szPath);
168 osl::FileBase::getFileURLFromSystemPath( aRet, aRet );
170 #else
171 // This should become a desktop specific setting in some system backend ..
172 OUString aHomeDir;
173 osl::Security().getHomeDir( aHomeDir );
174 aRet = aHomeDir + "/Desktop";
176 // Set path to home directory when there is no /Desktop directory
177 osl::Directory aDocumentsDir( aRet );
178 if( osl::FileBase::E_None != aDocumentsDir.open() )
179 aRet = aHomeDir;
180 #endif
182 return aRet;
185 OUString UpdateCheckConfig::getAllUsersDirectory()
187 OUString aRet;
189 #ifdef _WIN32
190 WCHAR szPath[MAX_PATH];
192 if (TRUE == SHGetSpecialFolderPathW(nullptr, szPath, CSIDL_COMMON_DOCUMENTS, true))
194 aRet = o3tl::toU(szPath);
195 osl::FileBase::getFileURLFromSystemPath( aRet, aRet );
197 #else
198 osl::FileBase::getTempDirURL(aRet);
199 #endif
201 return aRet;
204 UpdateCheckConfig::UpdateCheckConfig( const uno::Reference<container::XNameContainer>& xContainer,
205 const uno::Reference<container::XNameContainer>& xAvailableUpdates,
206 const uno::Reference<container::XNameContainer>& xIgnoredUpdates,
207 const ::rtl::Reference< UpdateCheckConfigListener >& rListener ) :
208 m_xContainer( xContainer ),
209 m_xAvailableUpdates( xAvailableUpdates ),
210 m_xIgnoredUpdates( xIgnoredUpdates ),
211 m_rListener( rListener )
214 UpdateCheckConfig::~UpdateCheckConfig()
217 ::rtl::Reference< UpdateCheckConfig >
218 UpdateCheckConfig::get(
219 const uno::Reference<uno::XComponentContext>& xContext,
220 const ::rtl::Reference< UpdateCheckConfigListener >& rListener)
222 uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
223 css::configuration::theDefaultProvider::get( xContext ) );
225 beans::PropertyValue aProperty;
226 aProperty.Name = "nodepath";
227 aProperty.Value <<= OUString("org.openoffice.Office.Jobs/Jobs/UpdateCheck/Arguments");
229 uno::Sequence< uno::Any > aArgumentList( 1 );
230 aArgumentList[0] <<= aProperty;
232 uno::Reference< container::XNameContainer > xContainer(
233 xConfigProvider->createInstanceWithArguments(
234 "com.sun.star.configuration.ConfigurationUpdateAccess", aArgumentList ),
235 uno::UNO_QUERY_THROW );
237 aProperty.Value <<= OUString("/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/IgnoredUpdates");
238 aArgumentList[0] <<= aProperty;
239 uno::Reference< container::XNameContainer > xIgnoredExt( xConfigProvider->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationUpdateAccess", aArgumentList ), uno::UNO_QUERY_THROW );
241 aProperty.Value <<= OUString("/org.openoffice.Office.ExtensionManager/ExtensionUpdateData/AvailableUpdates");
242 aArgumentList[0] <<= aProperty;
243 uno::Reference< container::XNameContainer > xUpdateAvail( xConfigProvider->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationUpdateAccess", aArgumentList ), uno::UNO_QUERY_THROW );
245 return new UpdateCheckConfig( xContainer, xUpdateAvail, xIgnoredExt, rListener );
248 bool
249 UpdateCheckConfig::isAutoCheckEnabled() const
251 bool nValue = false;
252 const_cast < UpdateCheckConfig *> (this)->getByName( AUTOCHECK_ENABLED ) >>= nValue;
253 return nValue;
256 bool
257 UpdateCheckConfig::isAutoDownloadEnabled() const
259 bool nValue = false;
260 const_cast < UpdateCheckConfig *> (this)->getByName( AUTODOWNLOAD_ENABLED ) >>= nValue;
261 return nValue;
264 OUString
265 UpdateCheckConfig::getUpdateEntryVersion() const
267 OUString aValue;
269 // getByName is defined as non const in XNameAccess
270 const_cast < UpdateCheckConfig *> (this)->getByName( OLD_VERSION ) >>= aValue;
272 return aValue;
275 sal_Int64
276 UpdateCheckConfig::getLastChecked() const
278 sal_Int64 nValue = 0;
280 // getByName is defined as non const in XNameAccess
281 const_cast < UpdateCheckConfig *> (this)->getByName( LAST_CHECK ) >>= nValue;
283 return nValue;
286 sal_Int64
287 UpdateCheckConfig::getCheckInterval() const
289 sal_Int64 nValue = 0;
291 // getByName is defined as non const in XNameAccess
292 const_cast < UpdateCheckConfig *> (this)->getByName( CHECK_INTERVAL ) >>= nValue;
294 return nValue;
297 OUString
298 UpdateCheckConfig::getLocalFileName() const
300 OUString aName = LOCAL_FILE;
301 OUString aRet;
303 if( m_xContainer->hasByName(aName) )
304 m_xContainer->getByName(aName) >>= aRet;
306 return aRet;
309 OUString
310 UpdateCheckConfig::getDownloadDestination() const
312 OUString aName = DOWNLOAD_DESTINATION;
313 OUString aRet;
315 const_cast <UpdateCheckConfig *> (this)->getByName(aName) >>= aRet;
317 return aRet;
320 void
321 UpdateCheckConfig::storeLocalFileName(const OUString& rLocalFileName, sal_Int64 nFileSize)
323 const sal_uInt8 nItems = 2;
324 const OUString aNameList[nItems] = { OUString(LOCAL_FILE), OUString(DOWNLOAD_SIZE) };
325 const uno::Any aValueList[nItems] = { uno::makeAny(rLocalFileName), uno::makeAny(nFileSize) };
327 for( sal_uInt8 i=0; i < nItems; ++i )
329 if( m_xContainer->hasByName(aNameList[i]) )
330 m_xContainer->replaceByName(aNameList[i], aValueList[i]);
331 else
332 m_xContainer->insertByName(aNameList[i], aValueList[i]);
335 commitChanges();
338 void
339 UpdateCheckConfig::clearLocalFileName()
341 const sal_uInt8 nItems = 2;
342 const OUString aNameList[nItems] = { OUString(LOCAL_FILE), OUString(DOWNLOAD_SIZE) };
344 for(const auto & i : aNameList)
346 if( m_xContainer->hasByName(i) )
347 m_xContainer->removeByName(i);
350 commitChanges();
353 void
354 UpdateCheckConfig::storeDownloadPaused(bool paused)
356 replaceByName(DOWNLOAD_PAUSED , uno::makeAny(paused));
357 commitChanges();
360 void
361 UpdateCheckConfig::updateLastChecked()
363 TimeValue systime;
364 osl_getSystemTime(&systime);
366 sal_Int64 lastCheck = systime.Seconds;
368 replaceByName(LAST_CHECK, uno::makeAny(lastCheck));
371 void
372 UpdateCheckConfig::storeUpdateFound( const UpdateInfo& rInfo, const OUString& aCurrentBuild)
375 bool autoDownloadEnabled = isAutoDownloadEnabled();
377 uno::Any aValues[nUpdateEntryProperties] =
379 uno::makeAny(rInfo.Version),
380 uno::makeAny(rInfo.BuildId),
381 uno::makeAny(rInfo.Description),
382 uno::makeAny(rInfo.Sources[0].URL),
383 uno::makeAny(rInfo.Sources[0].IsDirect),
384 uno::makeAny(getReleaseNote(rInfo, 1, autoDownloadEnabled) ),
385 uno::makeAny(getReleaseNote(rInfo, 2, autoDownloadEnabled) ),
386 uno::makeAny(getReleaseNote(rInfo, 3, autoDownloadEnabled) ),
387 uno::makeAny(getReleaseNote(rInfo, 4, autoDownloadEnabled) ),
388 uno::makeAny(getReleaseNote(rInfo, 5, autoDownloadEnabled) ),
389 uno::makeAny(aCurrentBuild)
392 OUString aName;
393 for( sal_uInt32 n=0; n < nUpdateEntryProperties; ++n )
395 aName = OUString::createFromAscii(aUpdateEntryProperties[n]);
397 if( m_xContainer->hasByName(aName) )
398 m_xContainer->replaceByName(aName, aValues[n]);
399 else
400 m_xContainer->insertByName(aName,aValues[n]);
403 commitChanges();
406 void
407 UpdateCheckConfig::clearUpdateFound()
409 OUString aName;
411 for(const char* aUpdateEntryPropertie : aUpdateEntryProperties)
413 aName = OUString::createFromAscii(aUpdateEntryPropertie);
415 try {
416 if( m_xContainer->hasByName(aName) )
417 m_xContainer->removeByName(aName);
418 } catch(const lang::WrappedTargetException& ) {
419 // Can not remove value, probably in share layer
420 OSL_ASSERT(false);
421 m_xContainer->replaceByName(aName, uno::makeAny(OUString()));
425 /* As we have removed UpdateVersionFound from the shared configuration
426 * existing entries in the user layer do not have a oor operation and
427 * thus are completely ignored (which also means they can not be removed).
430 commitChanges();
433 uno::Sequence< OUString >
434 UpdateCheckConfig::getServiceNames()
436 uno::Sequence< OUString > aServiceList { "com.sun.star.setup.UpdateCheckConfig" };
437 return aServiceList;
440 OUString
441 UpdateCheckConfig::getImplName()
443 return OUString("vnd.sun.UpdateCheckConfig");
446 uno::Type SAL_CALL
447 UpdateCheckConfig::getElementType()
449 return m_xContainer->getElementType();
452 sal_Bool SAL_CALL
453 UpdateCheckConfig::hasElements()
455 return m_xContainer->hasElements();
458 uno::Any SAL_CALL
459 UpdateCheckConfig::getByName( const OUString& aName )
461 uno::Any aValue = m_xContainer->getByName( aName );
463 // Provide dynamic default value
464 if( aName == DOWNLOAD_DESTINATION )
466 OUString aStr;
467 aValue >>= aStr;
469 if( aStr.isEmpty() )
470 aValue <<= getDownloadsDirectory();
472 return aValue;
475 uno::Sequence< OUString > SAL_CALL
476 UpdateCheckConfig::getElementNames()
478 return m_xContainer->getElementNames();
481 sal_Bool SAL_CALL
482 UpdateCheckConfig::hasByName( const OUString& aName )
484 return m_xContainer->hasByName( aName );
487 void SAL_CALL
488 UpdateCheckConfig::replaceByName( const OUString& aName, const uno::Any& aElement )
490 return m_xContainer->replaceByName( aName, aElement );
493 // XChangesBatch
495 void SAL_CALL
496 UpdateCheckConfig::commitChanges()
498 uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY);
499 if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() )
501 util::ChangesSet aChangesSet = xChangesBatch->getPendingChanges();
502 xChangesBatch->commitChanges();
504 if( m_rListener.is() )
506 const sal_Int32 nChanges = aChangesSet.getLength();
507 OUString aString;
509 for( sal_Int32 i=0; i<nChanges; ++i )
511 aChangesSet[i].Accessor >>= aString;
512 if( aString.endsWith(AUTOCHECK_ENABLED "']") )
514 bool bEnabled = false;
515 aChangesSet[i].Element >>= bEnabled;
516 m_rListener->autoCheckStatusChanged(bEnabled);
518 else if( aString.endsWith(CHECK_INTERVAL "']") )
520 m_rListener->autoCheckIntervalChanged();
526 xChangesBatch.set( m_xAvailableUpdates, uno::UNO_QUERY );
527 if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() )
529 xChangesBatch->commitChanges();
531 xChangesBatch.set( m_xIgnoredUpdates, uno::UNO_QUERY );
532 if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() )
534 xChangesBatch->commitChanges();
538 sal_Bool SAL_CALL
539 UpdateCheckConfig::hasPendingChanges( )
541 uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY);
542 if( xChangesBatch.is() )
543 return xChangesBatch->hasPendingChanges();
545 return false;
548 uno::Sequence< util::ElementChange > SAL_CALL
549 UpdateCheckConfig::getPendingChanges( )
551 uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY);
552 if( xChangesBatch.is() )
553 return xChangesBatch->getPendingChanges();
555 return uno::Sequence< util::ElementChange >();
558 bool UpdateCheckConfig::storeExtensionVersion( const OUString& rExtensionName,
559 const OUString& rVersion )
561 bool bNotify = true;
563 if ( m_xAvailableUpdates->hasByName( rExtensionName ) )
564 uno::Reference< beans::XPropertySet >( m_xAvailableUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->setPropertyValue( PROPERTY_VERSION, uno::Any( rVersion ) );
565 else
567 uno::Reference< beans::XPropertySet > elem( uno::Reference< lang::XSingleServiceFactory >( m_xAvailableUpdates, uno::UNO_QUERY_THROW )->createInstance(), uno::UNO_QUERY_THROW );
568 elem->setPropertyValue( PROPERTY_VERSION, uno::Any( rVersion ) );
569 m_xAvailableUpdates->insertByName( rExtensionName, uno::Any( elem ) );
572 if ( m_xIgnoredUpdates->hasByName( rExtensionName ) )
574 OUString aIgnoredVersion;
575 uno::Any aValue( uno::Reference< beans::XPropertySet >( m_xIgnoredUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->getPropertyValue( PROPERTY_VERSION ) );
576 aValue >>= aIgnoredVersion;
577 if ( aIgnoredVersion.isEmpty() ) // no version means ignore all updates
578 bNotify = false;
579 else if ( aIgnoredVersion == rVersion ) // the user wanted to ignore this update
580 bNotify = false;
583 commitChanges();
585 return bNotify;
588 bool UpdateCheckConfig::checkExtensionVersion( const OUString& rExtensionName,
589 const OUString& rVersion )
591 if ( m_xAvailableUpdates->hasByName( rExtensionName ) )
593 OUString aStoredVersion;
594 uno::Any aValue( uno::Reference< beans::XPropertySet >( m_xAvailableUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->getPropertyValue( PROPERTY_VERSION ) );
595 aValue >>= aStoredVersion;
597 if ( m_xIgnoredUpdates->hasByName( rExtensionName ) )
599 OUString aIgnoredVersion;
600 uno::Any aValue2( uno::Reference< beans::XPropertySet >( m_xIgnoredUpdates->getByName( rExtensionName ), uno::UNO_QUERY_THROW )->getPropertyValue( PROPERTY_VERSION ) );
601 aValue2 >>= aIgnoredVersion;
602 if ( aIgnoredVersion.isEmpty() ) // no version means ignore all updates
603 return false;
604 else if ( aIgnoredVersion == aStoredVersion ) // the user wanted to ignore this update
605 return false;
606 // TODO: else delete ignored entry?
608 if ( isVersionGreater( rVersion, aStoredVersion ) )
609 return true;
610 else
612 m_xAvailableUpdates->removeByName( rExtensionName );
613 commitChanges();
617 return false;
620 OUString UpdateCheckConfig::getSubVersion( const OUString& rVersion,
621 sal_Int32 *nIndex )
623 while ( *nIndex < rVersion.getLength() && rVersion[*nIndex] == '0')
625 ++*nIndex;
628 return rVersion.getToken( 0, '.', *nIndex );
631 /// checks if the second version string is greater than the first one
632 bool UpdateCheckConfig::isVersionGreater( const OUString& rVersion1,
633 const OUString& rVersion2 )
635 for ( sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0; )
637 OUString sSub1( getSubVersion( rVersion1, &i1 ) );
638 OUString sSub2( getSubVersion( rVersion2, &i2 ) );
640 if ( sSub1.getLength() < sSub2.getLength() ) {
641 return true;
642 } else if ( sSub1.getLength() > sSub2.getLength() ) {
643 return false;
644 } else if ( sSub1 < sSub2 ) {
645 return true;
646 } else if ( sSub1 > sSub2 ) {
647 return false;
650 return false;
653 OUString SAL_CALL
654 UpdateCheckConfig::getImplementationName()
656 return getImplName();
659 sal_Bool SAL_CALL
660 UpdateCheckConfig::supportsService(OUString const & serviceName)
662 return cppu::supportsService(this, serviceName);
665 uno::Sequence< OUString > SAL_CALL
666 UpdateCheckConfig::getSupportedServiceNames()
668 return getServiceNames();
671 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */