1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
32 #include "updatecheckconfig.hxx"
33 #include <com/sun/star/beans/PropertyValue.hpp>
34 #include <com/sun/star/beans/XPropertyState.hpp>
36 #ifndef _COM_SUN_STAR_CONTAINER_CHANGESEVENT_HPP_
37 #include <com/sun/star/beans/XPropertyState.hpp>
40 #include <osl/security.hxx>
42 #include <osl/file.hxx>
46 #pragma warning(push,1) // disable warnings within system headers
47 #pragma warning(disable: 4917)
55 namespace container
= com::sun::star::container
;
56 namespace beans
= com::sun::star::beans
;
57 namespace lang
= com::sun::star::lang
;
58 namespace util
= com::sun::star::util
;
59 namespace uno
= com::sun::star::uno
;
61 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
63 #define LAST_CHECK "LastCheck"
64 #define VERSION_FOUND "UpdateVersionFound"
65 #define UPDATE_VERSION "UpdateVersion"
66 #define UPDATE_BUILDID "UpdateBuildId"
67 #define UPDATE_DESCRIPTION "UpdateDescription"
68 #define DOWNLOAD_URL "DownloadURL"
69 #define IS_DIRECT_DOWNLOAD "IsDirectDownload"
70 #define OLD_VERSION "UpdateFoundFor"
71 #define AUTOCHECK_ENABLED "AutoCheckEnabled"
72 #define AUTODOWNLOAD_ENABLED "AutoDownloadEnabled"
73 #define CHECK_INTERVAL "CheckInterval"
74 #define LOCAL_FILE "LocalFile"
75 #define DOWNLOAD_SIZE "DownloadSize"
76 #define DOWNLOAD_PAUSED "DownloadPaused"
77 #define DOWNLOAD_DESTINATION "DownloadDestination"
78 #define RELEASE_NOTE "ReleaseNote"
79 #define EXTENSION_PREFIX "Extension_"
81 static const sal_Char
* const aUpdateEntryProperties
[] = {
95 static const sal_uInt32 nUpdateEntryProperties
= sizeof(aUpdateEntryProperties
) / sizeof(sal_Char
*);
97 //------------------------------------------------------------------------------
99 NamedValueByNameAccess::~NamedValueByNameAccess()
103 //------------------------------------------------------------------------------
105 ::com::sun::star::uno::Any
106 NamedValueByNameAccess::getValue(const sal_Char
* pName
)
108 const sal_Int32 nLen
= m_rValues
.getLength();
109 for( sal_Int32 n
=0; n
< nLen
; ++n
)
111 if( m_rValues
[n
].Name
.equalsAscii( pName
) )
112 return m_rValues
[n
].Value
;
114 return ::com::sun::star::uno::Any();
118 //------------------------------------------------------------------------------
121 UpdateCheckROModel::isAutoCheckEnabled() const
123 return sal_True
== m_aNameAccess
.getValue(AUTOCHECK_ENABLED
).get
< sal_Bool
>();
126 //------------------------------------------------------------------------------
129 UpdateCheckROModel::isDownloadPaused() const
131 return sal_True
== m_aNameAccess
.getValue(DOWNLOAD_PAUSED
).get
< sal_Bool
>();
134 //------------------------------------------------------------------------------
137 UpdateCheckROModel::getStringValue(const sal_Char
* pStr
) const
139 uno::Any
aAny( m_aNameAccess
.getValue(pStr
) );
147 //------------------------------------------------------------------------------
149 rtl::OUString
UpdateCheckROModel::getLocalFileName() const
151 return getStringValue(LOCAL_FILE
);
154 //------------------------------------------------------------------------------
156 sal_Int64
UpdateCheckROModel::getDownloadSize() const
158 uno::Any
aAny( m_aNameAccess
.getValue(DOWNLOAD_SIZE
) );
165 //------------------------------------------------------------------------------
168 UpdateCheckROModel::getUpdateEntryVersion() const
170 return getStringValue(OLD_VERSION
);
173 //------------------------------------------------------------------------------
176 UpdateCheckROModel::getUpdateEntry(UpdateInfo
& rInfo
) const
178 rInfo
.BuildId
= getStringValue(UPDATE_BUILDID
);
179 rInfo
.Version
= getStringValue(UPDATE_VERSION
);
180 rInfo
.Description
= getStringValue(UPDATE_DESCRIPTION
);
182 sal_Bool isDirectDownload
= sal_False
;
183 m_aNameAccess
.getValue(IS_DIRECT_DOWNLOAD
) >>= isDirectDownload
;
185 rInfo
.Sources
.push_back( DownloadSource( isDirectDownload
, getStringValue(DOWNLOAD_URL
) ) );
187 rtl::OString
aStr(RELEASE_NOTE
);
188 for(sal_Int32 n
=1; n
< 6; ++n
)
190 rtl::OUString aUStr
= getStringValue(aStr
+ rtl::OString::valueOf(n
));
191 if( aUStr
.getLength() > 0 )
192 rInfo
.ReleaseNotes
.push_back(ReleaseNote((sal_Int8
) n
, aUStr
));
197 //------------------------------------------------------------------------------
199 rtl::OUString
UpdateCheckConfig::getDesktopDirectory()
204 WCHAR szPath
[MAX_PATH
];
206 if( ! FAILED( SHGetSpecialFolderPathW( NULL
, szPath
, CSIDL_DESKTOPDIRECTORY
, true ) ) )
208 aRet
= rtl::OUString( reinterpret_cast< sal_Unicode
* >(szPath
) );
209 osl::FileBase::getFileURLFromSystemPath( aRet
, aRet
);
212 // This should become a desktop specific setting in some system backend ..
213 rtl::OUString aHomeDir
;
214 osl::Security().getHomeDir( aHomeDir
);
215 aRet
= aHomeDir
+ rtl::OUString::createFromAscii("/Desktop");
217 // Set path to home directory when there is no /Desktop directory
218 osl::Directory
aDocumentsDir( aRet
);
219 if( osl::FileBase::E_None
!= aDocumentsDir
.open() )
226 //------------------------------------------------------------------------------
228 rtl::OUString
UpdateCheckConfig::getAllUsersDirectory()
233 WCHAR szPath
[MAX_PATH
];
235 if( ! FAILED( SHGetSpecialFolderPathW( NULL
, szPath
, CSIDL_COMMON_DOCUMENTS
, true ) ) )
237 aRet
= rtl::OUString( reinterpret_cast< sal_Unicode
* >(szPath
) );
238 osl::FileBase::RC rc
;
239 rc
= osl::FileBase::getFileURLFromSystemPath( aRet
, aRet
);
242 osl::FileBase::getTempDirURL(aRet
);
248 //------------------------------------------------------------------------------
250 UpdateCheckConfig::UpdateCheckConfig(
251 const uno::Reference
<container::XNameContainer
>& xContainer
,
252 const ::rtl::Reference
< UpdateCheckConfigListener
>& rListener
253 ) : m_xContainer(xContainer
), m_rListener(rListener
)
257 //------------------------------------------------------------------------------
259 UpdateCheckConfig::~UpdateCheckConfig()
263 //------------------------------------------------------------------------------
265 ::rtl::Reference
< UpdateCheckConfig
>
266 UpdateCheckConfig::get(
267 const uno::Reference
<uno::XComponentContext
>& xContext
,
268 const ::rtl::Reference
< UpdateCheckConfigListener
>& rListener
)
271 throw uno::RuntimeException(
272 UNISTRING( "UpdateCheckConfig: empty component context" ),
273 uno::Reference
< uno::XInterface
>() );
275 uno::Reference
< lang::XMultiComponentFactory
> xServiceManager(xContext
->getServiceManager());
277 if( !xServiceManager
.is() )
278 throw uno::RuntimeException(
279 UNISTRING( "UpdateCheckConfig: unable to obtain service manager from component context" ),
280 uno::Reference
< uno::XInterface
>() );
282 uno::Reference
< lang::XMultiServiceFactory
> xConfigProvider(
283 xServiceManager
->createInstanceWithContext( UNISTRING( "com.sun.star.configuration.ConfigurationProvider" ), xContext
),
284 uno::UNO_QUERY_THROW
);
286 beans::PropertyValue aProperty
;
287 aProperty
.Name
= UNISTRING( "nodepath" );
288 aProperty
.Value
= uno::makeAny( UNISTRING("org.openoffice.Office.Jobs/Jobs/UpdateCheck/Arguments") );
290 uno::Sequence
< uno::Any
> aArgumentList( 1 );
291 aArgumentList
[0] = uno::makeAny( aProperty
);
293 uno::Reference
< container::XNameContainer
> xContainer(
294 xConfigProvider
->createInstanceWithArguments(
295 UNISTRING("com.sun.star.configuration.ConfigurationUpdateAccess"), aArgumentList
),
296 uno::UNO_QUERY_THROW
);
298 return new UpdateCheckConfig( xContainer
, rListener
);
301 //------------------------------------------------------------------------------
304 UpdateCheckConfig::isAutoCheckEnabled() const
306 sal_Bool nValue
= sal_False
;
307 const_cast < UpdateCheckConfig
*> (this)->getByName( UNISTRING( AUTOCHECK_ENABLED
) ) >>= nValue
;
311 //------------------------------------------------------------------------------
314 UpdateCheckConfig::isAutoDownloadEnabled() const
316 sal_Bool nValue
= sal_False
;
317 const_cast < UpdateCheckConfig
*> (this)->getByName( UNISTRING( AUTODOWNLOAD_ENABLED
) ) >>= nValue
;
321 //------------------------------------------------------------------------------
324 UpdateCheckConfig::getUpdateEntryVersion() const
326 rtl::OUString aValue
;
328 // getByName is defined as non const in XNameAccess
329 const_cast < UpdateCheckConfig
*> (this)->getByName( UNISTRING( OLD_VERSION
) ) >>= aValue
;
334 //------------------------------------------------------------------------------
337 UpdateCheckConfig::getLastChecked() const
339 sal_Int64 nValue
= 0;
341 // getByName is defined as non const in XNameAccess
342 const_cast < UpdateCheckConfig
*> (this)->getByName( UNISTRING( LAST_CHECK
) ) >>= nValue
;
347 //------------------------------------------------------------------------------
350 UpdateCheckConfig::getCheckInterval() const
352 sal_Int64 nValue
= 0;
354 // getByName is defined as non const in XNameAccess
355 const_cast < UpdateCheckConfig
*> (this)->getByName( UNISTRING( CHECK_INTERVAL
) ) >>= nValue
;
360 //------------------------------------------------------------------------------
363 UpdateCheckConfig::getLocalFileName() const
365 rtl::OUString aName
= UNISTRING(LOCAL_FILE
);
368 if( m_xContainer
->hasByName(aName
) )
369 m_xContainer
->getByName(aName
) >>= aRet
;
374 //------------------------------------------------------------------------------
377 UpdateCheckConfig::getDownloadDestination() const
379 rtl::OUString aName
= UNISTRING(DOWNLOAD_DESTINATION
);
382 const_cast <UpdateCheckConfig
*> (this)->getByName(aName
) >>= aRet
;
387 //------------------------------------------------------------------------------
390 UpdateCheckConfig::storeLocalFileName(const rtl::OUString
& rLocalFileName
, sal_Int64 nFileSize
)
392 const sal_uInt8 nItems
= 2;
393 const rtl::OUString aNameList
[nItems
] = { UNISTRING(LOCAL_FILE
), UNISTRING(DOWNLOAD_SIZE
) };
394 const uno::Any aValueList
[nItems
] = { uno::makeAny(rLocalFileName
), uno::makeAny(nFileSize
) };
396 for( sal_uInt8 i
=0; i
< nItems
; ++i
)
398 if( m_xContainer
->hasByName(aNameList
[i
]) )
399 m_xContainer
->replaceByName(aNameList
[i
], aValueList
[i
]);
401 m_xContainer
->insertByName(aNameList
[i
],aValueList
[i
]);
407 //------------------------------------------------------------------------------
410 UpdateCheckConfig::clearLocalFileName()
412 const sal_uInt8 nItems
= 2;
413 const rtl::OUString aNameList
[nItems
] = { UNISTRING(LOCAL_FILE
), UNISTRING(DOWNLOAD_SIZE
) };
415 for( sal_uInt8 i
=0; i
< nItems
; ++i
)
417 if( m_xContainer
->hasByName(aNameList
[i
]) )
418 m_xContainer
->removeByName(aNameList
[i
]);
424 //------------------------------------------------------------------------------
427 UpdateCheckConfig::storeDownloadPaused(bool paused
)
429 replaceByName(UNISTRING(DOWNLOAD_PAUSED
) , uno::makeAny(paused
));
433 //------------------------------------------------------------------------------
436 UpdateCheckConfig::updateLastChecked()
439 osl_getSystemTime(&systime
);
441 sal_Int64 lastCheck
= systime
.Seconds
;
443 replaceByName(UNISTRING(LAST_CHECK
), uno::makeAny(lastCheck
));
446 //------------------------------------------------------------------------------
449 UpdateCheckConfig::storeUpdateFound( const UpdateInfo
& rInfo
, const rtl::OUString
& aCurrentBuild
)
452 bool autoDownloadEnabled
= isAutoDownloadEnabled();
454 uno::Any aValues
[nUpdateEntryProperties
] =
456 uno::makeAny(rInfo
.Version
),
457 uno::makeAny(rInfo
.BuildId
),
458 uno::makeAny(rInfo
.Description
),
459 uno::makeAny(rInfo
.Sources
[0].URL
),
460 uno::makeAny(rInfo
.Sources
[0].IsDirect
? sal_True
: sal_False
),
461 uno::makeAny(getReleaseNote(rInfo
, 1, autoDownloadEnabled
) ),
462 uno::makeAny(getReleaseNote(rInfo
, 2, autoDownloadEnabled
) ),
463 uno::makeAny(getReleaseNote(rInfo
, 3, autoDownloadEnabled
) ),
464 uno::makeAny(getReleaseNote(rInfo
, 4, autoDownloadEnabled
) ),
465 uno::makeAny(getReleaseNote(rInfo
, 5, autoDownloadEnabled
) ),
466 uno::makeAny(aCurrentBuild
)
470 for( sal_uInt32 n
=0; n
< nUpdateEntryProperties
; ++n
)
472 aName
= rtl::OUString::createFromAscii(aUpdateEntryProperties
[n
]);
474 if( m_xContainer
->hasByName(aName
) )
475 m_xContainer
->replaceByName(aName
, aValues
[n
]);
477 m_xContainer
->insertByName(aName
,aValues
[n
]);
483 //------------------------------------------------------------------------------
486 UpdateCheckConfig::clearUpdateFound()
490 for( sal_uInt32 n
=0; n
< nUpdateEntryProperties
; ++n
)
492 aName
= rtl::OUString::createFromAscii(aUpdateEntryProperties
[n
]);
495 if( m_xContainer
->hasByName(aName
) )
496 m_xContainer
->removeByName(aName
);
497 } catch(const lang::WrappedTargetException
& ) {
498 // Can not remove value, probably in share layer
500 m_xContainer
->replaceByName(aName
, uno::makeAny(rtl::OUString()));
504 /* As we have removed UpdateVersionFound from the shared configuration
505 * existing entries in the user layer do not have a oor operation and
506 * thus are completly ignored (which also means they can not be removed).
512 //------------------------------------------------------------------------------
514 uno::Sequence
< rtl::OUString
>
515 UpdateCheckConfig::getServiceNames()
517 uno::Sequence
< rtl::OUString
> aServiceList(1);
518 aServiceList
[0] = UNISTRING( "com.sun.star.setup.UpdateCheckConfig");
522 //------------------------------------------------------------------------------
525 UpdateCheckConfig::getImplName()
527 return UNISTRING( "vnd.sun.UpdateCheckConfig");
530 //------------------------------------------------------------------------------
533 UpdateCheckConfig::getElementType() throw (uno::RuntimeException
)
535 return m_xContainer
->getElementType();
538 //------------------------------------------------------------------------------
541 UpdateCheckConfig::hasElements() throw (uno::RuntimeException
)
543 return m_xContainer
->hasElements();
546 //------------------------------------------------------------------------------
549 UpdateCheckConfig::getByName( const ::rtl::OUString
& aName
)
550 throw (container::NoSuchElementException
, lang::WrappedTargetException
, uno::RuntimeException
)
552 uno::Any aValue
= m_xContainer
->getByName( aName
);
554 // Provide dynamic default value
555 if( aName
.equalsAscii(DOWNLOAD_DESTINATION
) )
560 if( aStr
.getLength() == 0 )
561 aValue
= uno::makeAny(getDesktopDirectory());
567 //------------------------------------------------------------------------------
569 uno::Sequence
< ::rtl::OUString
> SAL_CALL
570 UpdateCheckConfig::getElementNames( ) throw (uno::RuntimeException
)
572 return m_xContainer
->getElementNames();
575 //------------------------------------------------------------------------------
578 UpdateCheckConfig::hasByName( const ::rtl::OUString
& aName
) throw (uno::RuntimeException
)
580 return m_xContainer
->hasByName( aName
);
583 //------------------------------------------------------------------------------
586 UpdateCheckConfig::replaceByName( const ::rtl::OUString
& aName
, const uno::Any
& aElement
)
587 throw (lang::IllegalArgumentException
, container::NoSuchElementException
,
588 lang::WrappedTargetException
, uno::RuntimeException
)
590 return m_xContainer
->replaceByName( aName
, aElement
);
593 //------------------------------------------------------------------------------
597 UpdateCheckConfig::commitChanges()
598 throw (lang::WrappedTargetException
, uno::RuntimeException
)
600 uno::Reference
< util::XChangesBatch
> xChangesBatch(m_xContainer
, uno::UNO_QUERY
);
601 if( xChangesBatch
.is() && xChangesBatch
->hasPendingChanges() )
603 util::ChangesSet aChangesSet
= xChangesBatch
->getPendingChanges();
604 xChangesBatch
->commitChanges();
606 if( m_rListener
.is() )
608 const sal_Int32 nChanges
= aChangesSet
.getLength();
609 rtl::OUString aString
;
611 for( sal_Int32 i
=0; i
<nChanges
; ++i
)
613 aChangesSet
[i
].Accessor
>>= aString
;
615 // FIXME: use non IgnoreAsciiCase version as soon as it becomes available
616 if( aString
.endsWithIgnoreAsciiCaseAsciiL(AUTOCHECK_ENABLED
"']", sizeof(AUTOCHECK_ENABLED
)+1) )
618 sal_Bool bEnabled
= sal_False
;
619 aChangesSet
[i
].Element
>>= bEnabled
;
620 m_rListener
->autoCheckStatusChanged(sal_True
== bEnabled
);
622 // FIXME: use non IgnoreAsciiCase version as soon as it becomes available
623 else if( aString
.endsWithIgnoreAsciiCaseAsciiL(CHECK_INTERVAL
"']", sizeof(CHECK_INTERVAL
)+1) )
625 m_rListener
->autoCheckIntervalChanged();
632 //------------------------------------------------------------------------------
635 UpdateCheckConfig::hasPendingChanges( ) throw (uno::RuntimeException
)
637 uno::Reference
< util::XChangesBatch
> xChangesBatch(m_xContainer
, uno::UNO_QUERY
);
638 if( xChangesBatch
.is() )
639 return xChangesBatch
->hasPendingChanges();
644 //------------------------------------------------------------------------------
646 uno::Sequence
< util::ElementChange
> SAL_CALL
647 UpdateCheckConfig::getPendingChanges( ) throw (uno::RuntimeException
)
649 uno::Reference
< util::XChangesBatch
> xChangesBatch(m_xContainer
, uno::UNO_QUERY
);
650 if( xChangesBatch
.is() )
651 return xChangesBatch
->getPendingChanges();
653 return uno::Sequence
< util::ElementChange
>();
656 //------------------------------------------------------------------------------
657 void UpdateCheckConfig::storeExtensionVersion( const rtl::OUString
& rExtensionName
,
658 const rtl::OUString
& rVersion
)
660 const rtl::OUString aExtName
= UNISTRING( EXTENSION_PREFIX
) + rExtensionName
;
661 const uno::Any aValue
= uno::makeAny( rVersion
);
663 if( m_xContainer
->hasByName( aExtName
) )
664 m_xContainer
->replaceByName( aExtName
, aValue
);
666 m_xContainer
->insertByName( aExtName
, aValue
);
671 //------------------------------------------------------------------------------
672 bool UpdateCheckConfig::checkExtensionVersion( const rtl::OUString
& rExtensionName
,
673 const rtl::OUString
& rVersion
)
675 const rtl::OUString aExtName
= UNISTRING( EXTENSION_PREFIX
) + rExtensionName
;
677 if( m_xContainer
->hasByName( aExtName
) )
679 uno::Any aValue
= m_xContainer
->getByName( aExtName
);
680 rtl::OUString aStoredVersion
;
681 aValue
>>= aStoredVersion
;
683 if ( isVersionGreater( rVersion
, aStoredVersion
) )
687 m_xContainer
->removeByName( aExtName
);
694 //------------------------------------------------------------------------------
695 rtl::OUString
UpdateCheckConfig::getSubVersion( const rtl::OUString
& rVersion
,
698 while ( *nIndex
< rVersion
.getLength() && rVersion
[*nIndex
] == '0')
703 return rVersion
.getToken( 0, '.', *nIndex
);
706 //------------------------------------------------------------------------------
707 // checks if the second version string is greater than the first one
709 bool UpdateCheckConfig::isVersionGreater( const rtl::OUString
& rVersion1
,
710 const rtl::OUString
& rVersion2
)
712 for ( sal_Int32 i1
= 0, i2
= 0; i1
>= 0 || i2
>= 0; )
714 ::rtl::OUString
sSub1( getSubVersion( rVersion1
, &i1
) );
715 ::rtl::OUString
sSub2( getSubVersion( rVersion2
, &i2
) );
717 if ( sSub1
.getLength() < sSub2
.getLength() ) {
719 } else if ( sSub1
.getLength() > sSub2
.getLength() ) {
721 } else if ( sSub1
< sSub2
) {
723 } else if ( sSub1
> sSub2
) {
730 //------------------------------------------------------------------------------
731 //------------------------------------------------------------------------------
732 //------------------------------------------------------------------------------
734 rtl::OUString SAL_CALL
735 UpdateCheckConfig::getImplementationName() throw (uno::RuntimeException
)
737 return getImplName();
740 //------------------------------------------------------------------------------
743 UpdateCheckConfig::supportsService(rtl::OUString
const & serviceName
)
744 throw (uno::RuntimeException
)
746 uno::Sequence
< rtl::OUString
> aServiceNameList
= getServiceNames();
748 for( sal_Int32 n
=0; n
< aServiceNameList
.getLength(); n
++ )
749 if( aServiceNameList
[n
].equals(serviceName
) )
755 //------------------------------------------------------------------------------
757 uno::Sequence
< rtl::OUString
> SAL_CALL
758 UpdateCheckConfig::getSupportedServiceNames() throw (uno::RuntimeException
)
760 return getServiceNames();