summaryrefslogtreecommitdiff
path: root/extensions/source/update
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/source/update')
-rw-r--r--extensions/source/update/check/Addons.xcu26
-rw-r--r--extensions/source/update/check/Jobs.xcu42
-rw-r--r--extensions/source/update/check/actionlistener.hxx49
-rw-r--r--extensions/source/update/check/download.cxx384
-rw-r--r--extensions/source/update/check/download.hxx85
-rw-r--r--extensions/source/update/check/makefile.mk138
-rw-r--r--extensions/source/update/check/transform.pl65
-rw-r--r--extensions/source/update/check/updatecheck.cxx1643
-rw-r--r--extensions/source/update/check/updatecheck.hxx195
-rw-r--r--extensions/source/update/check/updatecheckconfig.cxx763
-rw-r--r--extensions/source/update/check/updatecheckconfig.hxx241
-rw-r--r--extensions/source/update/check/updatecheckconfiglistener.hxx46
-rw-r--r--extensions/source/update/check/updatecheckjob.cxx429
-rw-r--r--extensions/source/update/check/updatehdl.cxx1318
-rw-r--r--extensions/source/update/check/updatehdl.hrc83
-rw-r--r--extensions/source/update/check/updatehdl.hxx218
-rw-r--r--extensions/source/update/check/updatehdl.src252
-rw-r--r--extensions/source/update/check/updateinfo.hxx89
-rw-r--r--extensions/source/update/check/updateprotocol.cxx336
-rw-r--r--extensions/source/update/check/updateprotocol.hxx59
-rw-r--r--extensions/source/update/check/updateprotocoltest.cxx97
-rw-r--r--extensions/source/update/check/updchk.xml49
-rw-r--r--extensions/source/update/exports.map10
-rw-r--r--extensions/source/update/feed/makefile.mk74
-rw-r--r--extensions/source/update/feed/test/makefile.mk62
-rw-r--r--extensions/source/update/feed/test/updatefeedtest.cxx109
-rw-r--r--extensions/source/update/feed/updatefeed.cxx1180
-rw-r--r--extensions/source/update/feed/updatefeed.xml49
-rw-r--r--extensions/source/update/tools/makefile.mk72
-rw-r--r--extensions/source/update/tools/ztool.cxx66
-rw-r--r--extensions/source/update/ui/makefile.mk78
-rw-r--r--extensions/source/update/ui/updatecheckui.cxx1086
-rw-r--r--extensions/source/update/ui/updatecheckui.hrc39
-rw-r--r--extensions/source/update/ui/updatecheckui.src54
-rw-r--r--extensions/source/update/ui/updchkui.xml34
35 files changed, 9520 insertions, 0 deletions
diff --git a/extensions/source/update/check/Addons.xcu b/extensions/source/update/check/Addons.xcu
new file mode 100644
index 000000000000..8794ce858073
--- /dev/null
+++ b/extensions/source/update/check/Addons.xcu
@@ -0,0 +1,26 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<oor:component-data oor:name="Addons" oor:package="org.openoffice.Office" xmlns:install="http://openoffice.org/2004/installation" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <node oor:name="AddonUI">
+ <node oor:name="OfficeHelp">
+ <node oor:name="UpdateCheckJob" oor:op="replace">
+ <prop oor:name="URL" oor:type="xs:string">
+ <value>vnd.sun.star.job:alias=UpdateCheck</value>
+ </prop>
+ <prop oor:name="ImageIdentifier" oor:type="xs:string">
+ <value/>
+ </prop>
+ <prop oor:name="Title" oor:type="xs:string">
+ <value xml:lang="en-US">Check for ~Updates...</value>
+ </prop>
+ <prop oor:name="Target" oor:type="xs:string">
+ <value>_self</value>
+ </prop>
+ <prop oor:name="Context" oor:type="xs:string">
+ <value/>
+ </prop>
+ </node>
+ </node>
+ </node>
+</oor:component-data>
+
diff --git a/extensions/source/update/check/Jobs.xcu b/extensions/source/update/check/Jobs.xcu
new file mode 100644
index 000000000000..ed324650c66f
--- /dev/null
+++ b/extensions/source/update/check/Jobs.xcu
@@ -0,0 +1,42 @@
+<?xml version='1.0' encoding='UTF-8'?>
+
+<oor:component-data oor:name="Jobs" oor:package="org.openoffice.Office" xmlns:install="http://openoffice.org/2004/installation" xmlns:oor="http://openoffice.org/2001/registry" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <node oor:name="Jobs">
+ <node oor:name="UpdateCheck" oor:op="replace">
+ <prop oor:name="Service">
+ <value>com.sun.star.setup.UpdateCheck</value>
+ </prop>
+ <node oor:name="Arguments">
+ <prop oor:name="AutoCheckEnabled" oor:type="xs:boolean" oor:op="replace">
+ <value>false</value>
+ </prop>
+ <prop oor:name="LastCheck" oor:type="xs:long" oor:op="replace">
+ <value>0</value>
+ </prop>
+ <prop oor:name="CheckInterval" oor:type="xs:long" oor:op="replace">
+ <value>604800</value>
+ </prop>
+ <prop oor:name="DownloadDestination" oor:type="xs:string" oor:op="replace">
+ <value></value>
+ </prop>
+ <prop oor:name="AutoDownloadEnabled" oor:type="xs:boolean" oor:op="replace">
+ <value>false</value>
+ </prop>
+ <prop oor:name="DownloadSupported" oor:type="xs:boolean" oor:op="replace">
+ <value>true</value>
+ </prop>
+ <prop oor:name="DownloadPaused" oor:type="xs:boolean" oor:op="replace">
+ <value>false</value>
+ </prop>
+ </node>
+ </node>
+ </node>
+ <node oor:name="Events">
+ <node oor:name="onFirstVisibleTask" oor:op="fuse">
+ <node oor:name="JobList">
+ <node oor:name="UpdateCheck" oor:op="replace"/>
+ </node>
+ </node>
+ </node>
+</oor:component-data>
+
diff --git a/extensions/source/update/check/actionlistener.hxx b/extensions/source/update/check/actionlistener.hxx
new file mode 100644
index 000000000000..76f942d402d7
--- /dev/null
+++ b/extensions/source/update/check/actionlistener.hxx
@@ -0,0 +1,49 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: actionlistener.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_ACTION_LISTENER_HXX
+#define INCLUDED_ACTION_LISTENER_HXX
+
+#include <rtl/ref.hxx>
+
+class IActionListener : public rtl::IReference
+{
+ public:
+
+ virtual void cancel() = 0;
+ virtual void download() = 0;
+ virtual void install() = 0;
+ virtual void pause() = 0;
+ virtual void resume() = 0;
+ virtual void closeAfterFailure() = 0;
+};
+
+#endif //INCLUDED_ACTION_LISTENER_HXX
+
diff --git a/extensions/source/update/check/download.cxx b/extensions/source/update/check/download.cxx
new file mode 100644
index 000000000000..eaa16a9f9368
--- /dev/null
+++ b/extensions/source/update/check/download.cxx
@@ -0,0 +1,384 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: download.cxx,v $
+ * $Revision: 1.7.88.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+
+#if defined WNT
+#ifdef _MSC_VER
+#pragma warning(push, 1) /* disable warnings within system headers */
+#endif
+#include <curl/curl.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#else
+#include <curl/curl.h>
+#endif
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+
+#include "download.hxx"
+
+namespace beans = com::sun::star::beans ;
+namespace container = com::sun::star::container ;
+namespace lang = com::sun::star::lang ;
+namespace uno = com::sun::star::uno ;
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+
+struct OutData
+{
+ rtl::Reference< DownloadInteractionHandler >Handler;
+ rtl::OUString File;
+ rtl::OUString DestinationDir;
+ oslFileHandle FileHandle;
+ sal_uInt64 Offset;
+ osl::Condition& StopCondition;
+ CURL *curl;
+
+ OutData(osl::Condition& rCondition) : FileHandle(NULL), Offset(0), StopCondition(rCondition), curl(NULL) {};
+};
+
+//------------------------------------------------------------------------------
+
+static void openFile( OutData& out )
+{
+ char * effective_url;
+ curl_easy_getinfo(out.curl, CURLINFO_EFFECTIVE_URL, &effective_url);
+
+ double fDownloadSize;
+ curl_easy_getinfo(out.curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &fDownloadSize);
+
+ rtl::OString aURL(effective_url);
+
+ // ensure no trailing '/'
+ sal_Int32 nLen = aURL.getLength();
+ while( (nLen > 0) && ('/' == aURL[nLen-1]) )
+ aURL = aURL.copy(0, --nLen);
+
+ // extract file name last '/'
+ sal_Int32 nIndex = aURL.lastIndexOf('/');
+ if( nIndex > 0 )
+ {
+ out.File = out.DestinationDir + rtl::OStringToOUString(aURL.copy(nIndex), RTL_TEXTENCODING_UTF8);
+
+ oslFileError rc;
+
+ // Give the user an overwrite warning if the target file exists
+ const sal_Int32 openFlags = osl_File_OpenFlag_Write | osl_File_OpenFlag_Create;
+ do
+ {
+ rc = osl_openFile(out.File.pData, &out.FileHandle, openFlags);
+
+ if( osl_File_E_EXIST == rc && ! out.Handler->downloadTargetExists(out.File) )
+ {
+ out.StopCondition.set();
+ break;
+ }
+
+ } while( osl_File_E_EXIST == rc );
+
+ if( osl_File_E_None == rc )
+ out.Handler->downloadStarted(out.File, (sal_Int64) fDownloadSize);
+ }
+}
+
+//------------------------------------------------------------------------------
+
+static inline rtl::OString
+getStringValue(const uno::Reference< container::XNameAccess >& xNameAccess, const rtl::OUString& aName)
+{
+ rtl::OString aRet;
+
+ OSL_ASSERT(xNameAccess->hasByName(aName));
+ uno::Any aValue = xNameAccess->getByName(aName);
+
+ return rtl::OUStringToOString(aValue.get<rtl::OUString>(), RTL_TEXTENCODING_UTF8);
+}
+
+//------------------------------------------------------------------------------
+
+static inline sal_Int32
+getInt32Value(const uno::Reference< container::XNameAccess >& xNameAccess,
+ const rtl::OUString& aName, sal_Int32 nDefault=-1)
+{
+ OSL_ASSERT(xNameAccess->hasByName(aName));
+ uno::Any aValue = xNameAccess->getByName(aName);
+
+ sal_Int32 n=nDefault;
+ aValue >>= n;
+ return n;
+}
+
+//------------------------------------------------------------------------------
+
+static size_t
+write_function( void *ptr, size_t size, size_t nmemb, void *stream )
+{
+ OutData *out = reinterpret_cast < OutData * > (stream);
+
+ if( NULL == out->FileHandle )
+ openFile(*out);
+
+ sal_uInt64 nBytesWritten = 0;
+
+ if( NULL != out->FileHandle )
+ osl_writeFile(out->FileHandle, ptr, size * nmemb, &nBytesWritten);
+
+ return (size_t) nBytesWritten;
+}
+
+//------------------------------------------------------------------------------
+
+static int
+progress_callback( void *clientp, double dltotal, double dlnow, double ultotal, double ulnow )
+{
+ (void) ultotal;
+ (void) ulnow;
+
+ OutData *out = reinterpret_cast < OutData * > (clientp);
+
+ OSL_ASSERT( out );
+
+ if( ! out->StopCondition.check() )
+ {
+ double fPercent = (dlnow + out->Offset) * 100 / (dltotal + out->Offset);
+ if( fPercent < 0 )
+ fPercent = 0;
+
+ // Do not report progress for redirection replies
+ long nCode;
+ curl_easy_getinfo(out->curl, CURLINFO_RESPONSE_CODE, &nCode);
+ if( (nCode != 302) && (nCode != 303) && (dltotal > 0) )
+ out->Handler->downloadProgressAt((sal_Int8)fPercent);
+
+ return 0;
+ }
+
+ // If stop condition is set, return non 0 value to abort
+ return -1;
+}
+
+//------------------------------------------------------------------------------
+
+void
+Download::getProxyForURL(const rtl::OUString& rURL, rtl::OString& rHost, sal_Int32& rPort) const
+{
+ if( !m_xContext.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "Download: empty component context" ),
+ uno::Reference< uno::XInterface >() );
+
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager(m_xContext->getServiceManager());
+
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "Download: unable to obtain service manager from component context" ),
+ uno::Reference< uno::XInterface >() );
+
+ uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
+ xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.configuration.ConfigurationProvider" ), m_xContext ),
+ uno::UNO_QUERY_THROW);
+
+ beans::PropertyValue aProperty;
+ aProperty.Name = UNISTRING( "nodepath" );
+ aProperty.Value = uno::makeAny( UNISTRING("org.openoffice.Inet/Settings") );
+
+ uno::Sequence< uno::Any > aArgumentList( 1 );
+ aArgumentList[0] = uno::makeAny( aProperty );
+
+ uno::Reference< container::XNameAccess > xNameAccess(
+ xConfigProvider->createInstanceWithArguments(
+ UNISTRING("com.sun.star.configuration.ConfigurationAccess"), aArgumentList ),
+ uno::UNO_QUERY_THROW );
+
+ OSL_ASSERT(xNameAccess->hasByName(UNISTRING("ooInetProxyType")));
+ uno::Any aValue = xNameAccess->getByName(UNISTRING("ooInetProxyType"));
+
+ sal_Int32 nProxyType = aValue.get< sal_Int32 >();
+ if( 0 != nProxyType ) // type 0 means "direct connection to the internet
+ {
+ if( rURL.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("http:")) )
+ {
+ rHost = getStringValue(xNameAccess, UNISTRING("ooInetHTTPProxyName"));
+ rPort = getInt32Value(xNameAccess, UNISTRING("ooInetHTTPProxyPort"));
+ }
+ else if( rURL.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("https:")) )
+ {
+ rHost = getStringValue(xNameAccess, UNISTRING("ooInetHTTPSProxyName"));
+ rPort = getInt32Value(xNameAccess, UNISTRING("ooInetHTTPSProxyPort"));
+ }
+ else if( rURL.matchAsciiL(RTL_CONSTASCII_STRINGPARAM("ftp:")) )
+ {
+ rHost = getStringValue(xNameAccess, UNISTRING("ooInetFTPProxyName"));
+ rPort = getInt32Value(xNameAccess, UNISTRING("ooInetFTPProxyPort"));
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+bool curl_run(const rtl::OUString& rURL, OutData& out, const rtl::OString& aProxyHost, sal_Int32 nProxyPort)
+{
+ /* Need to investigate further whether it is necessary to call
+ * curl_global_init or not - leave it for now (as the ftp UCB content
+ * provider does as well).
+ */
+
+ CURL * pCURL = curl_easy_init();
+ bool ret = false;
+
+ if( NULL != pCURL )
+ {
+ out.curl = pCURL;
+
+ rtl::OString aURL(rtl::OUStringToOString(rURL, RTL_TEXTENCODING_UTF8));
+ curl_easy_setopt(pCURL, CURLOPT_URL, aURL.getStr());
+
+ // enable redirection
+ curl_easy_setopt(pCURL, CURLOPT_FOLLOWLOCATION, 1);
+
+ // write function
+ curl_easy_setopt(pCURL, CURLOPT_WRITEDATA, &out);
+ curl_easy_setopt(pCURL, CURLOPT_WRITEFUNCTION, &write_function);
+
+ // progress handler - Condition::check unfortunatly is not defined const
+ curl_easy_setopt(pCURL, CURLOPT_NOPROGRESS, 0);
+ curl_easy_setopt(pCURL, CURLOPT_PROGRESSFUNCTION, &progress_callback);
+ curl_easy_setopt(pCURL, CURLOPT_PROGRESSDATA, &out);
+
+ // proxy
+ curl_easy_setopt(pCURL, CURLOPT_PROXY, aProxyHost.getStr());
+ curl_easy_setopt(pCURL, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
+ if( -1 != nProxyPort )
+ curl_easy_setopt(pCURL, CURLOPT_PROXYPORT, nProxyPort);
+
+ if( out.Offset > 0 )
+ {
+ // curl_off_t offset = nOffset; libcurl seems to be compiled with large
+ // file support (and we not) ..
+ sal_Int64 offset = (sal_Int64) out.Offset;
+ curl_easy_setopt(pCURL, CURLOPT_RESUME_FROM_LARGE, offset);
+ }
+
+ CURLcode cc = curl_easy_perform(pCURL);
+
+ // treat zero byte downloads as errors
+ if( NULL == out.FileHandle )
+ openFile(out);
+
+ if( CURLE_OK == cc )
+ {
+ out.Handler->downloadFinished(out.File);
+ ret = true;
+ }
+
+ // Avoid target file being removed
+ else if( (CURLE_ABORTED_BY_CALLBACK == cc) || out.StopCondition.check() )
+ ret = true;
+
+ // Only report errors when not stopped
+ else
+ {
+ rtl::OString aMessage(RTL_CONSTASCII_STRINGPARAM("Unknown error"));
+
+ const char * error_message = curl_easy_strerror(cc);
+ if( NULL != error_message )
+ aMessage = error_message;
+
+ out.Handler->downloadStalled( rtl::OStringToOUString(aMessage, RTL_TEXTENCODING_UTF8) );
+ }
+
+ curl_easy_cleanup(pCURL);
+ }
+
+ return ret;
+}
+
+//------------------------------------------------------------------------------
+
+bool
+Download::start(const rtl::OUString& rURL, const rtl::OUString& rFile, const rtl::OUString& rDestinationDir)
+{
+ OSL_ASSERT( m_aHandler.is() );
+
+ OutData out(m_aCondition);
+
+ out.File = rFile;
+ out.DestinationDir = rDestinationDir;
+ out.Handler = m_aHandler;
+
+ if( rFile.getLength() > 0 )
+ {
+ oslFileError rc = osl_openFile(rFile.pData, &out.FileHandle, osl_File_OpenFlag_Write);
+
+ if( osl_File_E_None == rc )
+ {
+ // Set file pointer to the end of the file on resume
+ if( osl_File_E_None == osl_setFilePos(out.FileHandle, osl_Pos_End, 0) )
+ {
+ osl_getFilePos(out.FileHandle, &out.Offset);
+ }
+ }
+ else if( osl_File_E_NOENT == rc ) // file has been deleted meanwhile ..
+ out.File = rtl::OUString();
+ }
+
+ rtl::OString aProxyHost;
+ sal_Int32 nProxyPort = -1;
+ getProxyForURL(rURL, aProxyHost, nProxyPort);
+
+ bool ret = curl_run(rURL, out, aProxyHost, nProxyPort);
+
+ if( NULL != out.FileHandle )
+ {
+ osl_syncFile(out.FileHandle);
+ osl_closeFile(out.FileHandle);
+
+// #i90930# Don't remove already downloaded bits, when curl_run reports an error
+// because later calls might be successful
+// if( ! ret )
+// osl_removeFile(out.File.pData);
+ }
+
+ m_aCondition.reset();
+ return ret;
+}
+
+//------------------------------------------------------------------------------
+
+void
+Download::stop()
+{
+ m_aCondition.set();
+}
diff --git a/extensions/source/update/check/download.hxx b/extensions/source/update/check/download.hxx
new file mode 100644
index 000000000000..24c2842a709d
--- /dev/null
+++ b/extensions/source/update/check/download.hxx
@@ -0,0 +1,85 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: download.hxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <rtl/ref.hxx>
+#include <rtl/ustring.hxx>
+#include <osl/conditn.hxx>
+#include <osl/file.h>
+
+struct DownloadInteractionHandler : public rtl::IReference
+{
+ // called if the destination file already exists, but resume is false
+ virtual bool downloadTargetExists(const rtl::OUString& rFileName) = 0;
+
+ // called when curl reports an error
+ virtual void downloadStalled(const rtl::OUString& rErrorMessage) = 0;
+
+ // progress handler
+ virtual void downloadProgressAt(sal_Int8 nPercent) = 0;
+
+ // called on first progress notification
+ virtual void downloadStarted(const rtl::OUString& rFileName, sal_Int64 nFileSize) = 0;
+
+ // called when download has been finished
+ virtual void downloadFinished(const rtl::OUString& rFileName) = 0;
+};
+
+
+class Download
+{
+public:
+ Download(const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& xContext,
+ const rtl::Reference< DownloadInteractionHandler >& rHandler) : m_xContext(xContext), m_aHandler(rHandler) {};
+
+ // returns true when the content of rURL was successfully written to rLocalFile
+ bool start(const rtl::OUString& rURL, const rtl::OUString& rFile, const rtl::OUString& rDestinationDir);
+
+ // stops the download after the next write operation
+ void stop();
+
+ // returns true if the stop condition is set
+ bool isStopped() const
+ { return sal_True == const_cast <Download *> (this)->m_aCondition.check(); };
+
+protected:
+
+ // Determines the appropriate proxy settings for the given URL. Returns true if a proxy should be used
+ void getProxyForURL(const rtl::OUString& rURL, rtl::OString& rHost, sal_Int32& rPort) const;
+
+private:
+ osl::Condition m_aCondition;
+ const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& m_xContext;
+ const rtl::Reference< DownloadInteractionHandler > m_aHandler;
+};
+
+
diff --git a/extensions/source/update/check/makefile.mk b/extensions/source/update/check/makefile.mk
new file mode 100644
index 000000000000..1824a1f63c7d
--- /dev/null
+++ b/extensions/source/update/check/makefile.mk
@@ -0,0 +1,138 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.12 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..$/..$/..
+
+PRJNAME=extensions
+TARGET=updchk
+PACKAGE=org.openoffice.Office
+
+LIBTARGET=NO
+ENABLE_EXCEPTIONS=TRUE
+
+ABSXCSROOT=$(SOLARXMLDIR)
+XCSROOT=..
+DTDDIR=$(ABSXCSROOT)
+XSLDIR=$(ABSXCSROOT)$/processing
+PROCESSOUT=$(MISC)$/$(TARGET)
+PROCESSORDIR=$(SOLARBINDIR)
+
+# no validation by inspector class
+NO_INSPECTION=TRUE
+
+# --- Settings ---
+
+.INCLUDE : settings.mk
+
+# no "lib" prefix
+DLLPRE =
+
+# --- Files ---
+
+SRS2NAME=$(TARGET)
+SRC2FILES=\
+ updatehdl.src
+
+RESLIB2NAME=upd
+RESLIB2SRSFILES= $(SRS)$/updchk.srs
+RESLIB2DEPN= updatehdl.src updatehdl.hrc
+
+SLOFILES=\
+ $(SLO)$/download.obj \
+ $(SLO)$/updatecheck.obj \
+ $(SLO)$/updatecheckjob.obj \
+ $(SLO)$/updatecheckconfig.obj \
+ $(SLO)$/updateprotocol.obj \
+ $(SLO)$/updatehdl.obj
+
+SHL1NOCHECK=TRUE
+SHL1TARGET=$(TARGET).uno
+SHL1OBJS=$(SLOFILES)
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+
+SHL1IMPLIB=i$(SHL1TARGET)
+SHL1STDLIBS= \
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
+ $(CURLLIB) \
+ $(SALLIB) \
+ $(SHELL32LIB) \
+ $(OLE32LIB)
+
+SHL1VERSIONMAP=..$/exports.map
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+DEF1NAME=$(SHL1TARGET)
+
+PACKAGEDIR=$(subst,.,$/ $(PACKAGE))
+SPOOLDIR=$(MISC)$/registry$/spool
+
+XCUFILES= \
+ Addons.xcu \
+ Jobs.xcu
+
+MYXCUFILES= \
+ $(SPOOLDIR)$/$(PACKAGEDIR)$/Addons$/Addons-onlineupdate.xcu \
+ $(SPOOLDIR)$/$(PACKAGEDIR)$/Jobs$/Jobs-onlineupdate.xcu
+
+LOCALIZEDFILES= \
+ Addons.xcu \
+ Jobs.xcu
+
+.IF "$(test)" != ""
+APP1TARGET=updateprotocoltest
+APP1STDLIBS= $(SHL1STDLIBS)
+APP1OBJS= \
+ $(SLO)$/updateprotocol.obj \
+ $(SLO)$/updateprotocoltest.obj
+
+
+.ENDIF # "$(test)" != ""
+
+# --- Targets ---
+
+.INCLUDE : target.mk
+
+ALLTAR : $(MYXCUFILES)
+
+.IF "$(WITH_LANG)"!=""
+XCU_SOURCEDIR:=$(PROCESSOUT)$/merge$/$(PACKAGEDIR)
+.ELSE # "$(WITH_LANG)"!=""
+XCU_SOURCEDIR:=.
+.ENDIF # "$(WITH_LANG)"!=""
+
+$(SPOOLDIR)$/$(PACKAGEDIR)$/Addons$/Addons-onlineupdate.xcu : $(XCU_SOURCEDIR)$/Addons.xcu
+ @-$(MKDIRHIER) $(@:d)
+ @$(COPY) $< $@
+
+$(SPOOLDIR)$/$(PACKAGEDIR)$/Jobs$/Jobs-onlineupdate.xcu : $(XCU_SOURCEDIR)$/Jobs.xcu
+ @-$(MKDIRHIER) $(@:d)
+ @$(COPY) $< $@
+# @$(PERL) transform.pl < $< > $@
+
diff --git a/extensions/source/update/check/transform.pl b/extensions/source/update/check/transform.pl
new file mode 100644
index 000000000000..79859cb455a4
--- /dev/null
+++ b/extensions/source/update/check/transform.pl
@@ -0,0 +1,65 @@
+:
+eval 'exec perl -wS $0 ${1+"$@"}'
+ if 0;
+
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: transform.pl,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+while (<>) {
+
+ if( /<prop/ ) {
+ $prop = $_;
+ next if( /Text/ || /Bubble/ );
+ }
+
+ if( /<\/prop>/ ) {
+ next if( $prop =~ /Text/ || $prop =~ /Bubble/ );
+ }
+
+ if( /xml:lang/ ) {
+ $lang = $_;
+ $lang =~ s/.*xml:lang=\"//;
+ $lang =~ s/\".*//;
+ chomp $lang;
+ $line = $prop;
+ $line =~ s/\" oor:type/_$lang\" oor:type/;
+ print $line;
+ $line = $_;
+ $line =~ s/ xml:lang=\".*\"//;
+ print $line;
+ $line = $prop;
+ $line =~ s/<prop.*/<\/prop>/;
+ print $line;
+ next;
+ }
+
+ print;
+} \ No newline at end of file
diff --git a/extensions/source/update/check/updatecheck.cxx b/extensions/source/update/check/updatecheck.cxx
new file mode 100644
index 000000000000..7ca5e97239d1
--- /dev/null
+++ b/extensions/source/update/check/updatecheck.cxx
@@ -0,0 +1,1643 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatecheck.cxx,v $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+
+#include "updatecheck.hxx"
+
+#include <cppuhelper/implbase1.hxx>
+#include <com/sun/star/beans/XFastPropertySet.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/frame/XFrame.hpp>
+#include <com/sun/star/frame/DispatchResultEvent.hpp>
+#include <com/sun/star/frame/DispatchResultState.hpp>
+#include <com/sun/star/system/XSystemShellExecute.hpp>
+#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
+#include <com/sun/star/task/XJob.hpp>
+#include <com/sun/star/task/XJobExecutor.hpp>
+
+// #include <comphelper/processfactory.hxx>
+
+#include <rtl/ustrbuf.hxx>
+
+#include <rtl/bootstrap.hxx>
+#include <osl/process.h>
+#include <osl/module.hxx>
+#include <osl/file.hxx>
+
+#ifdef WNT
+#ifdef _MSC_VER
+#pragma warning(push,1) // disable warnings within system headers
+//#pragma warning(disable: 4917)
+#endif
+#include <objbase.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#endif
+
+#include "updateprotocol.hxx"
+#include "updatecheckconfig.hxx"
+
+namespace awt = com::sun::star::awt ;
+namespace beans = com::sun::star::beans ;
+namespace container = com::sun::star::container ;
+namespace deployment = com::sun::star::deployment ;
+namespace frame = com::sun::star::frame ;
+namespace lang = com::sun::star::lang ;
+namespace c3s = com::sun::star::system ;
+namespace task = com::sun::star::task ;
+namespace util = com::sun::star::util ;
+namespace uno = com::sun::star::uno ;
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+#define PROPERTY_TITLE UNISTRING("BubbleHeading")
+#define PROPERTY_TEXT UNISTRING("BubbleText")
+#define PROPERTY_IMAGE UNISTRING("BubbleImageURL")
+#define PROPERTY_SHOW_BUBBLE UNISTRING("BubbleVisible")
+#define PROPERTY_CLICK_HDL UNISTRING("MenuClickHDL")
+#define PROPERTY_DEFAULT_TITLE UNISTRING("DefaultHeading")
+#define PROPERTY_DEFAULT_TEXT UNISTRING("DefaultText")
+#define PROPERTY_SHOW_MENUICON UNISTRING("MenuIconVisible")
+
+//------------------------------------------------------------------------------
+
+// Returns the URL of the release note for the given position
+rtl::OUString getReleaseNote(const UpdateInfo& rInfo, sal_uInt8 pos, bool autoDownloadEnabled)
+{
+ std::vector< ReleaseNote >::const_iterator iter = rInfo.ReleaseNotes.begin();
+ while( iter != rInfo.ReleaseNotes.end() )
+ {
+ if( pos == iter->Pos )
+ {
+ if( (pos > 2) || !autoDownloadEnabled || ! (iter->URL2.getLength() > 0) )
+ return iter->URL;
+ }
+ else if( (pos == iter->Pos2) && ((1 == iter->Pos) || (2 == iter->Pos)) && autoDownloadEnabled )
+ return iter->URL2;
+
+ ++iter;
+ }
+
+ return rtl::OUString();
+}
+
+//------------------------------------------------------------------------------
+
+namespace
+{
+
+static inline rtl::OUString getBuildId()
+{
+ rtl::OUString aPathVal(UNISTRING("${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}"));
+ rtl::Bootstrap::expandMacros(aPathVal);
+ return aPathVal;
+}
+
+//------------------------------------------------------------------------------
+static inline rtl::OUString getBaseInstallation()
+{
+ rtl::OUString aPathVal(UNISTRING("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap") ":BaseInstallation}"));
+ rtl::Bootstrap::expandMacros(aPathVal);
+ return aPathVal;
+}
+
+//------------------------------------------------------------------------------
+
+inline bool isObsoleteUpdateInfo(const rtl::OUString& rBuildId)
+{
+ return sal_True != rBuildId.equals(getBuildId()) && rBuildId.getLength() > 0;
+}
+
+
+//------------------------------------------------------------------------------
+
+rtl::OUString getImageFromFileName(const rtl::OUString& aFile)
+{
+#ifndef WNT
+ rtl::OUString aUnpackPath;
+ if( osl_getExecutableFile(&aUnpackPath.pData) == osl_Process_E_None )
+ {
+ sal_uInt32 lastIndex = aUnpackPath.lastIndexOf('/');
+ if ( lastIndex > 0 )
+ {
+ aUnpackPath = aUnpackPath.copy( 0, lastIndex+1 );
+ aUnpackPath += UNISTRING( "unpack_update" );
+ }
+
+ oslFileHandle hOut = NULL;
+ oslProcess hProcess = NULL;
+
+ rtl::OUString aSystemPath;
+ osl::File::getSystemPathFromFileURL(aFile, aSystemPath);
+
+ oslProcessError rc = osl_executeProcess_WithRedirectedIO(
+ aUnpackPath.pData, // [in] Image name
+ &aSystemPath.pData, 1, // [in] Arguments
+ osl_Process_WAIT || osl_Process_NORMAL, // [in] Options
+ NULL, // [in] Security
+ NULL, // [in] Working directory
+ NULL, 0, // [in] Environment variables
+ &hProcess, // [out] Process handle
+ NULL, &hOut, NULL // [out] File handles for redirected I/O
+ );
+
+ if( osl_Process_E_None == rc )
+ {
+ oslProcessInfo aInfo;
+ aInfo.Size = sizeof(oslProcessInfo);
+
+ if( osl_Process_E_None == osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &aInfo) )
+ {
+ if( 0 == aInfo.Code )
+ {
+ sal_Char szBuffer[4096];
+ sal_uInt64 nBytesRead = 0;
+ const sal_uInt64 nBytesToRead = sizeof(szBuffer) - 1;
+
+ rtl::OUString aImageName;
+ while( osl_File_E_None == osl_readFile(hOut, szBuffer, nBytesToRead, &nBytesRead) )
+ {
+ sal_Char *pc = szBuffer + nBytesRead;
+ do
+ {
+ *pc = '\0'; --pc;
+ }
+ while( ('\n' == *pc) || ('\r' == *pc) );
+
+ aImageName += rtl::OUString(szBuffer, pc - szBuffer + 1, osl_getThreadTextEncoding());
+
+ if( nBytesRead < nBytesToRead )
+ break;
+ }
+
+ if( osl::FileBase::E_None == osl::FileBase::getFileURLFromSystemPath(aImageName, aImageName) )
+ return aImageName;
+ }
+ }
+
+ osl_closeFile(hOut);
+ osl_freeProcessHandle(hProcess);
+ }
+ }
+#endif
+
+ return aFile;
+}
+
+
+//------------------------------------------------------------------------------
+
+static uno::Reference< beans::XPropertySet > createMenuBarUI(
+ const uno::Reference< uno::XComponentContext >& xContext,
+ const uno::Reference< task::XJob >& xJob)
+{
+ if( !xContext.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheckJob: empty component context" ), uno::Reference< uno::XInterface > () );
+
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheckJob: unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () );
+
+ uno::Reference< beans::XPropertySet > xMenuBarUI =
+ uno::Reference< beans::XPropertySet > (
+ xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.setup.UpdateCheckUI" ), xContext ),
+ uno::UNO_QUERY_THROW);
+
+ xMenuBarUI->setPropertyValue( PROPERTY_CLICK_HDL, uno::makeAny( xJob ) );
+
+ return xMenuBarUI;
+}
+
+//------------------------------------------------------------------------------
+
+
+
+typedef sal_Bool (* OnlineCheckFunc) ();
+
+class UpdateCheckThread : public WorkerThread
+{
+
+public:
+ UpdateCheckThread( osl::Condition& rCondition,
+ const uno::Reference<uno::XComponentContext>& xContext );
+
+ virtual void SAL_CALL join();
+ virtual void SAL_CALL terminate();
+ virtual void SAL_CALL cancel();
+
+protected:
+ virtual ~UpdateCheckThread();
+
+ virtual void SAL_CALL run();
+ virtual void SAL_CALL onTerminated();
+
+ /* Wrapper around checkForUpdates */
+ bool runCheck( bool & rbExtensionsChecked );
+
+private:
+
+ /* Used to avoid dialup login windows (on platforms we know how to double this) */
+ inline bool hasInternetConnection() const
+ {
+ if(m_pHasInternetConnection != NULL )
+ return (sal_True == m_pHasInternetConnection());
+ return true;
+ }
+
+ /* Creates a new instance of UpdateInformationProvider and returns this instance */
+ inline uno::Reference<deployment::XUpdateInformationProvider> createProvider()
+ {
+ osl::MutexGuard aGuard(m_aMutex);
+ m_xProvider = deployment::UpdateInformationProvider::create(m_xContext);
+ return m_xProvider;
+ };
+
+ /* Returns the remembered instance of UpdateInformationProvider if any */
+ inline uno::Reference<deployment::XUpdateInformationProvider> getProvider()
+ { osl::MutexGuard aGuard(m_aMutex); return m_xProvider; };
+
+ /* Releases the remembered instance of UpdateInformationProvider if any */
+ inline void clearProvider()
+ { osl::MutexGuard aGuard(m_aMutex); m_xProvider.clear(); };
+
+ osl::Mutex m_aMutex;
+ osl::Module m_aModule;
+
+protected:
+ osl::Condition& m_aCondition;
+
+private:
+
+// const
+ OnlineCheckFunc m_pHasInternetConnection;
+
+ const uno::Reference<uno::XComponentContext> m_xContext;
+ uno::Reference<deployment::XUpdateInformationProvider> m_xProvider;
+};
+
+
+class ManualUpdateCheckThread : public UpdateCheckThread
+{
+public:
+ ManualUpdateCheckThread( osl::Condition& rCondition, const uno::Reference<uno::XComponentContext>& xContext ) :
+ UpdateCheckThread(rCondition, xContext) {};
+
+ virtual void SAL_CALL run();
+};
+
+
+class MenuBarButtonJob : public ::cppu::WeakImplHelper1< task::XJob >
+{
+public:
+ MenuBarButtonJob(const rtl::Reference< UpdateCheck >& rUpdateCheck);
+
+ // XJob
+ virtual uno::Any SAL_CALL execute(const uno::Sequence<beans::NamedValue>&)
+ throw (lang::IllegalArgumentException, uno::Exception);
+
+private:
+ rtl::Reference< UpdateCheck > m_aUpdateCheck;
+};
+
+class DownloadThread : public WorkerThread
+{
+public:
+ DownloadThread(
+ osl::Condition& rCondition,
+ const uno::Reference<uno::XComponentContext>& xContext,
+ const rtl::Reference< DownloadInteractionHandler >& rHandler,
+ const rtl::OUString& rURL );
+
+ virtual void SAL_CALL run();
+ virtual void SAL_CALL cancel();
+ virtual void SAL_CALL suspend();
+ virtual void SAL_CALL onTerminated();
+
+protected:
+ ~DownloadThread();
+
+private:
+ osl::Condition& m_aCondition;
+ const uno::Reference<uno::XComponentContext> m_xContext;
+ const rtl::OUString m_aURL;
+ Download m_aDownload;
+};
+
+//------------------------------------------------------------------------------
+class ShutdownThread : public osl::Thread
+{
+public:
+ ShutdownThread( const uno::Reference<uno::XComponentContext>& xContext );
+
+ virtual void SAL_CALL run();
+ virtual void SAL_CALL onTerminated();
+
+protected:
+ ~ShutdownThread();
+
+private:
+ osl::Condition m_aCondition;
+ const uno::Reference<uno::XComponentContext> m_xContext;
+};
+
+//------------------------------------------------------------------------------
+
+UpdateCheckThread::UpdateCheckThread( osl::Condition& rCondition,
+ const uno::Reference<uno::XComponentContext>& xContext ) :
+ m_aCondition(rCondition),
+ m_pHasInternetConnection(NULL),
+ m_xContext(xContext)
+{
+
+#ifdef WNT
+ rtl::OUString aPath;
+ if( osl_getExecutableFile(&aPath.pData) == osl_Process_E_None )
+ {
+ sal_uInt32 lastIndex = aPath.lastIndexOf('/');
+ if ( lastIndex > 0 )
+ {
+ aPath = aPath.copy( 0, lastIndex+1 );
+ aPath += UNISTRING( "onlinecheck" );
+ }
+
+ if ( m_aModule.load(aPath) )
+ {
+ m_pHasInternetConnection =
+ reinterpret_cast < OnlineCheckFunc > (
+ m_aModule.getFunctionSymbol( UNISTRING("hasInternetConnection")));
+ }
+ }
+#endif
+
+ createSuspended();
+
+ // actually run the thread
+ resume();
+}
+
+//------------------------------------------------------------------------------
+
+UpdateCheckThread::~UpdateCheckThread()
+{
+}
+
+//------------------------------------------------------------------------------
+
+
+void SAL_CALL
+UpdateCheckThread::terminate()
+{
+ // Cancel potentially hanging http request ..
+ cancel();
+ // .. before terminating
+ osl::Thread::terminate();
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL
+UpdateCheckThread::join()
+{
+ uno::Reference< deployment::XUpdateInformationProvider > xProvider(getProvider());
+
+ // do not join during an update check until #i73893# is fixed
+ if( ! xProvider.is() )
+ {
+ osl::Thread::join();
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL
+UpdateCheckThread::cancel()
+{
+ uno::Reference< deployment::XUpdateInformationProvider > xProvider(getProvider());
+
+ if( xProvider.is() )
+ xProvider->cancel();
+}
+
+//------------------------------------------------------------------------------
+
+bool
+UpdateCheckThread::runCheck( bool & rbExtensionsChecked )
+{
+ bool ret = false;
+ UpdateState eUIState = UPDATESTATE_NO_UPDATE_AVAIL;
+
+ UpdateInfo aInfo;
+ rtl::Reference< UpdateCheck > aController(UpdateCheck::get());
+
+ if( checkForUpdates(aInfo, m_xContext, aController->getInteractionHandler(), createProvider()) )
+ {
+ aController->setUpdateInfo(aInfo);
+ eUIState = aController->getUIState(aInfo);
+ ret = true;
+ }
+ else
+ aController->setCheckFailedState();
+
+ // We will only look for extension updates, when there is no 'check for office updates' dialog open
+ // and when there was no office update found
+ if ( ( eUIState != UPDATESTATE_UPDATE_AVAIL ) &&
+ ( eUIState != UPDATESTATE_UPDATE_NO_DOWNLOAD ) &&
+ !aController->isDialogShowing() &&
+ !rbExtensionsChecked )
+ {
+ bool bHasExtensionUpdates = checkForExtensionUpdates( m_xContext );
+ aController->setHasExtensionUpdates( bHasExtensionUpdates );
+ if ( bHasExtensionUpdates )
+ aController->setUIState( UPDATESTATE_EXT_UPD_AVAIL );
+ rbExtensionsChecked = true;
+ }
+
+ // joining with this thread is safe again
+ clearProvider();
+ return ret;
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL
+UpdateCheckThread::onTerminated()
+{
+ delete this;
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL
+UpdateCheckThread::run()
+{
+ bool bExtensionsChecked = false;
+ TimeValue systime;
+ TimeValue nExtCheckTime;
+ osl_getSystemTime( &nExtCheckTime );
+
+ osl::Condition::Result aResult = osl::Condition::result_timeout;
+ TimeValue tv = { 10, 0 };
+
+ // Initial wait to avoid doing further time consuming tasks during start-up
+ aResult = m_aCondition.wait(&tv);
+
+ try {
+
+ while( sal_True == schedule() )
+ {
+ /* Use cases:
+ * a) manual check requested from auto check thread - "last check" should not be checked (one time)
+ * a1) manual check was requested in the middle of a running auto check,
+ * condition is set
+ * a2) manual check was requested while waiting for a retry,
+ * condition is set
+ * a3) manual check was requested while waiting for time to next
+ * scheduled check elapsing, condition is set
+ * a4) manual check was requested during initial wait, condition is set
+ * b) check interval got changed, condition may be set - same sub-cases as a),
+ * but "last check" should be honored
+ * c) normal auto check mode, condition not set - "last check" should be honored
+ */
+
+ // Accessing const members without synchronization
+ rtl::Reference< UpdateCheck > aController(UpdateCheck::get());
+ rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext, *aController);
+
+ // FIXME: remember last & offset ?
+ sal_Int64 last = rModel->getLastChecked();
+ sal_Int64 offset = rModel->getCheckInterval();
+
+ rModel.clear();
+
+ // last == 0 means check immediately
+ bool checkNow = ! (last > 0);
+
+ // Reset the condition to avoid busy loops
+ if( osl::Condition::result_ok == aResult )
+ {
+ m_aCondition.reset();
+ aResult = osl::Condition::result_timeout;
+ checkNow = aController->isDialogShowing();
+ }
+
+ if( ! checkNow )
+ {
+ osl_getSystemTime(&systime);
+
+ // Go back to sleep until time has elapsed
+ sal_Int64 next = last + offset;
+ if( last + offset > systime.Seconds )
+ {
+ // This can not be > 32 Bit for now ..
+ tv.Seconds = static_cast< sal_Int32 > (next - systime.Seconds);
+ aResult = m_aCondition.wait(&tv);
+ continue;
+ }
+ }
+
+ static sal_uInt8 n = 0;
+
+ if( ! hasInternetConnection() || ! runCheck( bExtensionsChecked ) )
+ {
+ // the extension update check should be independent from the office update check
+ //
+ osl_getSystemTime( &systime );
+ if ( nExtCheckTime.Seconds + offset < systime.Seconds )
+ bExtensionsChecked = false;
+
+ // Increase next by 15, 60, .. minutes
+ static const sal_Int32 nRetryInterval[] = { 900, 3600, 14400, 86400 };
+
+ if( n < sizeof(nRetryInterval) / sizeof(sal_Int32) )
+ ++n;
+
+ tv.Seconds = nRetryInterval[n-1];
+ aResult = m_aCondition.wait(&tv);
+ }
+ else // reset retry counter
+ {
+ n = 0;
+ bExtensionsChecked = false;
+ }
+ }
+ }
+
+ catch(const uno::Exception& e) {
+ // Silently catch all errors
+ OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL
+ManualUpdateCheckThread::run()
+{
+ bool bExtensionsChecked = false;
+
+ try {
+ runCheck( bExtensionsChecked );
+ m_aCondition.reset();
+ }
+ catch(const uno::Exception& e) {
+ // Silently catch all errors
+ OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
+ }
+}
+
+//------------------------------------------------------------------------------
+
+MenuBarButtonJob::MenuBarButtonJob(const rtl::Reference< UpdateCheck >& rUpdateCheck) :
+ m_aUpdateCheck(rUpdateCheck)
+{
+};
+
+//------------------------------------------------------------------------------
+
+uno::Any SAL_CALL
+MenuBarButtonJob::execute(const uno::Sequence<beans::NamedValue>& )
+ throw (lang::IllegalArgumentException, uno::Exception)
+{
+ if ( m_aUpdateCheck->shouldShowExtUpdDlg() )
+ m_aUpdateCheck->showExtensionDialog();
+ else
+ m_aUpdateCheck->showDialog();
+
+ return uno::Any();
+}
+
+//------------------------------------------------------------------------------
+
+DownloadThread::DownloadThread(osl::Condition& rCondition,
+ const uno::Reference<uno::XComponentContext>& xContext,
+ const rtl::Reference< DownloadInteractionHandler >& rHandler,
+ const rtl::OUString& rURL) :
+ m_aCondition(rCondition),
+ m_xContext(xContext),
+ m_aURL(rURL),
+ m_aDownload(xContext, rHandler)
+{
+ createSuspended();
+}
+
+//------------------------------------------------------------------------------
+
+DownloadThread::~DownloadThread()
+{
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL
+DownloadThread::run()
+{
+#ifdef WNT
+ CoUninitialize();
+ CoInitialize( NULL );
+#endif
+
+ while( schedule() )
+ {
+ rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
+
+ rtl::OUString aLocalFile = rModel->getLocalFileName();
+ rtl::OUString aDownloadDest = rModel->getDownloadDestination();
+
+ // release config class for now
+ rModel.clear();
+
+ static sal_uInt8 n = 0;
+ if( ! m_aDownload.start(m_aURL, aLocalFile, aDownloadDest ) )
+ {
+ // retry every 15s unless the dialog is not visible
+ TimeValue tv;
+ tv.Seconds = 15;
+
+ if( ! UpdateCheck::get()->isDialogShowing() )
+ {
+ // Increase next by 1, 5, 15, 60, .. minutes
+ static const sal_Int16 nRetryInterval[] = { 60, 300, 900, 3600 };
+
+ if( n < sizeof(nRetryInterval) / sizeof(sal_Int16) )
+ ++n;
+
+ tv.Seconds = nRetryInterval[n-1];
+ }
+ m_aCondition.wait(&tv);
+ }
+ else
+ {
+ // reset wait period after successful download
+ n=0;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL DownloadThread::cancel()
+{
+ m_aDownload.stop();
+ resume();
+
+ rtl::Reference< UpdateCheck > aController(UpdateCheck::get());
+ aController->cancelDownload();
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL DownloadThread::suspend()
+{
+ osl::Thread::suspend();
+ m_aDownload.stop();
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL DownloadThread::onTerminated()
+{
+ delete this;
+}
+
+//------------------------------------------------------------------------------
+ShutdownThread::ShutdownThread( const uno::Reference<uno::XComponentContext>& xContext) :
+ m_xContext( xContext )
+{
+ create();
+}
+
+//------------------------------------------------------------------------------
+ShutdownThread::~ShutdownThread()
+{
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL
+ShutdownThread::run()
+{
+ TimeValue tv = { 0, 250 };
+
+ m_aCondition.wait(&tv);
+
+ // Tell QuickStarter not to veto ..
+ uno::Reference< beans::XFastPropertySet > xQuickStarter(
+ UpdateCheck::createService(UNISTRING("com.sun.star.office.Quickstart"), m_xContext),
+ uno::UNO_QUERY
+ );
+
+ if (xQuickStarter.is())
+ xQuickStarter->setFastPropertyValue(0, uno::makeAny(false));
+
+ // Shutdown the office
+ uno::Reference< frame::XDesktop > xDesktop(
+ UpdateCheck::createService(UNISTRING("com.sun.star.frame.Desktop"), m_xContext),
+ uno::UNO_QUERY);
+
+ if( xDesktop.is() )
+ xDesktop->terminate();
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL ShutdownThread::onTerminated()
+{
+ delete this;
+}
+
+//------------------------------------------------------------------------------
+
+} // anonymous namespace
+
+
+//------------------------------------------------------------------------------
+
+
+void
+UpdateCheck::initialize(const uno::Sequence< beans::NamedValue >& rValues,
+ const uno::Reference<uno::XComponentContext>& xContext)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if( NOT_INITIALIZED == m_eState )
+ {
+ NamedValueByNameAccess aNameAccess(rValues);
+ UpdateCheckROModel aModel( aNameAccess );
+ m_xContext = xContext;
+
+ rtl::OUString aUpdateEntryVersion = aModel.getUpdateEntryVersion();
+
+ aModel.getUpdateEntry(m_aUpdateInfo);
+
+ bool obsoleteUpdateInfo = isObsoleteUpdateInfo(aUpdateEntryVersion);
+
+ m_bHasExtensionUpdate = checkForPendingUpdates( xContext );
+ m_bShowExtUpdDlg = false;
+
+ rtl::OUString aLocalFileName = aModel.getLocalFileName();
+
+ if( aLocalFileName.getLength() > 0 )
+ {
+ bool downloadPaused = aModel.isDownloadPaused();
+
+ enableDownload(true, downloadPaused);
+ setUIState(downloadPaused ? UPDATESTATE_DOWNLOAD_PAUSED : UPDATESTATE_DOWNLOADING);
+
+ // Try to get the number of bytes already on disk
+ osl::DirectoryItem aDirectoryItem;
+ if( osl::DirectoryItem::E_None == osl::DirectoryItem::get(aLocalFileName, aDirectoryItem) )
+ {
+ osl::FileStatus aFileStatus(FileStatusMask_FileSize);
+ if( osl::DirectoryItem::E_None == aDirectoryItem.getFileStatus(aFileStatus) )
+ {
+ // Calculate initial percent value.
+ if( aModel.getDownloadSize() > 0 )
+ {
+ sal_Int32 nPercent = (sal_Int32) (100 * aFileStatus.getFileSize() / aModel.getDownloadSize());
+ getUpdateHandler()->setProgress(nPercent);
+ }
+ }
+ }
+ }
+ else
+ {
+ // We do this intentionally only if no download is in progress ..
+ if( obsoleteUpdateInfo )
+ {
+ // Bring-up release note for position 5 ..
+ const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 5));
+ if( aURL.getLength() > 0 )
+ showReleaseNote(aURL);
+
+ // Data is outdated, probably due to installed update
+ rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( xContext, *this );
+ aConfig->clearUpdateFound();
+
+ m_aUpdateInfo = UpdateInfo();
+ }
+ else
+ {
+ enableAutoCheck(aModel.isAutoCheckEnabled());
+ setUIState(getUIState(m_aUpdateInfo));
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::cancel()
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ WorkerThread *pThread = m_pThread;
+ UpdateState eUIState = getUIState(m_aUpdateInfo);
+
+ aGuard.clear();
+
+ if( NULL != pThread )
+ pThread->cancel();
+
+ setUIState(eUIState);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::download()
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+ UpdateInfo aInfo(m_aUpdateInfo);
+ State eState = m_eState;
+ aGuard.clear();
+
+ if( aInfo.Sources[0].IsDirect )
+ {
+ // Ignore second click of a double click
+ if( DOWNLOADING != eState )
+ {
+ shutdownThread(true);
+
+ osl::ClearableMutexGuard aGuard2(m_aMutex);
+ enableDownload(true);
+ aGuard2.clear();
+ setUIState(UPDATESTATE_DOWNLOADING);
+ }
+ }
+ else
+ {
+ showReleaseNote(aInfo.Sources[0].URL); // Display in browser
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::install()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ const uno::Reference< c3s::XSystemShellExecute > xShellExecute(
+ createService( UNISTRING( "com.sun.star.system.SystemShellExecute" ), m_xContext ),
+ uno::UNO_QUERY );
+
+ try {
+ // Construct install command ??
+
+ // Store release note for position 3 and 4
+ rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 3));
+ storeReleaseNote(1, aURL);
+
+ aURL = getReleaseNote(m_aUpdateInfo, 4);
+ storeReleaseNote(2, aURL);
+
+ if( xShellExecute.is() )
+ {
+ rtl::OUString aInstallImage(m_aImageName);
+ osl::FileBase::getSystemPathFromFileURL(aInstallImage, aInstallImage);
+
+ rtl::OUString aParameter;
+ sal_Int32 nFlags = c3s::SystemShellExecuteFlags::DEFAULTS;
+#if ( defined LINUX || defined SOLARIS )
+ nFlags = 42;
+ aParameter = getBaseInstallation();
+ if( aParameter.getLength() > 0 )
+ osl::FileBase::getSystemPathFromFileURL(aParameter, aParameter);
+
+ aParameter += UNISTRING(" &");
+#endif
+ xShellExecute->execute(aInstallImage, aParameter, nFlags);
+ ShutdownThread *pShutdownThread = new ShutdownThread( m_xContext );
+ (void) pShutdownThread;
+ }
+ } catch(uno::Exception&) {
+ m_aUpdateHandler->setErrorMessage( m_aUpdateHandler->getDefaultInstErrMsg() );
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::pause()
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ if( NULL != m_pThread )
+ m_pThread->suspend();
+
+ rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
+ aGuard.clear();
+
+ rModel->storeDownloadPaused(true);
+ setUIState(UPDATESTATE_DOWNLOAD_PAUSED);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::resume()
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ if( NULL != m_pThread )
+ m_pThread->resume();
+
+ rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
+ aGuard.clear();
+
+ rModel->storeDownloadPaused(false);
+ setUIState(UPDATESTATE_DOWNLOADING);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::closeAfterFailure()
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ if ( ( m_eState == DISABLED ) || ( m_eState == CHECK_SCHEDULED ) )
+ {
+ const UpdateState eUIState = getUIState( m_aUpdateInfo );
+ aGuard.clear();
+ setUIState( eUIState, true );
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::shutdownThread(bool join)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ // copy thread object pointer to stack
+ osl::Thread *pThread = m_pThread;
+ m_pThread = NULL;
+ aGuard.clear();
+
+ if( NULL != pThread )
+ {
+ pThread->terminate();
+ if( join )
+ {
+ m_aCondition.set();
+ pThread->join();
+ m_aCondition.reset();
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::enableAutoCheck(bool enable)
+{
+ if( enable )
+ m_pThread = new UpdateCheckThread(m_aCondition, m_xContext);
+
+ m_eState = enable ? CHECK_SCHEDULED : DISABLED;
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::enableDownload(bool enable, bool paused)
+{
+ OSL_ASSERT(NULL == m_pThread);
+
+ State eState = DISABLED;
+ if( enable )
+ {
+ m_pThread = new DownloadThread(m_aCondition, m_xContext, this, m_aUpdateInfo.Sources[0].URL );
+ if( !paused )
+ {
+ eState = DOWNLOADING;
+ m_pThread->resume();
+ }
+ else
+ eState = DOWNLOAD_PAUSED;
+
+ m_eState = eState;
+ }
+ else {
+ enableAutoCheck(UpdateCheckConfig::get(m_xContext)->isAutoCheckEnabled());
+ }
+
+}
+
+//------------------------------------------------------------------------------
+
+bool
+UpdateCheck::downloadTargetExists(const rtl::OUString& rFileName)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler());
+ UpdateState eUIState = UPDATESTATE_DOWNLOADING;
+
+ bool cont = false;
+
+ if( aUpdateHandler->isVisible() )
+ {
+ cont = aUpdateHandler->showOverwriteWarning();
+ if( cont )
+ {
+ if( osl_File_E_None != osl_removeFile(rFileName.pData) )
+ {
+ // FIXME: error message
+ cont = false;
+ }
+ }
+ else
+ eUIState = getUIState(m_aUpdateInfo);
+ }
+ else
+ {
+ m_aImageName = getImageFromFileName(rFileName);
+ eUIState = UPDATESTATE_DOWNLOAD_AVAIL;
+ }
+
+ if( !cont )
+ {
+ shutdownThread(false);
+ enableDownload(false);
+
+ aGuard.clear();
+ setUIState(eUIState);
+ }
+
+ return cont;
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::downloadStalled(const rtl::OUString& rErrorMessage)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+ rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler());
+ aGuard.clear();
+
+ aUpdateHandler->setErrorMessage(rErrorMessage);
+ setUIState(UPDATESTATE_ERROR_DOWNLOADING);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::downloadProgressAt(sal_Int8 nPercent)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+ rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler());
+ aGuard.clear();
+
+ aUpdateHandler->setProgress(nPercent);
+ setUIState(UPDATESTATE_DOWNLOADING);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::downloadStarted(const rtl::OUString& rLocalFileName, sal_Int64 nFileSize)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ rtl::Reference< UpdateCheckConfig > aModel(UpdateCheckConfig::get(m_xContext));
+ aModel->storeLocalFileName(rLocalFileName, nFileSize);
+
+ // Bring-up release note for position 1 ..
+ const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 1, aModel->isAutoDownloadEnabled()));
+ if( aURL.getLength() > 0 )
+ showReleaseNote(aURL);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::downloadFinished(const rtl::OUString& rLocalFileName)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ // no more retries
+ m_pThread->terminate();
+
+ rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
+ rModel->clearLocalFileName();
+
+ m_aImageName = getImageFromFileName(rLocalFileName);
+ UpdateInfo aUpdateInfo(m_aUpdateInfo);
+
+ aGuard.clear();
+ setUIState(UPDATESTATE_DOWNLOAD_AVAIL);
+
+ // Bring-up release note for position 2 ..
+ const rtl::OUString aURL(getReleaseNote(aUpdateInfo, 2, rModel->isAutoDownloadEnabled()));
+ if( aURL.getLength() > 0 )
+ showReleaseNote(aURL);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::cancelDownload()
+{
+ shutdownThread(true);
+
+ osl::MutexGuard aGuard(m_aMutex);
+ enableDownload(false);
+
+ rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
+
+ rtl::OUString aLocalFile(rModel->getLocalFileName());
+ rModel->clearLocalFileName();
+ rModel->storeDownloadPaused(false);
+
+ if( isObsoleteUpdateInfo(rModel->getUpdateEntryVersion()) )
+ {
+ rModel->clearUpdateFound(); // This wasn't done during init yet ..
+ m_aUpdateInfo = UpdateInfo();
+ }
+
+ /*oslFileError rc =*/ osl_removeFile(aLocalFile.pData);
+ // FIXME: error handling ..
+
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::showDialog(bool forceCheck)
+{
+ osl::ResettableMutexGuard aGuard(m_aMutex);
+
+ bool update_found = m_aUpdateInfo.BuildId.getLength() > 0;
+ bool bSetUIState = ! m_aUpdateHandler.is();
+
+ UpdateState eDialogState = UPDATESTATES_COUNT;
+
+ switch( m_eState )
+ {
+ case DISABLED:
+ case CHECK_SCHEDULED:
+ if( forceCheck || ! update_found ) // Run check when forced or if we did not find an update yet
+ {
+ eDialogState = UPDATESTATE_CHECKING;
+ bSetUIState = true;
+ }
+ else if(m_aUpdateInfo.Sources[0].IsDirect)
+ eDialogState = UPDATESTATE_UPDATE_AVAIL;
+ else
+ eDialogState = UPDATESTATE_UPDATE_NO_DOWNLOAD;
+ break;
+
+ case DOWNLOADING:
+ eDialogState = UPDATESTATE_DOWNLOADING;
+ break;
+
+ case DOWNLOAD_PAUSED:
+ eDialogState = UPDATESTATE_DOWNLOAD_PAUSED;
+ break;
+
+ case NOT_INITIALIZED:
+ OSL_ASSERT( false );
+ break;
+ }
+
+ if( bSetUIState )
+ {
+ aGuard.clear();
+ setUIState(eDialogState, true); // suppress bubble as Dialog will be visible soon
+ aGuard.reset();
+ }
+
+ getUpdateHandler()->setVisible(true);
+
+ // Run check in separate thread ..
+ if( UPDATESTATE_CHECKING == eDialogState )
+ {
+ if( DISABLED == m_eState )
+ {
+ // destructs itself when done, not cancellable for now ..
+ new ManualUpdateCheckThread(m_aCondition, m_xContext);
+ }
+
+ m_aCondition.set();
+ }
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::setUpdateInfo(const UpdateInfo& aInfo)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ bool bSuppressBubble = (sal_True == aInfo.BuildId.equals(m_aUpdateInfo.BuildId));
+ m_aUpdateInfo = aInfo;
+
+ OSL_ASSERT(DISABLED == m_eState || CHECK_SCHEDULED == m_eState);
+
+ // Ignore leading non direct download if we get direct ones
+ std::vector< DownloadSource >::iterator iter = m_aUpdateInfo.Sources.begin();
+ while( iter != m_aUpdateInfo.Sources.end() )
+ {
+ if( iter->IsDirect )
+ break;
+
+ ++iter;
+ }
+
+ if( (iter != m_aUpdateInfo.Sources.begin()) &&
+ (iter != m_aUpdateInfo.Sources.end()) &&
+ iter->IsDirect )
+ {
+ m_aUpdateInfo.Sources.erase(m_aUpdateInfo.Sources.begin(), --iter);
+ }
+
+ rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext, *this);
+ OSL_ASSERT( rModel.is() );
+
+ // Decide whether to use alternate release note pos ..
+ bool autoDownloadEnabled = rModel->isAutoDownloadEnabled();
+
+ std::vector< ReleaseNote >::iterator iter2 = m_aUpdateInfo.ReleaseNotes.begin();
+ while( iter2 != m_aUpdateInfo.ReleaseNotes.end() )
+ {
+ if( ((1 == iter2->Pos) || (2 == iter2->Pos)) && autoDownloadEnabled && (iter2->URL2.getLength() > 0))
+ {
+ iter2->URL = iter2->URL2;
+ iter2->URL2 = rtl::OUString();
+ iter2->Pos = iter2->Pos2;
+ iter2->Pos2 = 0;
+ }
+
+ ++iter2;
+ }
+
+ // do not move below store/clear ..
+ rModel->updateLastChecked();
+
+ UpdateState eUIState;
+ if( m_aUpdateInfo.Sources.size() > 0 )
+ {
+ rModel->storeUpdateFound(aInfo, getBuildId());
+
+ if( m_aUpdateInfo.Sources[0].IsDirect )
+ {
+ eUIState = UPDATESTATE_UPDATE_AVAIL;
+
+ if( rModel->isAutoDownloadEnabled() )
+ {
+ shutdownThread(false);
+ eUIState = UPDATESTATE_DOWNLOADING;
+ enableDownload(true);
+ }
+ }
+ else
+ eUIState = UPDATESTATE_UPDATE_NO_DOWNLOAD;
+ }
+ else
+ {
+ eUIState = UPDATESTATE_NO_UPDATE_AVAIL;
+ rModel->clearUpdateFound();
+ }
+
+ aGuard.clear();
+ setUIState(eUIState, bSuppressBubble);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::setCheckFailedState()
+{
+ setUIState(UPDATESTATE_ERROR_CHECKING);
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheck::handleMenuBarUI( rtl::Reference< UpdateHandler > rUpdateHandler,
+ UpdateState& eState,
+ bool suppressBubble )
+{
+ uno::Reference<beans::XPropertySet> xMenuBarUI( m_xMenuBarUI );
+
+ if ( ( UPDATESTATE_NO_UPDATE_AVAIL == eState ) && m_bHasExtensionUpdate )
+ eState = UPDATESTATE_EXT_UPD_AVAIL;
+
+ if ( UPDATESTATE_EXT_UPD_AVAIL == eState )
+ m_bShowExtUpdDlg = true;
+ else
+ m_bShowExtUpdDlg = false;
+
+ if( xMenuBarUI.is() )
+ {
+ if( UPDATESTATE_NO_UPDATE_AVAIL == eState )
+ {
+ xMenuBarUI->setPropertyValue( PROPERTY_SHOW_MENUICON, uno::makeAny(sal_False) );
+ }
+ else
+ {
+ xMenuBarUI->setPropertyValue( PROPERTY_TITLE, uno::makeAny(rUpdateHandler->getBubbleTitle(eState)) );
+ xMenuBarUI->setPropertyValue( PROPERTY_TEXT, uno::makeAny(rUpdateHandler->getBubbleText(eState)) );
+
+ if( ! suppressBubble && ( ! rUpdateHandler->isVisible() || rUpdateHandler->isMinimized() ) )
+ xMenuBarUI->setPropertyValue( PROPERTY_SHOW_BUBBLE, uno::makeAny( sal_True ) );
+
+ if( UPDATESTATE_CHECKING != eState )
+ xMenuBarUI->setPropertyValue( PROPERTY_SHOW_MENUICON, uno::makeAny(sal_True) );
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheck::setUIState(UpdateState eState, bool suppressBubble)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ if( ! m_xMenuBarUI.is() &&
+ (DISABLED != m_eState) &&
+ ( m_bHasExtensionUpdate || (UPDATESTATE_NO_UPDATE_AVAIL != eState)) &&
+ (UPDATESTATE_CHECKING != eState) &&
+ (UPDATESTATE_ERROR_CHECKING != eState)
+ )
+ {
+ m_xMenuBarUI = createMenuBarUI(m_xContext, new MenuBarButtonJob(this));
+ }
+
+ // Show bubble only when the status has changed
+ if ( eState == m_eUpdateState )
+ suppressBubble = true;
+ else
+ m_eUpdateState = eState;
+
+ rtl::Reference<UpdateHandler> aUpdateHandler(getUpdateHandler());
+ OSL_ASSERT( aUpdateHandler.is() );
+
+ UpdateInfo aUpdateInfo(m_aUpdateInfo);
+ rtl::OUString aImageName(m_aImageName);
+
+ aGuard.clear();
+
+ handleMenuBarUI( aUpdateHandler, eState, suppressBubble );
+
+ if( (UPDATESTATE_UPDATE_AVAIL == eState)
+ || (UPDATESTATE_DOWNLOAD_PAUSED == eState)
+ || (UPDATESTATE_DOWNLOADING == eState) )
+ {
+ uno::Reference< uno::XComponentContext > xContext(m_xContext);
+
+ rtl::OUString aDownloadDestination =
+ UpdateCheckConfig::get(xContext, this)->getDownloadDestination();
+
+ osl_getSystemPathFromFileURL(aDownloadDestination.pData, &aDownloadDestination.pData);
+
+ aUpdateHandler->setDownloadPath(aDownloadDestination);
+ }
+ else if( UPDATESTATE_DOWNLOAD_AVAIL == eState )
+ {
+ aUpdateHandler->setDownloadFile(aImageName);
+ }
+
+ aUpdateHandler->setDescription(aUpdateInfo.Description);
+ aUpdateHandler->setNextVersion(aUpdateInfo.Version);
+ aUpdateHandler->setState(eState);
+}
+
+//------------------------------------------------------------------------------
+
+UpdateState
+UpdateCheck::getUIState(const UpdateInfo& rInfo)
+{
+ UpdateState eUIState = UPDATESTATE_NO_UPDATE_AVAIL;
+
+ if( rInfo.BuildId.getLength() > 0 )
+ {
+ if( rInfo.Sources[0].IsDirect )
+ eUIState = UPDATESTATE_UPDATE_AVAIL;
+ else
+ eUIState = UPDATESTATE_UPDATE_NO_DOWNLOAD;
+ }
+
+ return eUIState;
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::showReleaseNote(const rtl::OUString& rURL) const
+{
+ const uno::Reference< c3s::XSystemShellExecute > xShellExecute(
+ createService( UNISTRING( "com.sun.star.system.SystemShellExecute" ), m_xContext ),
+ uno::UNO_QUERY );
+
+ try {
+
+ if( xShellExecute.is() )
+ xShellExecute->execute(rURL, rtl::OUString(), c3s::SystemShellExecuteFlags::DEFAULTS);
+ } catch(c3s::SystemShellExecuteException&) {
+ }
+}
+
+//------------------------------------------------------------------------------
+
+bool
+UpdateCheck::storeReleaseNote(sal_Int8 nNum, const rtl::OUString &rURL)
+{
+ osl::FileBase::RC rc;
+ rtl::OUString aTargetDir( UpdateCheckConfig::getAllUsersDirectory() + UNISTRING( "/sun" ) );
+
+ rc = osl::Directory::createPath( aTargetDir );
+
+ rtl::OUString aFileName = UNISTRING("releasenote") +
+ rtl::OUString::valueOf( (sal_Int32) nNum ) +
+ UNISTRING(".url");
+
+ rtl::OUString aFilePath;
+ rc = osl::FileBase::getAbsoluteFileURL( aTargetDir, aFileName, aFilePath );
+ if ( rc != osl::FileBase::E_None ) return false;
+
+ rc = osl::File::remove( aFilePath );
+
+ // don't store empty release notes, but delete old ones
+ if ( rURL.getLength() == 0 )
+ return true;
+
+ osl::File aFile( aFilePath );
+ rc = aFile.open( OpenFlag_Write | OpenFlag_Create );
+
+ if ( rc != osl::FileBase::E_None ) return false;
+
+ rtl::OString aLineBuf("[InternetShortcut]\r\n");
+ sal_uInt64 nWritten = 0;
+
+ rtl::OUString aURL( rURL );
+#ifdef WNT
+ rc = aFile.write( aLineBuf.getStr(), aLineBuf.getLength(), nWritten );
+ if ( rc != osl::FileBase::E_None ) return false;
+ aURL = UNISTRING("URL=") + rURL;
+#endif
+ aLineBuf = rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 );
+ rc = aFile.write( aLineBuf.getStr(), aLineBuf.getLength(), nWritten );
+ if ( rc != osl::FileBase::E_None ) return false;
+
+ aFile.close();
+ return true;
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheck::showExtensionDialog()
+{
+ rtl::OUString sServiceName = UNISTRING("com.sun.star.deployment.ui.PackageManagerDialog");
+ rtl::OUString sArguments = UNISTRING("SHOW_UPDATE_DIALOG");
+ uno::Reference< uno::XInterface > xService;
+
+ if( ! m_xContext.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheck::showExtensionDialog(): empty component context" ), uno::Reference< uno::XInterface > () );
+
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager( m_xContext->getServiceManager() );
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheck::showExtensionDialog(): unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () );
+
+ xService = xServiceManager->createInstanceWithContext( sServiceName, m_xContext );
+ uno::Reference< task::XJobExecutor > xExecuteable( xService, uno::UNO_QUERY );
+ if ( xExecuteable.is() )
+ xExecuteable->trigger( sArguments );
+}
+
+//------------------------------------------------------------------------------
+
+rtl::Reference<UpdateHandler>
+UpdateCheck::getUpdateHandler()
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ if( ! m_aUpdateHandler.is() )
+ m_aUpdateHandler = new UpdateHandler(m_xContext, this);
+
+ return m_aUpdateHandler;
+}
+
+//------------------------------------------------------------------------------
+
+uno::Reference< task::XInteractionHandler >
+UpdateCheck::getInteractionHandler() const
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ uno::Reference< task::XInteractionHandler > xHandler;
+
+ if( m_aUpdateHandler.is() && m_aUpdateHandler->isVisible() )
+ xHandler = m_aUpdateHandler.get();
+
+ return xHandler;
+}
+
+//------------------------------------------------------------------------------
+
+uno::Reference< uno::XInterface >
+UpdateCheck::createService(const rtl::OUString& rServiceName,
+ const uno::Reference<uno::XComponentContext>& xContext)
+{
+ if( !xContext.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheckConfig: empty component context" ),
+ uno::Reference< uno::XInterface >() );
+
+ const uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
+
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheckConfig: unable to obtain service manager from component context" ),
+ uno::Reference< uno::XInterface >() );
+
+ return xServiceManager->createInstanceWithContext(rServiceName, xContext);
+}
+
+//------------------------------------------------------------------------------
+
+bool
+UpdateCheck::isDialogShowing() const
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ return sal_True == m_aUpdateHandler.is() && m_aUpdateHandler->isVisible();
+};
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::autoCheckStatusChanged(bool enabled)
+{
+ osl::ClearableMutexGuard aGuard(m_aMutex);
+
+ if( (CHECK_SCHEDULED == m_eState) && !enabled )
+ shutdownThread(false);
+
+ if( (DISABLED == m_eState) || (CHECK_SCHEDULED == m_eState) )
+ {
+ enableAutoCheck(enabled);
+ UpdateState eState = getUIState(m_aUpdateInfo);
+ aGuard.clear();
+ setUIState(eState);
+ }
+};
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheck::autoCheckIntervalChanged()
+{
+ // just wake-up
+ m_aCondition.set();
+};
+
+//------------------------------------------------------------------------------
+
+oslInterlockedCount SAL_CALL
+UpdateCheck::acquire() SAL_THROW(())
+{
+ return ReferenceObject::acquire();
+}
+
+//------------------------------------------------------------------------------
+
+oslInterlockedCount SAL_CALL
+UpdateCheck::release() SAL_THROW(())
+{
+ return ReferenceObject::release();
+}
diff --git a/extensions/source/update/check/updatecheck.hxx b/extensions/source/update/check/updatecheck.hxx
new file mode 100644
index 000000000000..c3a088897860
--- /dev/null
+++ b/extensions/source/update/check/updatecheck.hxx
@@ -0,0 +1,195 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatecheck.hxx,v $
+ * $Revision: 1.6.70.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+
+#include <osl/conditn.hxx>
+#include <osl/thread.hxx>
+#include <rtl/instance.hxx>
+#include <salhelper/refobj.hxx>
+
+#include "updateinfo.hxx"
+#include "updatecheckconfiglistener.hxx"
+#include "actionlistener.hxx"
+#include "updatehdl.hxx"
+#include "download.hxx"
+
+
+class UpdateCheck;
+class UpdateCheckConfig;
+
+class UpdateCheckInitData {
+
+public:
+ inline rtl::Reference< UpdateCheck > SAL_CALL operator() () const;
+};
+
+class WorkerThread : public osl::Thread
+{
+public:
+ virtual void SAL_CALL cancel() = 0;
+};
+
+class UpdateCheck :
+ public UpdateCheckConfigListener,
+ public IActionListener,
+ public DownloadInteractionHandler,
+ public salhelper::ReferenceObject,
+ public rtl::StaticWithInit< rtl::Reference< UpdateCheck >, UpdateCheckInitData >
+{
+ UpdateCheck() : m_eState(NOT_INITIALIZED), m_eUpdateState(UPDATESTATES_COUNT), m_pThread(NULL) {};
+
+public:
+ inline SAL_CALL operator rtl::Reference< UpdateCheckConfigListener > ()
+ { return static_cast< UpdateCheckConfigListener * > (this); }
+
+ void initialize(const com::sun::star::uno::Sequence<com::sun::star::beans::NamedValue>& rValues,
+ const com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext>& xContext);
+
+ /* Returns an instance of the specified service obtained from the specified
+ * component context
+ */
+
+ static com::sun::star::uno::Reference< com::sun::star::uno::XInterface > createService(
+ const rtl::OUString& aServiceName,
+ const com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext>& xContext);
+
+ // Update internal update info member
+ void setUpdateInfo(const UpdateInfo& aInfo);
+
+ /* This method turns on the menubar icon, triggers the bubble window or
+ * updates the dialog text when appropriate
+ */
+ void setUIState(UpdateState eState, bool suppressBubble = false);
+
+ // Returns the UI state that matches rInfo best
+ static UpdateState getUIState(const UpdateInfo& rInfo);
+
+ // Check for updates failed
+ void setCheckFailedState();
+
+ // Executes the update check dialog for manual checks and downloads interaction
+ void showDialog(bool forceCheck = false);
+
+ // Returns true if the update dialog is currently showing
+ bool isDialogShowing() const;
+ bool shouldShowExtUpdDlg() const { return ( m_bShowExtUpdDlg && m_bHasExtensionUpdate ); }
+ void showExtensionDialog();
+ void setHasExtensionUpdates( bool bHasUpdates ) { m_bHasExtensionUpdate = bHasUpdates; }
+ bool hasOfficeUpdate() const { return (m_aUpdateInfo.BuildId.getLength() > 0); }
+
+ // DownloadInteractionHandler
+ virtual bool downloadTargetExists(const rtl::OUString& rFileName);
+ virtual void downloadStalled(const rtl::OUString& rErrorMessage);
+ virtual void downloadProgressAt(sal_Int8 nProcent);
+ virtual void downloadStarted(const rtl::OUString& rLocalFileName, sal_Int64 nFileSize);
+ virtual void downloadFinished(const rtl::OUString& rLocalFileName);
+
+ // Cancels the download action (and resumes checking if enabled)
+ void cancelDownload();
+
+ // Returns the XInteractionHandler of the UpdateHandler instance if present (and visible)
+ com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > getInteractionHandler() const;
+
+ // UpdateCheckConfigListener
+ virtual void autoCheckStatusChanged(bool enabled);
+ virtual void autoCheckIntervalChanged();
+
+ // IActionListener
+ void cancel();
+ void download();
+ void install();
+ void pause();
+ void resume();
+ void closeAfterFailure();
+
+ // rtl::IReference
+ virtual oslInterlockedCount SAL_CALL acquire() SAL_THROW(());
+ virtual oslInterlockedCount SAL_CALL release() SAL_THROW(());
+
+private:
+
+ // Schedules or cancels next automatic check for updates
+ void enableAutoCheck(bool enable);
+
+ // Starts/resumes or stops a download
+ void enableDownload(bool enable, bool paused=false);
+
+ // Shuts down the currently running thread
+ void shutdownThread(bool join);
+
+ // Returns the update handler instance
+ rtl::Reference<UpdateHandler> getUpdateHandler();
+
+ // Open the given URL in a browser
+ void showReleaseNote(const rtl::OUString& rURL) const;
+
+ // stores the release note url on disk to be used by setup app
+ static bool storeReleaseNote(sal_Int8 nNum, const rtl::OUString &rURL);
+
+ /* This method turns on the menubar icon and triggers the bubble window
+ */
+ void handleMenuBarUI( rtl::Reference< UpdateHandler > rUpdateHandler,
+ UpdateState& eState, bool suppressBubble );
+ enum State {
+ NOT_INITIALIZED,
+ DISABLED,
+ CHECK_SCHEDULED,
+ DOWNLOADING,
+ DOWNLOAD_PAUSED
+ };
+
+ State m_eState;
+ UpdateState m_eUpdateState;
+
+ mutable osl::Mutex m_aMutex;
+ WorkerThread *m_pThread;
+ osl::Condition m_aCondition;
+
+ UpdateInfo m_aUpdateInfo;
+ rtl::OUString m_aImageName;
+ bool m_bHasExtensionUpdate;
+ bool m_bShowExtUpdDlg;
+
+ rtl::Reference<UpdateHandler> m_aUpdateHandler;
+ com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> m_xMenuBarUI;
+ com::sun::star::uno::Reference<com::sun::star::uno::XComponentContext> m_xContext;
+
+ friend class UpdateCheckInitData;
+};
+
+inline rtl::Reference< UpdateCheck > SAL_CALL
+UpdateCheckInitData::operator() () const
+{
+ return rtl::Reference< UpdateCheck > (new UpdateCheck());
+}
diff --git a/extensions/source/update/check/updatecheckconfig.cxx b/extensions/source/update/check/updatecheckconfig.cxx
new file mode 100644
index 000000000000..45a7c15ecb2e
--- /dev/null
+++ b/extensions/source/update/check/updatecheckconfig.cxx
@@ -0,0 +1,763 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+
+
+#include "updatecheckconfig.hxx"
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+
+#ifndef _COM_SUN_STAR_CONTAINER_CHANGESEVENT_HPP_
+#include <com/sun/star/beans/XPropertyState.hpp>
+#endif
+
+#include <osl/security.hxx>
+#include <osl/time.h>
+#include <osl/file.hxx>
+
+#ifdef WNT
+#ifdef _MSC_VER
+#pragma warning(push,1) // disable warnings within system headers
+#pragma warning(disable: 4917)
+#endif
+#include <shlobj.h>
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+#endif
+
+namespace container = com::sun::star::container ;
+namespace beans = com::sun::star::beans ;
+namespace lang = com::sun::star::lang ;
+namespace util = com::sun::star::util ;
+namespace uno = com::sun::star::uno ;
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+#define LAST_CHECK "LastCheck"
+#define VERSION_FOUND "UpdateVersionFound"
+#define UPDATE_VERSION "UpdateVersion"
+#define UPDATE_BUILDID "UpdateBuildId"
+#define UPDATE_DESCRIPTION "UpdateDescription"
+#define DOWNLOAD_URL "DownloadURL"
+#define IS_DIRECT_DOWNLOAD "IsDirectDownload"
+#define OLD_VERSION "UpdateFoundFor"
+#define AUTOCHECK_ENABLED "AutoCheckEnabled"
+#define AUTODOWNLOAD_ENABLED "AutoDownloadEnabled"
+#define CHECK_INTERVAL "CheckInterval"
+#define LOCAL_FILE "LocalFile"
+#define DOWNLOAD_SIZE "DownloadSize"
+#define DOWNLOAD_PAUSED "DownloadPaused"
+#define DOWNLOAD_DESTINATION "DownloadDestination"
+#define RELEASE_NOTE "ReleaseNote"
+#define EXTENSION_PREFIX "Extension_"
+
+static const sal_Char * const aUpdateEntryProperties[] = {
+ UPDATE_VERSION,
+ UPDATE_BUILDID,
+ UPDATE_DESCRIPTION,
+ DOWNLOAD_URL,
+ IS_DIRECT_DOWNLOAD,
+ RELEASE_NOTE"1",
+ RELEASE_NOTE"2",
+ RELEASE_NOTE"3",
+ RELEASE_NOTE"4",
+ RELEASE_NOTE"5",
+ OLD_VERSION
+};
+
+static const sal_uInt32 nUpdateEntryProperties = sizeof(aUpdateEntryProperties) / sizeof(sal_Char *);
+
+//------------------------------------------------------------------------------
+
+NamedValueByNameAccess::~NamedValueByNameAccess()
+{
+}
+
+//------------------------------------------------------------------------------
+
+::com::sun::star::uno::Any
+NamedValueByNameAccess::getValue(const sal_Char * pName)
+{
+ const sal_Int32 nLen = m_rValues.getLength();
+ for( sal_Int32 n=0; n < nLen; ++n )
+ {
+ if( m_rValues[n].Name.equalsAscii( pName ) )
+ return m_rValues[n].Value;
+ }
+ return ::com::sun::star::uno::Any();
+}
+
+
+//------------------------------------------------------------------------------
+
+bool
+UpdateCheckROModel::isAutoCheckEnabled() const
+{
+ return sal_True == m_aNameAccess.getValue(AUTOCHECK_ENABLED).get< sal_Bool >();
+}
+
+//------------------------------------------------------------------------------
+
+bool
+UpdateCheckROModel::isDownloadPaused() const
+{
+ return sal_True == m_aNameAccess.getValue(DOWNLOAD_PAUSED).get< sal_Bool >();
+}
+
+//------------------------------------------------------------------------------
+
+rtl::OUString
+UpdateCheckROModel::getStringValue(const sal_Char * pStr) const
+{
+ uno::Any aAny( m_aNameAccess.getValue(pStr) );
+ rtl::OUString aRet;
+
+ aAny >>= aRet;
+
+ return aRet;
+}
+
+//------------------------------------------------------------------------------
+
+rtl::OUString UpdateCheckROModel::getLocalFileName() const
+{
+ return getStringValue(LOCAL_FILE);
+};
+
+//------------------------------------------------------------------------------
+
+sal_Int64 UpdateCheckROModel::getDownloadSize() const
+{
+ uno::Any aAny( m_aNameAccess.getValue(DOWNLOAD_SIZE) );
+ sal_Int64 nRet = -1;
+
+ aAny >>= nRet;
+ return nRet;
+};
+
+//------------------------------------------------------------------------------
+
+rtl::OUString
+UpdateCheckROModel::getUpdateEntryVersion() const
+{
+ return getStringValue(OLD_VERSION);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheckROModel::getUpdateEntry(UpdateInfo& rInfo) const
+{
+ rInfo.BuildId = getStringValue(UPDATE_BUILDID);
+ rInfo.Version = getStringValue(UPDATE_VERSION);
+ rInfo.Description = getStringValue(UPDATE_DESCRIPTION);
+
+ sal_Bool isDirectDownload = sal_False;
+ m_aNameAccess.getValue(IS_DIRECT_DOWNLOAD) >>= isDirectDownload;
+
+ rInfo.Sources.push_back( DownloadSource( isDirectDownload, getStringValue(DOWNLOAD_URL) ) );
+
+ rtl::OString aStr(RELEASE_NOTE);
+ for(sal_Int32 n=1; n < 6; ++n )
+ {
+ rtl::OUString aUStr = getStringValue(aStr + rtl::OString::valueOf(n));
+ if( aUStr.getLength() > 0 )
+ rInfo.ReleaseNotes.push_back(ReleaseNote((sal_Int8) n, aUStr));
+ }
+}
+
+
+//------------------------------------------------------------------------------
+
+rtl::OUString UpdateCheckConfig::getDesktopDirectory()
+{
+ rtl::OUString aRet;
+
+#ifdef WNT
+ WCHAR szPath[MAX_PATH];
+
+ if( ! FAILED( SHGetSpecialFolderPathW( NULL, szPath, CSIDL_DESKTOPDIRECTORY, true ) ) )
+ {
+ aRet = rtl::OUString( reinterpret_cast< sal_Unicode * >(szPath) );
+ osl::FileBase::getFileURLFromSystemPath( aRet, aRet );
+ }
+#else
+ // This should become a desktop specific setting in some system backend ..
+ rtl::OUString aHomeDir;
+ osl::Security().getHomeDir( aHomeDir );
+ aRet = aHomeDir + rtl::OUString::createFromAscii("/Desktop");
+
+ // Set path to home directory when there is no /Desktop directory
+ osl::Directory aDocumentsDir( aRet );
+ if( osl::FileBase::E_None != aDocumentsDir.open() )
+ aRet = aHomeDir;
+#endif
+
+ return aRet;
+}
+
+//------------------------------------------------------------------------------
+
+rtl::OUString UpdateCheckConfig::getAllUsersDirectory()
+{
+ rtl::OUString aRet;
+
+#ifdef WNT
+ WCHAR szPath[MAX_PATH];
+
+ if( ! FAILED( SHGetSpecialFolderPathW( NULL, szPath, CSIDL_COMMON_DOCUMENTS, true ) ) )
+ {
+ aRet = rtl::OUString( reinterpret_cast< sal_Unicode * >(szPath) );
+ osl::FileBase::RC rc;
+ rc = osl::FileBase::getFileURLFromSystemPath( aRet, aRet );
+ }
+#else
+ osl::FileBase::getTempDirURL(aRet);
+#endif
+
+ return aRet;
+}
+
+//------------------------------------------------------------------------------
+
+UpdateCheckConfig::UpdateCheckConfig(
+ const uno::Reference<container::XNameContainer>& xContainer,
+ const ::rtl::Reference< UpdateCheckConfigListener >& rListener
+) : m_xContainer(xContainer), m_rListener(rListener)
+{
+}
+
+//------------------------------------------------------------------------------
+
+UpdateCheckConfig::~UpdateCheckConfig()
+{
+}
+
+//------------------------------------------------------------------------------
+
+::rtl::Reference< UpdateCheckConfig >
+UpdateCheckConfig::get(
+ const uno::Reference<uno::XComponentContext>& xContext,
+ const ::rtl::Reference< UpdateCheckConfigListener >& rListener)
+{
+ if( !xContext.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheckConfig: empty component context" ),
+ uno::Reference< uno::XInterface >() );
+
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
+
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheckConfig: unable to obtain service manager from component context" ),
+ uno::Reference< uno::XInterface >() );
+
+ uno::Reference< lang::XMultiServiceFactory > xConfigProvider(
+ xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.configuration.ConfigurationProvider" ), xContext ),
+ uno::UNO_QUERY_THROW);
+
+ beans::PropertyValue aProperty;
+ aProperty.Name = UNISTRING( "nodepath" );
+ aProperty.Value = uno::makeAny( UNISTRING("org.openoffice.Office.Jobs/Jobs/UpdateCheck/Arguments") );
+
+ uno::Sequence< uno::Any > aArgumentList( 1 );
+ aArgumentList[0] = uno::makeAny( aProperty );
+
+ uno::Reference< container::XNameContainer > xContainer(
+ xConfigProvider->createInstanceWithArguments(
+ UNISTRING("com.sun.star.configuration.ConfigurationUpdateAccess"), aArgumentList ),
+ uno::UNO_QUERY_THROW );
+
+ return new UpdateCheckConfig( xContainer, rListener );
+}
+
+//------------------------------------------------------------------------------
+
+bool
+UpdateCheckConfig::isAutoCheckEnabled() const
+{
+ sal_Bool nValue = sal_False;
+ const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( AUTOCHECK_ENABLED ) ) >>= nValue;
+ return nValue;
+}
+
+//------------------------------------------------------------------------------
+
+bool
+UpdateCheckConfig::isAutoDownloadEnabled() const
+{
+ sal_Bool nValue = sal_False;
+ const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( AUTODOWNLOAD_ENABLED ) ) >>= nValue;
+ return nValue;
+}
+
+//------------------------------------------------------------------------------
+
+rtl::OUString
+UpdateCheckConfig::getUpdateEntryVersion() const
+{
+ rtl::OUString aValue;
+
+ // getByName is defined as non const in XNameAccess
+ const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( OLD_VERSION ) ) >>= aValue;
+
+ return aValue;
+}
+
+//------------------------------------------------------------------------------
+
+sal_Int64
+UpdateCheckConfig::getLastChecked() const
+{
+ sal_Int64 nValue = 0;
+
+ // getByName is defined as non const in XNameAccess
+ const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( LAST_CHECK ) ) >>= nValue;
+
+ return nValue;
+}
+
+//------------------------------------------------------------------------------
+
+sal_Int64
+UpdateCheckConfig::getCheckInterval() const
+{
+ sal_Int64 nValue = 0;
+
+ // getByName is defined as non const in XNameAccess
+ const_cast < UpdateCheckConfig *> (this)->getByName( UNISTRING( CHECK_INTERVAL ) ) >>= nValue;
+
+ return nValue;
+}
+
+//------------------------------------------------------------------------------
+
+rtl::OUString
+UpdateCheckConfig::getLocalFileName() const
+{
+ rtl::OUString aName = UNISTRING(LOCAL_FILE);
+ rtl::OUString aRet;
+
+ if( m_xContainer->hasByName(aName) )
+ m_xContainer->getByName(aName) >>= aRet;
+
+ return aRet;
+}
+
+//------------------------------------------------------------------------------
+
+rtl::OUString
+UpdateCheckConfig::getDownloadDestination() const
+{
+ rtl::OUString aName = UNISTRING(DOWNLOAD_DESTINATION);
+ rtl::OUString aRet;
+
+ const_cast <UpdateCheckConfig *> (this)->getByName(aName) >>= aRet;
+
+ return aRet;
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheckConfig::storeLocalFileName(const rtl::OUString& rLocalFileName, sal_Int64 nFileSize)
+{
+ const sal_uInt8 nItems = 2;
+ const rtl::OUString aNameList[nItems] = { UNISTRING(LOCAL_FILE), UNISTRING(DOWNLOAD_SIZE) };
+ const uno::Any aValueList[nItems] = { uno::makeAny(rLocalFileName), uno::makeAny(nFileSize) };
+
+ for( sal_uInt8 i=0; i < nItems; ++i )
+ {
+ if( m_xContainer->hasByName(aNameList[i]) )
+ m_xContainer->replaceByName(aNameList[i], aValueList[i]);
+ else
+ m_xContainer->insertByName(aNameList[i],aValueList[i]);
+ }
+
+ commitChanges();
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheckConfig::clearLocalFileName()
+{
+ const sal_uInt8 nItems = 2;
+ const rtl::OUString aNameList[nItems] = { UNISTRING(LOCAL_FILE), UNISTRING(DOWNLOAD_SIZE) };
+
+ for( sal_uInt8 i=0; i < nItems; ++i )
+ {
+ if( m_xContainer->hasByName(aNameList[i]) )
+ m_xContainer->removeByName(aNameList[i]);
+ }
+
+ commitChanges();
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheckConfig::storeDownloadPaused(bool paused)
+{
+ replaceByName(UNISTRING(DOWNLOAD_PAUSED) , uno::makeAny(paused));
+ commitChanges();
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheckConfig::updateLastChecked()
+{
+ TimeValue systime;
+ osl_getSystemTime(&systime);
+
+ sal_Int64 lastCheck = systime.Seconds;
+
+ replaceByName(UNISTRING(LAST_CHECK), uno::makeAny(lastCheck));
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheckConfig::storeUpdateFound( const UpdateInfo& rInfo, const rtl::OUString& aCurrentBuild)
+
+{
+ bool autoDownloadEnabled = isAutoDownloadEnabled();
+
+ uno::Any aValues[nUpdateEntryProperties] =
+ {
+ uno::makeAny(rInfo.Version),
+ uno::makeAny(rInfo.BuildId),
+ uno::makeAny(rInfo.Description),
+ uno::makeAny(rInfo.Sources[0].URL),
+ uno::makeAny(rInfo.Sources[0].IsDirect ? sal_True : sal_False),
+ uno::makeAny(getReleaseNote(rInfo, 1, autoDownloadEnabled) ),
+ uno::makeAny(getReleaseNote(rInfo, 2, autoDownloadEnabled) ),
+ uno::makeAny(getReleaseNote(rInfo, 3, autoDownloadEnabled) ),
+ uno::makeAny(getReleaseNote(rInfo, 4, autoDownloadEnabled) ),
+ uno::makeAny(getReleaseNote(rInfo, 5, autoDownloadEnabled) ),
+ uno::makeAny(aCurrentBuild)
+ };
+
+ rtl::OUString aName;
+ for( sal_uInt32 n=0; n < nUpdateEntryProperties; ++n )
+ {
+ aName = rtl::OUString::createFromAscii(aUpdateEntryProperties[n]);
+
+ if( m_xContainer->hasByName(aName) )
+ m_xContainer->replaceByName(aName, aValues[n]);
+ else
+ m_xContainer->insertByName(aName,aValues[n]);
+ }
+
+ commitChanges();
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateCheckConfig::clearUpdateFound()
+{
+ rtl::OUString aName;
+
+ for( sal_uInt32 n=0; n < nUpdateEntryProperties; ++n )
+ {
+ aName = rtl::OUString::createFromAscii(aUpdateEntryProperties[n]);
+
+ try {
+ if( m_xContainer->hasByName(aName) )
+ m_xContainer->removeByName(aName);
+ } catch(const lang::WrappedTargetException& ) {
+ // Can not remove value, probably in share layer
+ OSL_ASSERT(false);
+ m_xContainer->replaceByName(aName, uno::makeAny(rtl::OUString()));
+ }
+ }
+
+ /* As we have removed UpdateVersionFound from the shared configuration
+ * existing entries in the user layer do not have a oor operation and
+ * thus are completly ignored (which also means they can not be removed).
+ */
+
+ commitChanges();
+}
+
+//------------------------------------------------------------------------------
+
+uno::Sequence< rtl::OUString >
+UpdateCheckConfig::getServiceNames()
+{
+ uno::Sequence< rtl::OUString > aServiceList(1);
+ aServiceList[0] = UNISTRING( "com.sun.star.setup.UpdateCheckConfig");
+ return aServiceList;
+}
+
+//------------------------------------------------------------------------------
+
+rtl::OUString
+UpdateCheckConfig::getImplName()
+{
+ return UNISTRING( "vnd.sun.UpdateCheckConfig");
+}
+
+//------------------------------------------------------------------------------
+
+uno::Type SAL_CALL
+UpdateCheckConfig::getElementType() throw (uno::RuntimeException)
+{
+ return m_xContainer->getElementType();
+}
+
+//------------------------------------------------------------------------------
+
+sal_Bool SAL_CALL
+UpdateCheckConfig::hasElements() throw (uno::RuntimeException)
+{
+ return m_xContainer->hasElements();
+}
+
+//------------------------------------------------------------------------------
+
+uno::Any SAL_CALL
+UpdateCheckConfig::getByName( const ::rtl::OUString& aName )
+ throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ uno::Any aValue = m_xContainer->getByName( aName );
+
+ // Provide dynamic default value
+ if( aName.equalsAscii(DOWNLOAD_DESTINATION) )
+ {
+ rtl::OUString aStr;
+ aValue >>= aStr;
+
+ if( aStr.getLength() == 0 )
+ aValue = uno::makeAny(getDesktopDirectory());
+ }
+
+ return aValue;
+}
+
+//------------------------------------------------------------------------------
+
+uno::Sequence< ::rtl::OUString > SAL_CALL
+UpdateCheckConfig::getElementNames( ) throw (uno::RuntimeException)
+{
+ return m_xContainer->getElementNames();
+}
+
+//------------------------------------------------------------------------------
+
+sal_Bool SAL_CALL
+UpdateCheckConfig::hasByName( const ::rtl::OUString& aName ) throw (uno::RuntimeException)
+{
+ return m_xContainer->hasByName( aName );
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL
+UpdateCheckConfig::replaceByName( const ::rtl::OUString& aName, const uno::Any& aElement )
+ throw (lang::IllegalArgumentException, container::NoSuchElementException,
+ lang::WrappedTargetException, uno::RuntimeException)
+{
+ return m_xContainer->replaceByName( aName, aElement );
+}
+
+//------------------------------------------------------------------------------
+// XChangesBatch
+
+void SAL_CALL
+UpdateCheckConfig::commitChanges()
+ throw (lang::WrappedTargetException, uno::RuntimeException)
+{
+ uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY);
+ if( xChangesBatch.is() && xChangesBatch->hasPendingChanges() )
+ {
+ util::ChangesSet aChangesSet = xChangesBatch->getPendingChanges();
+ xChangesBatch->commitChanges();
+
+ if( m_rListener.is() )
+ {
+ const sal_Int32 nChanges = aChangesSet.getLength();
+ rtl::OUString aString;
+
+ for( sal_Int32 i=0; i<nChanges; ++i )
+ {
+ aChangesSet[i].Accessor >>= aString;
+
+ // FIXME: use non IgnoreAsciiCase version as soon as it becomes available
+ if( aString.endsWithIgnoreAsciiCaseAsciiL(AUTOCHECK_ENABLED "']", sizeof(AUTOCHECK_ENABLED)+1) )
+ {
+ sal_Bool bEnabled = sal_False;
+ aChangesSet[i].Element >>= bEnabled;
+ m_rListener->autoCheckStatusChanged(sal_True == bEnabled);
+ }
+ // FIXME: use non IgnoreAsciiCase version as soon as it becomes available
+ else if( aString.endsWithIgnoreAsciiCaseAsciiL(CHECK_INTERVAL "']", sizeof(CHECK_INTERVAL)+1) )
+ {
+ m_rListener->autoCheckIntervalChanged();
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+sal_Bool SAL_CALL
+UpdateCheckConfig::hasPendingChanges( ) throw (uno::RuntimeException)
+{
+ uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY);
+ if( xChangesBatch.is() )
+ return xChangesBatch->hasPendingChanges();
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+
+uno::Sequence< util::ElementChange > SAL_CALL
+UpdateCheckConfig::getPendingChanges( ) throw (uno::RuntimeException)
+{
+ uno::Reference< util::XChangesBatch > xChangesBatch(m_xContainer, uno::UNO_QUERY);
+ if( xChangesBatch.is() )
+ return xChangesBatch->getPendingChanges();
+
+ return uno::Sequence< util::ElementChange >();
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheckConfig::storeExtensionVersion( const rtl::OUString& rExtensionName,
+ const rtl::OUString& rVersion )
+{
+ const rtl::OUString aExtName = UNISTRING( EXTENSION_PREFIX ) + rExtensionName;
+ const uno::Any aValue = uno::makeAny( rVersion );
+
+ if( m_xContainer->hasByName( aExtName ) )
+ m_xContainer->replaceByName( aExtName, aValue );
+ else
+ m_xContainer->insertByName( aExtName, aValue );
+
+ commitChanges();
+}
+
+//------------------------------------------------------------------------------
+bool UpdateCheckConfig::checkExtensionVersion( const rtl::OUString& rExtensionName,
+ const rtl::OUString& rVersion )
+{
+ const rtl::OUString aExtName = UNISTRING( EXTENSION_PREFIX ) + rExtensionName;
+
+ if( m_xContainer->hasByName( aExtName ) )
+ {
+ uno::Any aValue = m_xContainer->getByName( aExtName );
+ rtl::OUString aStoredVersion;
+ aValue >>= aStoredVersion;
+
+ if ( isVersionGreater( rVersion, aStoredVersion ) )
+ return true;
+ else
+ {
+ m_xContainer->removeByName( aExtName );
+ commitChanges();
+ }
+ }
+ return false;
+}
+
+//------------------------------------------------------------------------------
+rtl::OUString UpdateCheckConfig::getSubVersion( const rtl::OUString& rVersion,
+ sal_Int32 *nIndex )
+{
+ while ( *nIndex < rVersion.getLength() && rVersion[*nIndex] == '0')
+ {
+ ++*nIndex;
+ }
+
+ return rVersion.getToken( 0, '.', *nIndex );
+}
+
+//------------------------------------------------------------------------------
+// checks if the second version string is greater than the first one
+
+bool UpdateCheckConfig::isVersionGreater( const rtl::OUString& rVersion1,
+ const rtl::OUString& rVersion2 )
+{
+ for ( sal_Int32 i1 = 0, i2 = 0; i1 >= 0 || i2 >= 0; )
+ {
+ ::rtl::OUString sSub1( getSubVersion( rVersion1, &i1 ) );
+ ::rtl::OUString sSub2( getSubVersion( rVersion2, &i2 ) );
+
+ if ( sSub1.getLength() < sSub2.getLength() ) {
+ return true;
+ } else if ( sSub1.getLength() > sSub2.getLength() ) {
+ return false;
+ } else if ( sSub1 < sSub2 ) {
+ return true;
+ } else if ( sSub1 > sSub2 ) {
+ return false;
+ }
+ }
+ return false;
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+rtl::OUString SAL_CALL
+UpdateCheckConfig::getImplementationName() throw (uno::RuntimeException)
+{
+ return getImplName();
+}
+
+//------------------------------------------------------------------------------
+
+sal_Bool SAL_CALL
+UpdateCheckConfig::supportsService(rtl::OUString const & serviceName)
+ throw (uno::RuntimeException)
+{
+ uno::Sequence< rtl::OUString > aServiceNameList = getServiceNames();
+
+ for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ )
+ if( aServiceNameList[n].equals(serviceName) )
+ return sal_True;
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+
+uno::Sequence< rtl::OUString > SAL_CALL
+UpdateCheckConfig::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return getServiceNames();
+}
+
+
diff --git a/extensions/source/update/check/updatecheckconfig.hxx b/extensions/source/update/check/updatecheckconfig.hxx
new file mode 100644
index 000000000000..dc66656314dd
--- /dev/null
+++ b/extensions/source/update/check/updatecheckconfig.hxx
@@ -0,0 +1,241 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatecheckconfig.hxx,v $
+ * $Revision: 1.9 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <cppuhelper/implbase3.hxx>
+#include <com/sun/star/beans/NamedValue.hpp>
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/util/XChangesBatch.hpp>
+#include <rtl/ref.hxx>
+
+#include "updatecheckconfiglistener.hxx"
+#include "updateinfo.hxx"
+
+/* Interface to acess configuration data read-only */
+struct IByNameAccess
+{
+ virtual ::com::sun::star::uno::Any getValue(const sal_Char * pName) = 0;
+};
+
+/* This helper class provides by name access to a sequence of named values */
+class NamedValueByNameAccess : public IByNameAccess
+{
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& m_rValues;
+
+public:
+ NamedValueByNameAccess(
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& rValues) :
+ m_rValues(rValues) {} ;
+
+ virtual ~NamedValueByNameAccess();
+
+ virtual ::com::sun::star::uno::Any getValue(const sal_Char * pName);
+};
+
+
+/* This class encapsulates the configuration item actually used for storing the state
+ * the update check is actually in.
+ */
+class UpdateCheckROModel
+{
+public:
+ UpdateCheckROModel(IByNameAccess& aNameAccess) : m_aNameAccess(aNameAccess) {};
+
+ bool isAutoCheckEnabled() const;
+ bool isDownloadPaused() const;
+ rtl::OUString getLocalFileName() const;
+ sal_Int64 getDownloadSize() const;
+
+ rtl::OUString getUpdateEntryVersion() const;
+ void getUpdateEntry(UpdateInfo& rInfo) const;
+
+private:
+
+ rtl::OUString getStringValue(const sal_Char *) const;
+
+ IByNameAccess& m_aNameAccess;
+};
+
+
+
+/* This class implements the non published UNO service com.sun.star.setup.UpdateCheckConfig,
+ * which primary use is to be able to track changes done in the Toos -> Options page of this
+ * component, as this is not supported by the OOo configuration for extendable groups.
+ */
+
+class UpdateCheckConfig : public ::cppu::WeakImplHelper3<
+ ::com::sun::star::container::XNameReplace,
+ ::com::sun::star::util::XChangesBatch,
+ ::com::sun::star::lang::XServiceInfo >
+{
+ UpdateCheckConfig(const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer >& xContainer,
+ const ::rtl::Reference< UpdateCheckConfigListener >& rListener );
+
+ virtual ~UpdateCheckConfig();
+
+public:
+
+ static ::com::sun::star::uno::Sequence< rtl::OUString > getServiceNames();
+ static rtl::OUString getImplName();
+
+ static ::rtl::Reference< UpdateCheckConfig > get(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& xContext,
+ const ::rtl::Reference< UpdateCheckConfigListener >& rListener = ::rtl::Reference< UpdateCheckConfigListener >());
+
+ // Should really implement ROModel ..
+ bool isAutoCheckEnabled() const;
+ bool isAutoDownloadEnabled() const;
+ rtl::OUString getUpdateEntryVersion() const;
+
+ /* Updates the timestamp of last check, but does not commit the change
+ * as either clearUpdateFound() or setUpdateFound() are expected to get
+ * called next.
+ */
+ void updateLastChecked();
+
+ /* Returns the date of the last successful check in seconds since 1970 */
+ sal_Int64 getLastChecked() const;
+
+ /* Returns configured check interval in seconds */
+ sal_Int64 getCheckInterval() const;
+
+ /* Reset values of previously remembered update
+ */
+ void clearUpdateFound();
+
+ /* Stores the specified data of an available update
+ */
+ void storeUpdateFound(const UpdateInfo& rInfo, const rtl::OUString& aCurrentBuild);
+
+ // Returns the local file name of a started download
+ rtl::OUString getLocalFileName() const;
+
+ // Returns the local file name of a started download
+ rtl::OUString getDownloadDestination() const;
+
+ // stores the local file name of a just started download
+ void storeLocalFileName(const rtl::OUString& rFileName, sal_Int64 nFileSize);
+
+ // Removes the local file name of a download
+ void clearLocalFileName();
+
+ // Stores the bool value for manually paused downloads
+ void storeDownloadPaused(bool paused);
+
+ // Returns the directory that acts as the user's desktop
+ static rtl::OUString getDesktopDirectory();
+
+ // Returns a directory accessible for all users
+ static rtl::OUString getAllUsersDirectory();
+
+ // store and retrieve information about extensions
+ void storeExtensionVersion( const rtl::OUString& rExtensionName,
+ const rtl::OUString& rVersion );
+ bool checkExtensionVersion( const rtl::OUString& rExtensionName,
+ const rtl::OUString& rVersion );
+
+ // XElementAccess
+ virtual ::com::sun::star::uno::Type SAL_CALL getElementType( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL hasElements( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XNameAccess
+ virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
+ throw (::com::sun::star::container::NoSuchElementException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XNameReplace
+ virtual void SAL_CALL replaceByName( const ::rtl::OUString& aName, const ::com::sun::star::uno::Any& aElement )
+ throw (::com::sun::star::lang::IllegalArgumentException,
+ ::com::sun::star::container::NoSuchElementException,
+ ::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException);
+
+ // XChangesBatch
+ virtual void SAL_CALL commitChanges( )
+ throw (::com::sun::star::lang::WrappedTargetException,
+ ::com::sun::star::uno::RuntimeException);
+ virtual ::sal_Bool SAL_CALL hasPendingChanges( )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::util::ElementChange > SAL_CALL getPendingChanges( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XServiceInfo
+ virtual rtl::OUString SAL_CALL getImplementationName()
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName)
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual ::com::sun::star::uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames()
+ throw (::com::sun::star::uno::RuntimeException);
+
+private:
+
+ static rtl::OUString getSubVersion( const rtl::OUString& rVersion, sal_Int32 *nIndex );
+ static bool isVersionGreater( const rtl::OUString& rVersion1, const rtl::OUString& rVersion2 );
+
+ const ::com::sun::star::uno::Reference< ::com::sun::star::container::XNameContainer > m_xContainer;
+ const ::rtl::Reference< UpdateCheckConfigListener > m_rListener;
+};
+
+//------------------------------------------------------------------------------
+
+
+template <typename T>
+T getValue( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::NamedValue >& rNamedValues, const sal_Char * pszName )
+ throw (::com::sun::star::uno::RuntimeException)
+{
+ for( sal_Int32 n=0; n < rNamedValues.getLength(); n++ )
+ {
+ // Unfortunatly gcc-3.3 does not like Any.get<T>();
+ if( rNamedValues[n].Name.equalsAscii( pszName ) )
+ {
+ T value = T();
+ if( ! (rNamedValues[n].Value >>= value) )
+ throw ::com::sun::star::uno::RuntimeException(
+ ::rtl::OUString(
+ cppu_Any_extraction_failure_msg(
+ &rNamedValues[n].Value,
+ ::cppu::getTypeFavourUnsigned(&value).getTypeLibType() ),
+ SAL_NO_ACQUIRE ),
+ ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() );
+
+ return value;
+ }
+ }
+
+ return T();
+}
diff --git a/extensions/source/update/check/updatecheckconfiglistener.hxx b/extensions/source/update/check/updatecheckconfiglistener.hxx
new file mode 100644
index 000000000000..6ff0af2fb457
--- /dev/null
+++ b/extensions/source/update/check/updatecheckconfiglistener.hxx
@@ -0,0 +1,46 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatecheckconfiglistener.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <rtl/ref.hxx>
+
+#ifndef _UPDATECHECKCONFIGLISTENER_HXX_
+#define _UPDATECHECKCONFIGLISTENER_HXX_
+
+/* This interface should be implemented by classes acting
+ * as controller (as in the MVC pattern).
+ */
+
+struct UpdateCheckConfigListener : public rtl::IReference
+{
+ virtual void autoCheckStatusChanged(bool enabled) = 0;
+ virtual void autoCheckIntervalChanged() = 0;
+};
+
+#endif
diff --git a/extensions/source/update/check/updatecheckjob.cxx b/extensions/source/update/check/updatecheckjob.cxx
new file mode 100644
index 000000000000..f64ba851e679
--- /dev/null
+++ b/extensions/source/update/check/updatecheckjob.cxx
@@ -0,0 +1,429 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatecheckjob.cxx,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+
+#include "updatecheck.hxx"
+#include "updatecheckconfig.hxx"
+#include "updatehdl.hxx"
+#include "updateprotocol.hxx"
+
+#include <cppuhelper/implbase3.hxx>
+#include <cppuhelper/implementationentry.hxx>
+
+#include "com/sun/star/frame/XDesktop.hpp"
+#include "com/sun/star/frame/XTerminateListener.hpp"
+#include <com/sun/star/task/XJob.hpp>
+
+namespace beans = com::sun::star::beans ;
+namespace frame = com::sun::star::frame ;
+namespace lang = com::sun::star::lang ;
+namespace task = com::sun::star::task ;
+namespace uno = com::sun::star::uno ;
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+namespace
+{
+
+class InitUpdateCheckJobThread : public osl::Thread
+{
+public:
+ InitUpdateCheckJobThread( const uno::Reference< uno::XComponentContext > &xContext,
+ const uno::Sequence< beans::NamedValue > &xParameters );
+
+ virtual void SAL_CALL run();
+ virtual void SAL_CALL onTerminated();
+
+ void showDialog();
+ void setTerminating() { m_bTerminating = true; }
+
+protected:
+ ~InitUpdateCheckJobThread();
+
+private:
+ osl::Condition m_aCondition;
+ uno::Reference<uno::XComponentContext> m_xContext;
+ uno::Sequence<beans::NamedValue> m_xParameters;
+ bool m_bShowDialog;
+ bool m_bTerminating;
+};
+
+class UpdateCheckJob :
+ public ::cppu::WeakImplHelper3< task::XJob, lang::XServiceInfo, frame::XTerminateListener >
+{
+ virtual ~UpdateCheckJob();
+
+public:
+
+ UpdateCheckJob(const uno::Reference<uno::XComponentContext>& xContext);
+
+ static uno::Sequence< rtl::OUString > getServiceNames();
+ static rtl::OUString getImplName();
+
+ // Allows runtime exceptions to be thrown by const methods
+ inline SAL_CALL operator uno::Reference< uno::XInterface > () const
+ { return const_cast< cppu::OWeakObject * > (static_cast< cppu::OWeakObject const * > (this)); };
+
+ // XJob
+ virtual uno::Any SAL_CALL execute(const uno::Sequence<beans::NamedValue>&)
+ throw (lang::IllegalArgumentException, uno::Exception);
+
+ // XServiceInfo
+ virtual rtl::OUString SAL_CALL getImplementationName()
+ throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName)
+ throw (uno::RuntimeException);
+ virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames()
+ throw (uno::RuntimeException);
+
+ // XEventListener
+ virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XTerminateListener
+ virtual void SAL_CALL queryTermination( lang::EventObject const & evt )
+ throw ( frame::TerminationVetoException, uno::RuntimeException );
+ virtual void SAL_CALL notifyTermination( lang::EventObject const & evt )
+ throw ( uno::RuntimeException );
+
+private:
+ uno::Reference<uno::XComponentContext> m_xContext;
+ uno::Reference< frame::XDesktop > m_xDesktop;
+ InitUpdateCheckJobThread *m_pInitThread;
+
+ void handleExtensionUpdates( const uno::Sequence< beans::NamedValue > &rListProp );
+};
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+InitUpdateCheckJobThread::InitUpdateCheckJobThread(
+ const uno::Reference< uno::XComponentContext > &xContext,
+ const uno::Sequence< beans::NamedValue > &xParameters ) :
+ m_xContext( xContext ),
+ m_xParameters( xParameters ),
+ m_bShowDialog( false ),
+ m_bTerminating( false )
+{
+ create();
+}
+
+//------------------------------------------------------------------------------
+InitUpdateCheckJobThread::~InitUpdateCheckJobThread()
+{
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL InitUpdateCheckJobThread::run()
+{
+ TimeValue tv = { 25, 0 };
+
+ m_aCondition.wait( &tv );
+
+ if ( m_bTerminating )
+ return;
+
+ rtl::Reference< UpdateCheck > aController( UpdateCheck::get() );
+ aController->initialize( m_xParameters, m_xContext );
+
+ if ( m_bShowDialog )
+ aController->showDialog( true );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL InitUpdateCheckJobThread::onTerminated()
+{
+ delete this;
+}
+
+//------------------------------------------------------------------------------
+void InitUpdateCheckJobThread::showDialog()
+{
+ m_bShowDialog = true;
+ m_aCondition.set();
+}
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+UpdateCheckJob::UpdateCheckJob( const uno::Reference<uno::XComponentContext>& xContext ) :
+ m_xContext(xContext),
+ m_pInitThread( NULL )
+{
+ m_xDesktop.set( xContext->getServiceManager()->createInstanceWithContext( UNISTRING("com.sun.star.frame.Desktop"), xContext ), uno::UNO_QUERY );
+ if ( m_xDesktop.is() )
+ m_xDesktop->addTerminateListener( this );
+}
+
+//------------------------------------------------------------------------------
+
+UpdateCheckJob::~UpdateCheckJob()
+{
+}
+
+//------------------------------------------------------------------------------
+
+uno::Sequence< rtl::OUString >
+UpdateCheckJob::getServiceNames()
+{
+ uno::Sequence< rtl::OUString > aServiceList(1);
+ aServiceList[0] = UNISTRING( "com.sun.star.setup.UpdateCheck");
+ return aServiceList;
+};
+
+//------------------------------------------------------------------------------
+
+rtl::OUString
+UpdateCheckJob::getImplName()
+{
+ return UNISTRING( "vnd.sun.UpdateCheck");
+}
+
+
+//------------------------------------------------------------------------------
+
+uno::Any
+UpdateCheckJob::execute(const uno::Sequence<beans::NamedValue>& namedValues)
+ throw (lang::IllegalArgumentException, uno::Exception)
+{
+ for ( sal_Int32 n=namedValues.getLength(); n-- > 0; )
+ {
+ if ( namedValues[ n ].Name.equalsAscii( "DynamicData" ) )
+ {
+ uno::Sequence<beans::NamedValue> aListProp;
+ if ( namedValues[n].Value >>= aListProp )
+ {
+ for ( sal_Int32 i=aListProp.getLength(); i-- > 0; )
+ {
+ if ( aListProp[ i ].Name.equalsAscii( "updateList" ) )
+ {
+ handleExtensionUpdates( aListProp );
+ return uno::Any();
+ }
+ }
+ }
+ }
+ }
+
+ uno::Sequence<beans::NamedValue> aConfig =
+ getValue< uno::Sequence<beans::NamedValue> > (namedValues, "JobConfig");
+ m_pInitThread = new InitUpdateCheckJobThread( m_xContext, aConfig );
+
+ /* Determine the way we got invoked here -
+ * see Developers Guide Chapter "4.7.2 Jobs" to understand the magic
+ */
+
+ uno::Sequence<beans::NamedValue> aEnvironment =
+ getValue< uno::Sequence<beans::NamedValue> > (namedValues, "Environment");
+
+ rtl::OUString aEventName = getValue< rtl::OUString > (aEnvironment, "EventName");
+
+ if( ! aEventName.equalsAscii("onFirstVisibleTask") )
+ {
+ m_pInitThread->showDialog();
+ }
+
+ return uno::Any();
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheckJob::handleExtensionUpdates( const uno::Sequence< beans::NamedValue > &rListProp )
+{
+ try {
+ uno::Sequence< uno::Sequence< rtl::OUString > > aList =
+ getValue< uno::Sequence< uno::Sequence< rtl::OUString > > > ( rListProp, "updateList" );
+ bool bPrepareOnly = getValue< bool > ( rListProp, "prepareOnly" );
+
+ // we will first store any new found updates and then check, if there are any
+ // pending updates.
+ storeExtensionUpdateInfos( m_xContext, aList );
+
+ if ( bPrepareOnly )
+ return;
+
+ bool bHasUpdates = checkForPendingUpdates( m_xContext );
+
+ rtl::Reference<UpdateCheck> aController( UpdateCheck::get() );
+ if ( ! aController.is() )
+ return;
+
+ aController->setHasExtensionUpdates( bHasUpdates );
+
+ if ( ! aController->hasOfficeUpdate() )
+ {
+ if ( bHasUpdates )
+ aController->setUIState( UPDATESTATE_EXT_UPD_AVAIL, true );
+ else
+ aController->setUIState( UPDATESTATE_NO_UPDATE_AVAIL, true );
+ }
+ }
+ catch( const uno::Exception& e )
+ {
+ OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
+ }
+}
+
+//------------------------------------------------------------------------------
+
+rtl::OUString SAL_CALL
+UpdateCheckJob::getImplementationName() throw (uno::RuntimeException)
+{
+ return getImplName();
+}
+
+//------------------------------------------------------------------------------
+
+uno::Sequence< rtl::OUString > SAL_CALL
+UpdateCheckJob::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return getServiceNames();
+}
+
+//------------------------------------------------------------------------------
+
+sal_Bool SAL_CALL
+UpdateCheckJob::supportsService( rtl::OUString const & serviceName ) throw (uno::RuntimeException)
+{
+ uno::Sequence< rtl::OUString > aServiceNameList = getServiceNames();
+
+ for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ )
+ if( aServiceNameList[n].equals(serviceName) )
+ return sal_True;
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+// XEventListener
+void SAL_CALL UpdateCheckJob::disposing( lang::EventObject const & rEvt )
+ throw ( uno::RuntimeException )
+{
+ bool shutDown = ( rEvt.Source == m_xDesktop );
+
+ if ( shutDown && m_xDesktop.is() )
+ {
+ m_xDesktop->removeTerminateListener( this );
+ m_xDesktop.clear();
+ }
+}
+
+//------------------------------------------------------------------------------
+// XTerminateListener
+void SAL_CALL UpdateCheckJob::queryTermination( lang::EventObject const & )
+ throw ( frame::TerminationVetoException, uno::RuntimeException )
+{
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL UpdateCheckJob::notifyTermination( lang::EventObject const & rEvt )
+ throw ( uno::RuntimeException )
+{
+ if ( m_pInitThread )
+ m_pInitThread->setTerminating();
+
+ disposing( rEvt );
+}
+
+} // anonymous namespace
+
+//------------------------------------------------------------------------------
+
+static uno::Reference<uno::XInterface> SAL_CALL
+createJobInstance(const uno::Reference<uno::XComponentContext>& xContext)
+{
+ return *new UpdateCheckJob(xContext);
+}
+
+//------------------------------------------------------------------------------
+
+static uno::Reference<uno::XInterface> SAL_CALL
+createConfigInstance(const uno::Reference<uno::XComponentContext>& xContext)
+{
+ return *UpdateCheckConfig::get(xContext, *UpdateCheck::get());
+}
+
+//------------------------------------------------------------------------------
+
+static const cppu::ImplementationEntry kImplementations_entries[] =
+{
+ {
+ createJobInstance,
+ UpdateCheckJob::getImplName,
+ UpdateCheckJob::getServiceNames,
+ cppu::createSingleComponentFactory,
+ NULL,
+ 0
+ },
+ {
+ createConfigInstance,
+ UpdateCheckConfig::getImplName,
+ UpdateCheckConfig::getServiceNames,
+ cppu::createSingleComponentFactory,
+ NULL,
+ 0
+ },
+ { NULL, NULL, NULL, NULL, NULL, 0 }
+} ;
+
+//------------------------------------------------------------------------------
+
+extern "C" void SAL_CALL
+component_getImplementationEnvironment( const sal_Char **aEnvTypeName, uno_Environment **)
+{
+ *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" sal_Bool SAL_CALL
+component_writeInfo(void *pServiceManager, void *pRegistryKey)
+{
+ return cppu::component_writeInfoHelper(
+ pServiceManager,
+ pRegistryKey,
+ kImplementations_entries
+ );
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" void *
+component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
+{
+ return cppu::component_getFactoryHelper(
+ pszImplementationName,
+ pServiceManager,
+ pRegistryKey,
+ kImplementations_entries) ;
+}
diff --git a/extensions/source/update/check/updatehdl.cxx b/extensions/source/update/check/updatehdl.cxx
new file mode 100644
index 000000000000..ad1debd91beb
--- /dev/null
+++ b/extensions/source/update/check/updatehdl.cxx
@@ -0,0 +1,1318 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatehdl.cxx,v $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+
+#include "updatehdl.hxx"
+#include "update.hrc"
+
+#include "osl/diagnose.h"
+#include "osl/thread.hxx"
+#include "osl/file.hxx"
+#include "rtl/ustring.hxx"
+#include "rtl/bootstrap.hxx"
+
+#include "com/sun/star/uno/Sequence.h"
+
+#include <com/sun/star/style/VerticalAlignment.hpp>
+
+#include "com/sun/star/awt/ActionEvent.hpp"
+#include "com/sun/star/awt/PushButtonType.hpp"
+#include "com/sun/star/awt/VclWindowPeerAttribute.hpp"
+#include "com/sun/star/awt/WindowAttribute.hpp"
+#include "com/sun/star/awt/XButton.hpp"
+#include "com/sun/star/awt/XControl.hpp"
+#include "com/sun/star/awt/XControlContainer.hpp"
+#include "com/sun/star/awt/XMessageBox.hpp"
+#include "com/sun/star/awt/XThrobber.hpp"
+#include "com/sun/star/awt/XTopWindow.hpp"
+#include "com/sun/star/awt/XVclWindowPeer.hpp"
+#include "com/sun/star/awt/XWindow.hpp"
+#include "com/sun/star/awt/XWindow2.hpp"
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include "com/sun/star/beans/XPropertySet.hpp"
+
+#include "com/sun/star/container/XNameContainer.hpp"
+
+#include "com/sun/star/frame/XDesktop.hpp"
+
+#include "com/sun/star/lang/XMultiServiceFactory.hpp"
+#include "com/sun/star/task/InteractionRequestStringResolver.hpp"
+
+#include <com/sun/star/resource/XResourceBundleLoader.hpp>
+
+#include "updatehdl.hrc"
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+#define COMMAND_CLOSE UNISTRING("close")
+
+#define CTRL_THROBBER UNISTRING("throbber")
+#define CTRL_PROGRESS UNISTRING("progress")
+
+#define TEXT_STATUS UNISTRING("text_status")
+#define TEXT_PERCENT UNISTRING("text_percent")
+#define TEXT_DESCRIPTION UNISTRING("text_description")
+
+#define FIXED_LINE_MODEL UNISTRING("com.sun.star.awt.UnoControlFixedLineModel")
+#define FIXED_TEXT_MODEL UNISTRING("com.sun.star.awt.UnoControlFixedTextModel")
+#define EDIT_FIELD_MODEL UNISTRING("com.sun.star.awt.UnoControlEditModel")
+#define BUTTON_MODEL UNISTRING("com.sun.star.awt.UnoControlButtonModel")
+#define GROUP_BOX_MODEL UNISTRING("com.sun.star.awt.UnoControlGroupBoxModel")
+
+using namespace com::sun::star;
+
+//--------------------------------------------------------------------
+UpdateHandler::UpdateHandler( const uno::Reference< uno::XComponentContext > & rxContext,
+ const rtl::Reference< IActionListener > & rxActionListener ) :
+ mxContext( rxContext ),
+ mxActionListener( rxActionListener ),
+ meCurState( UPDATESTATES_COUNT ),
+ meLastState( UPDATESTATES_COUNT ),
+ mnPercent( 0 ),
+ mnLastCtrlState( -1 ),
+ mbDownloadBtnHasDots( false ),
+ mbVisible( false ),
+ mbStringsLoaded( false ),
+ mbMinimized( false ),
+ mbListenerAdded(false)
+{
+}
+
+//--------------------------------------------------------------------
+UpdateHandler::~UpdateHandler()
+{
+ mxContext = NULL;
+ mxUpdDlg = NULL;
+ mxInteractionHdl = NULL;
+ mxActionListener = NULL;
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::enableControls( short nCtrlState )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ if ( nCtrlState == mnLastCtrlState )
+ return;
+
+ bool bEnableControl;
+
+ short nCurStateVal = nCtrlState;
+ short nOldStateVal = mnLastCtrlState;
+
+ // the help button should always be the last button in the
+ // enum list und must never be disabled
+ for ( int i=0; i<HELP_BUTTON; i++ )
+ {
+ nCurStateVal = (short)(nCtrlState >> i);
+ nOldStateVal = (short)(mnLastCtrlState >> i);
+ if ( ( nCurStateVal & 0x01 ) != ( nOldStateVal & 0x01 ) )
+ {
+ bEnableControl = ( ( nCurStateVal & 0x01 ) == 0x01 );
+ setControlProperty( msButtonIDs[i], UNISTRING("Enabled"), uno::Any( bEnableControl ) );
+ }
+ }
+
+ mnLastCtrlState = nCtrlState;
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::setDownloadBtnLabel( bool bAppendDots )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ if ( mbDownloadBtnHasDots != bAppendDots )
+ {
+ rtl::OUString aLabel( msDownload );
+
+ if ( bAppendDots )
+ aLabel += UNISTRING( "..." );
+
+ setControlProperty( msButtonIDs[DOWNLOAD_BUTTON], UNISTRING("Label"), uno::Any( aLabel ) );
+ setControlProperty( msButtonIDs[DOWNLOAD_BUTTON], UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_DOWNLOAD2 ) ) );
+
+ mbDownloadBtnHasDots = bAppendDots;
+ }
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::setState( UpdateState eState )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ meCurState = eState;
+
+ if ( mxUpdDlg.is() && mbVisible )
+ updateState( meCurState );
+}
+
+//--------------------------------------------------------------------
+bool UpdateHandler::isVisible() const
+{
+ if ( !mxUpdDlg.is() ) return false;
+
+ uno::Reference< awt::XWindow2 > xWindow( mxUpdDlg, uno::UNO_QUERY );
+
+ if ( xWindow.is() )
+ return xWindow->isVisible();
+ else
+ return false;
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::setVisible( bool bVisible )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ mbVisible = bVisible;
+
+ if ( bVisible )
+ {
+ if ( !mxUpdDlg.is() )
+ createDialog();
+
+ // this should never happen, but if it happens we better return here
+ if ( !mxUpdDlg.is() )
+ return;
+
+ updateState( meCurState );
+
+ uno::Reference< awt::XWindow > xWindow( mxUpdDlg, uno::UNO_QUERY );
+
+ if ( xWindow.is() )
+ xWindow->setVisible( bVisible );
+
+ uno::Reference< awt::XTopWindow > xTopWindow( mxUpdDlg, uno::UNO_QUERY );
+ if ( xTopWindow.is() )
+ {
+ xTopWindow->toFront();
+ if ( !mbListenerAdded )
+ {
+ xTopWindow->addTopWindowListener( this );
+ mbListenerAdded = true;
+ }
+ }
+ }
+ else if ( mxUpdDlg.is() )
+ {
+ uno::Reference< awt::XWindow > xWindow( mxUpdDlg, uno::UNO_QUERY );
+
+ if ( xWindow.is() )
+ xWindow->setVisible( bVisible );
+ }
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::setProgress( sal_Int32 nPercent )
+{
+ if ( nPercent != mnPercent )
+ {
+ osl::MutexGuard aGuard( maMutex );
+
+ mnPercent = nPercent;
+ setControlProperty( CTRL_PROGRESS, UNISTRING("ProgressValue"), uno::Any( nPercent ) );
+ setControlProperty( TEXT_PERCENT, UNISTRING("Text"), uno::Any( substVariables(msPercent) ) );
+ }
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::setErrorMessage( const rtl::OUString& rErrorMsg )
+{
+ setControlProperty( TEXT_DESCRIPTION, UNISTRING("Text"), uno::Any( rErrorMsg ) );
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::setDownloadFile( const rtl::OUString& rFilePath )
+{
+ sal_Int32 nLast = rFilePath.lastIndexOf( '/' );
+ if ( nLast != -1 )
+ {
+ msDownloadFile = rFilePath.copy( nLast+1 );
+ const rtl::OUString aDownloadURL = rFilePath.copy( 0, nLast );
+ osl::FileBase::getSystemPathFromFileURL( aDownloadURL, msDownloadPath );
+ }
+}
+
+//--------------------------------------------------------------------
+rtl::OUString UpdateHandler::getBubbleText( UpdateState eState )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ rtl::OUString sText;
+ sal_Int32 nIndex = (sal_Int32) eState;
+
+ loadStrings();
+
+ if ( ( UPDATESTATE_UPDATE_AVAIL <= nIndex ) && ( nIndex < UPDATESTATES_COUNT ) )
+ sText = substVariables( msBubbleTexts[ nIndex - UPDATESTATE_UPDATE_AVAIL ] );
+
+ return sText;
+}
+
+//--------------------------------------------------------------------
+rtl::OUString UpdateHandler::getBubbleTitle( UpdateState eState )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ rtl::OUString sText;
+ sal_Int32 nIndex = (sal_Int32) eState;
+
+ loadStrings();
+
+ if ( ( UPDATESTATE_UPDATE_AVAIL <= nIndex ) && ( nIndex < UPDATESTATES_COUNT ) )
+ sText = substVariables( msBubbleTitles[ nIndex - UPDATESTATE_UPDATE_AVAIL] );
+
+ return sText;
+}
+
+//--------------------------------------------------------------------
+rtl::OUString UpdateHandler::getDefaultInstErrMsg()
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ loadStrings();
+
+ return substVariables( msInstallError );
+}
+
+// XActionListener
+//--------------------------------------------------------------------
+void SAL_CALL UpdateHandler::disposing( const lang::EventObject& rEvt )
+ throw( uno::RuntimeException )
+{
+ if ( rEvt.Source == mxUpdDlg )
+ mxUpdDlg.clear();
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL UpdateHandler::actionPerformed( awt::ActionEvent const & rEvent )
+ throw( uno::RuntimeException )
+{
+ DialogControls eButton = BUTTON_COUNT;
+ for ( int i = 0; i < BUTTON_COUNT; i++ )
+ {
+ if ( rEvent.ActionCommand.equals( msButtonIDs[i] ) )
+ {
+ eButton = (DialogControls) i;
+ break;
+ }
+ }
+
+ if ( rEvent.ActionCommand.equals( COMMAND_CLOSE ) )
+ {
+ if ( ( mnLastCtrlState & ( 1 << CLOSE_BUTTON ) ) == ( 1 << CLOSE_BUTTON ) )
+ eButton = CLOSE_BUTTON;
+ else
+ eButton = CANCEL_BUTTON;
+ }
+
+ switch ( eButton ) {
+ case CANCEL_BUTTON:
+ {
+ bool bCancel = true;
+
+ if ( ( meCurState == UPDATESTATE_DOWNLOADING ) ||
+ ( meCurState == UPDATESTATE_DOWNLOAD_PAUSED ) ||
+ ( meCurState == UPDATESTATE_ERROR_DOWNLOADING ) )
+ bCancel = showWarning( msCancelMessage );
+
+ if ( bCancel )
+ {
+ mxActionListener->cancel();
+ setVisible( false );
+ }
+ break;
+ }
+ case CLOSE_BUTTON:
+ setVisible( false );
+ if ( meCurState == UPDATESTATE_ERROR_CHECKING )
+ mxActionListener->closeAfterFailure();
+ break;
+ case DOWNLOAD_BUTTON:
+ mxActionListener->download();
+ break;
+ case INSTALL_BUTTON:
+ if ( showWarning( msInstallMessage ) )
+ mxActionListener->install();
+ break;
+ case PAUSE_BUTTON:
+ mxActionListener->pause();
+ break;
+ case RESUME_BUTTON:
+ mxActionListener->resume();
+ break;
+ case HELP_BUTTON:
+ break;
+ default:
+ OSL_ENSURE( false, "UpdateHandler::actionPerformed: unknown command!" );
+ }
+}
+
+// XTopWindowListener
+//--------------------------------------------------------------------
+void SAL_CALL UpdateHandler::windowOpened( const lang::EventObject& )
+ throw( uno::RuntimeException )
+{
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL UpdateHandler::windowClosing( const lang::EventObject& e )
+ throw( uno::RuntimeException )
+{
+ awt::ActionEvent aActionEvt;
+ aActionEvt.ActionCommand = COMMAND_CLOSE;
+ aActionEvt.Source = e.Source;
+
+ actionPerformed( aActionEvt );
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL UpdateHandler::windowClosed( const lang::EventObject& )
+ throw( uno::RuntimeException )
+{
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL UpdateHandler::windowMinimized( const lang::EventObject& )
+ throw( uno::RuntimeException )
+{
+ mbMinimized = true;
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL UpdateHandler::windowNormalized( const lang::EventObject& )
+ throw( uno::RuntimeException )
+{
+ mbMinimized = false;
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL UpdateHandler::windowActivated( const lang::EventObject& )
+ throw( uno::RuntimeException )
+{
+}
+
+//--------------------------------------------------------------------
+void SAL_CALL UpdateHandler::windowDeactivated( const lang::EventObject& )
+ throw( uno::RuntimeException )
+{
+}
+
+// XInteractionHandler
+//------------------------------------------------------------------------------
+void SAL_CALL UpdateHandler::handle( uno::Reference< task::XInteractionRequest > const & rRequest)
+ throw (uno::RuntimeException)
+{
+ if ( !mxInteractionHdl.is() )
+ {
+ if( !mxContext.is() )
+ throw uno::RuntimeException( UNISTRING( "UpdateHandler:: empty component context" ), *this );
+
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager(mxContext->getServiceManager());
+
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException( UNISTRING( "UpdateHandler: unable to obtain service manager from component context" ), *this );
+
+ mxInteractionHdl = uno::Reference<task::XInteractionHandler> (
+ xServiceManager->createInstanceWithContext(
+ UNISTRING( "com.sun.star.task.InteractionHandler" ),
+ mxContext),
+ uno::UNO_QUERY_THROW);
+ if( !mxInteractionHdl.is() )
+ throw uno::RuntimeException( UNISTRING( "UpdateHandler:: could not get default interaction handler" ), *this );
+ }
+ uno::Reference< task::XInteractionRequestStringResolver > xStrResolver =
+ task::InteractionRequestStringResolver::create( mxContext );
+ beans::Optional< ::rtl::OUString > aErrorText = xStrResolver->getStringFromInformationalRequest( rRequest );
+ if ( aErrorText.IsPresent )
+ {
+ setControlProperty( TEXT_DESCRIPTION, UNISTRING("Text"), uno::Any( aErrorText.Value ) );
+
+ uno::Sequence< uno::Reference< task::XInteractionContinuation > > xContinuations = rRequest->getContinuations();
+ if ( xContinuations.getLength() == 1 )
+ {
+ if ( meCurState == UPDATESTATE_CHECKING )
+ setState( UPDATESTATE_ERROR_CHECKING );
+ else if ( meCurState == UPDATESTATE_DOWNLOADING )
+ setState( UPDATESTATE_ERROR_DOWNLOADING );
+
+ xContinuations[0]->select();
+ }
+ else
+ mxInteractionHdl->handle( rRequest );
+ }
+ else
+ mxInteractionHdl->handle( rRequest );
+}
+
+//------------------------------------------------------------------------------
+// XTerminateListener
+//------------------------------------------------------------------------------
+void SAL_CALL UpdateHandler::queryTermination( const lang::EventObject& )
+ throw ( frame::TerminationVetoException, uno::RuntimeException )
+{
+ setVisible( false );
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL UpdateHandler::notifyTermination( const lang::EventObject& )
+ throw ( uno::RuntimeException )
+{
+ osl::MutexGuard aGuard( maMutex );
+
+ if ( mxUpdDlg.is() )
+ {
+ uno::Reference< awt::XTopWindow > xTopWindow( mxUpdDlg, uno::UNO_QUERY );
+ if ( xTopWindow.is() )
+ xTopWindow->removeTopWindowListener( this );
+
+ uno::Reference< lang::XComponent > xComponent( mxUpdDlg, uno::UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+
+ mxUpdDlg.clear();
+ }
+}
+
+//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+//--------------------------------------------------------------------
+void UpdateHandler::updateState( UpdateState eState )
+{
+ if ( meLastState == eState )
+ return;
+
+ if ( isVisible() )
+ {} // ToTop();
+
+ rtl::OUString sText;
+
+ switch ( eState )
+ {
+ case UPDATESTATE_CHECKING:
+ showControls( (1<<CANCEL_BUTTON) + (1<<THROBBER_CTRL) );
+ enableControls( 1<<CANCEL_BUTTON );
+ setControlProperty( TEXT_STATUS, UNISTRING("Text"), uno::Any( substVariables(msChecking) ) );
+ setControlProperty( TEXT_DESCRIPTION, UNISTRING("Text"), uno::Any( rtl::OUString() ) );
+ focusControl( CANCEL_BUTTON );
+ break;
+ case UPDATESTATE_ERROR_CHECKING:
+ showControls( 0 );
+ enableControls( 1 << CLOSE_BUTTON );
+ setControlProperty( TEXT_STATUS, UNISTRING("Text"), uno::Any( substVariables(msCheckingError) ) );
+ focusControl( CLOSE_BUTTON );
+ break;
+ case UPDATESTATE_UPDATE_AVAIL:
+ showControls( 0 );
+ enableControls( ( 1 << CLOSE_BUTTON ) + ( 1 << DOWNLOAD_BUTTON ) );
+ setControlProperty( TEXT_STATUS, UNISTRING("Text"), uno::Any( substVariables(msUpdFound) ) );
+
+ sText = substVariables(msDownloadWarning);
+ if ( msDescriptionMsg.getLength() )
+ sText += UNISTRING("\n\n") + msDescriptionMsg;
+ setControlProperty( TEXT_DESCRIPTION, UNISTRING("Text"), uno::Any( sText ) );
+
+ setDownloadBtnLabel( false );
+ focusControl( DOWNLOAD_BUTTON );
+ break;
+ case UPDATESTATE_UPDATE_NO_DOWNLOAD:
+ showControls( 0 );
+ enableControls( ( 1 << CLOSE_BUTTON ) + ( 1 << DOWNLOAD_BUTTON ) );
+ setControlProperty( TEXT_STATUS, UNISTRING("Text"), uno::Any( substVariables(msUpdFound) ) );
+
+ sText = substVariables(msDownloadNotAvail);
+ if ( msDescriptionMsg.getLength() )
+ sText += UNISTRING("\n\n") + msDescriptionMsg;
+ setControlProperty( TEXT_DESCRIPTION, UNISTRING("Text"), uno::Any( sText ) );
+
+ setDownloadBtnLabel( true );
+ focusControl( DOWNLOAD_BUTTON );
+ break;
+ case UPDATESTATE_NO_UPDATE_AVAIL:
+ case UPDATESTATE_EXT_UPD_AVAIL: // will only be set, when there are no office updates avail
+ showControls( 0 );
+ enableControls( 1 << CLOSE_BUTTON );
+ setControlProperty( TEXT_STATUS, UNISTRING("Text"), uno::Any( substVariables(msNoUpdFound) ) );
+ setControlProperty( TEXT_DESCRIPTION, UNISTRING("Text"), uno::Any( rtl::OUString() ) );
+ focusControl( CLOSE_BUTTON );
+ break;
+ case UPDATESTATE_DOWNLOADING:
+ showControls( (1<<PROGRESS_CTRL) + (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) + (1<<RESUME_BUTTON) );
+ enableControls( (1<<CLOSE_BUTTON) + (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) );
+ setControlProperty( TEXT_STATUS, UNISTRING("Text"), uno::Any( substVariables(msDownloading) ) );
+ setControlProperty( TEXT_PERCENT, UNISTRING("Text"), uno::Any( substVariables(msPercent) ) );
+ setControlProperty( TEXT_DESCRIPTION, UNISTRING("Text"), uno::Any( substVariables(msDownloadWarning) ) );
+ setControlProperty( CTRL_PROGRESS, UNISTRING("ProgressValue"), uno::Any( mnPercent ) );
+ focusControl( CLOSE_BUTTON );
+ break;
+ case UPDATESTATE_DOWNLOAD_PAUSED:
+ showControls( (1<<PROGRESS_CTRL) + (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) + (1<<RESUME_BUTTON) );
+ enableControls( (1<<CLOSE_BUTTON) + (1<<CANCEL_BUTTON) + (1<<RESUME_BUTTON) );
+ setControlProperty( TEXT_STATUS, UNISTRING("Text"), uno::Any( substVariables(msDownloadPause) ) );
+ setControlProperty( TEXT_PERCENT, UNISTRING("Text"), uno::Any( substVariables(msPercent) ) );
+ setControlProperty( TEXT_DESCRIPTION, UNISTRING("Text"), uno::Any( substVariables(msDownloadWarning) ) );
+ setControlProperty( CTRL_PROGRESS, UNISTRING("ProgressValue"), uno::Any( mnPercent ) );
+ focusControl( CLOSE_BUTTON );
+ break;
+ case UPDATESTATE_ERROR_DOWNLOADING:
+ showControls( (1<<PROGRESS_CTRL) + (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) + (1<<RESUME_BUTTON) );
+ enableControls( (1<<CLOSE_BUTTON) + (1<<CANCEL_BUTTON) );
+ setControlProperty( TEXT_STATUS, UNISTRING("Text"), uno::Any( substVariables(msDownloadError) ) );
+ focusControl( CLOSE_BUTTON );
+ break;
+ case UPDATESTATE_DOWNLOAD_AVAIL:
+ showControls( 0 );
+ enableControls( (1<<CLOSE_BUTTON) + (1<<INSTALL_BUTTON) );
+ setControlProperty( TEXT_STATUS, UNISTRING("Text"), uno::Any( substVariables(msReady2Install) ) );
+ setControlProperty( TEXT_DESCRIPTION, UNISTRING("Text"), uno::Any( substVariables(msDownloadDescr) ) );
+ focusControl( INSTALL_BUTTON );
+ break;
+ case UPDATESTATE_AUTO_START:
+ case UPDATESTATES_COUNT:
+ //do nothing, only count!
+ break;
+ }
+
+ meLastState = eState;
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::searchAndReplaceAll( rtl::OUString &rText,
+ const rtl::OUString &rWhat,
+ const rtl::OUString &rWith ) const
+{
+ sal_Int32 nIndex = rText.indexOf( rWhat );
+
+ while ( nIndex != -1 )
+ {
+ rText = rText.replaceAt( nIndex, rWhat.getLength(), rWith );
+ nIndex = rText.indexOf( rWhat, nIndex );
+ }
+}
+
+//--------------------------------------------------------------------
+rtl::OUString UpdateHandler::loadString( const uno::Reference< resource::XResourceBundle > xBundle,
+ sal_Int32 nResourceId ) const
+{
+ rtl::OUString sString;
+ rtl::OUString sKey = UNISTRING( "string:" ) + rtl::OUString::valueOf( nResourceId );
+
+ try
+ {
+ OSL_VERIFY( xBundle->getByName( sKey ) >>= sString );
+ }
+ catch( const uno::Exception& )
+ {
+ OSL_ENSURE( false, "UpdateHandler::loadString: caught an exception!" );
+ sString = UNISTRING("Missing ") + sKey;
+ }
+
+ return sString;
+}
+
+rtl::OUString UpdateHandler::substVariables( const rtl::OUString &rSource ) const
+{
+ rtl::OUString sString( rSource );
+
+ searchAndReplaceAll( sString, UNISTRING( "%NEXTVERSION" ), msNextVersion );
+ searchAndReplaceAll( sString, UNISTRING( "%DOWNLOAD_PATH" ), msDownloadPath );
+ searchAndReplaceAll( sString, UNISTRING( "%FILE_NAME" ), msDownloadFile );
+ searchAndReplaceAll( sString, UNISTRING( "%PERCENT" ), rtl::OUString::valueOf( mnPercent ) );
+
+ return sString;
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::loadStrings()
+{
+ if ( mbStringsLoaded )
+ return;
+ else
+ mbStringsLoaded = true;
+
+ uno::Reference< resource::XResourceBundleLoader > xLoader;
+ try
+ {
+ uno::Any aValue( mxContext->getValueByName(
+ UNISTRING( "/singletons/com.sun.star.resource.OfficeResourceLoader" ) ) );
+ OSL_VERIFY( aValue >>= xLoader );
+ }
+ catch( const uno::Exception& )
+ {
+ OSL_ENSURE( false, "UpdateHandler::loadStrings: could not create the resource loader!" );
+ }
+
+ if ( !xLoader.is() ) return;
+
+ uno::Reference< resource::XResourceBundle > xBundle;
+
+ try
+ {
+ xBundle = xLoader->loadBundle_Default( UNISTRING( "upd" ) );
+ }
+ catch( const resource::MissingResourceException& )
+ {
+ OSL_ENSURE( false, "UpdateHandler::loadStrings: missing the resource bundle!" );
+ }
+
+ if ( !xBundle.is() ) return;
+
+ msChecking = loadString( xBundle, RID_UPDATE_STR_CHECKING );
+ msCheckingError = loadString( xBundle, RID_UPDATE_STR_CHECKING_ERR );
+ msNoUpdFound = loadString( xBundle, RID_UPDATE_STR_NO_UPD_FOUND );
+
+ msUpdFound = loadString( xBundle, RID_UPDATE_STR_UPD_FOUND );
+ setFullVersion( msUpdFound );
+
+ msDlgTitle = loadString( xBundle, RID_UPDATE_STR_DLG_TITLE );
+ msDownloadPause = loadString( xBundle, RID_UPDATE_STR_DOWNLOAD_PAUSE );
+ msDownloadError = loadString( xBundle, RID_UPDATE_STR_DOWNLOAD_ERR );
+ msDownloadWarning = loadString( xBundle, RID_UPDATE_STR_DOWNLOAD_WARN );
+ msDownloadDescr = loadString( xBundle, RID_UPDATE_STR_DOWNLOAD_DESCR );
+ msDownloadNotAvail = loadString( xBundle, RID_UPDATE_STR_DOWNLOAD_UNAVAIL );
+ msDownloading = loadString( xBundle, RID_UPDATE_STR_DOWNLOADING );
+ msReady2Install = loadString( xBundle, RID_UPDATE_STR_READY_INSTALL );
+ msCancelTitle = loadString( xBundle, RID_UPDATE_STR_CANCEL_TITLE );
+ msCancelMessage = loadString( xBundle, RID_UPDATE_STR_CANCEL_DOWNLOAD );
+ msInstallMessage = loadString( xBundle, RID_UPDATE_STR_BEGIN_INSTALL );
+ msInstallNow = loadString( xBundle, RID_UPDATE_STR_INSTALL_NOW );
+ msInstallLater = loadString( xBundle, RID_UPDATE_STR_INSTALL_LATER );
+ msInstallError = loadString( xBundle, RID_UPDATE_STR_INSTALL_ERROR );
+ msOverwriteWarning = loadString( xBundle, RID_UPDATE_STR_OVERWRITE_WARNING );
+ msPercent = loadString( xBundle, RID_UPDATE_STR_PERCENT );
+
+ msStatusFL = loadString( xBundle, RID_UPDATE_FT_STATUS );
+ msDescription = loadString( xBundle, RID_UPDATE_FT_DESCRIPTION );
+
+ msClose = loadString( xBundle, RID_UPDATE_BTN_CLOSE );
+ msDownload = loadString( xBundle, RID_UPDATE_BTN_DOWNLOAD );
+ msInstall = loadString( xBundle, RID_UPDATE_BTN_INSTALL );
+ msPauseBtn = loadString( xBundle, RID_UPDATE_BTN_PAUSE );
+ msResumeBtn = loadString( xBundle, RID_UPDATE_BTN_RESUME );
+ msCancelBtn = loadString( xBundle, RID_UPDATE_BTN_CANCEL );
+
+ // all update states before UPDATESTATE_UPDATE_AVAIL don't have a bubble
+ // so we can ignore them
+ for ( int i=0; i < (int)(UPDATESTATES_COUNT - UPDATESTATE_UPDATE_AVAIL); i++ )
+ {
+ msBubbleTexts[ i ] = loadString( xBundle, RID_UPDATE_BUBBLE_TEXT_START + i );
+ msBubbleTitles[ i ] = loadString( xBundle, RID_UPDATE_BUBBLE_T_TEXT_START + i );
+ }
+
+ for ( int i=0; i < BUTTON_COUNT; i++ )
+ {
+ msButtonIDs[ i ] = UNISTRING("BUTTON_") + rtl::OUString::valueOf( (sal_Int32) i );
+ }
+}
+
+
+//--------------------------------------------------------------------
+void UpdateHandler::startThrobber( bool bStart )
+{
+ uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY );
+ uno::Reference< awt::XThrobber > xThrobber( xContainer->getControl( CTRL_THROBBER ), uno::UNO_QUERY );
+
+ if ( xThrobber.is() )
+ {
+ if ( bStart )
+ xThrobber->start();
+ else
+ xThrobber->stop();
+ }
+
+ uno::Reference< awt::XWindow > xWindow( xContainer->getControl( CTRL_THROBBER ), uno::UNO_QUERY );
+ if (xWindow.is() )
+ xWindow->setVisible( bStart );
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::setControlProperty( const rtl::OUString &rCtrlName,
+ const rtl::OUString &rPropName,
+ const uno::Any &rPropValue )
+{
+ if ( !mxUpdDlg.is() ) return;
+
+ uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY );
+ uno::Reference< awt::XControl > xControl( xContainer->getControl( rCtrlName ), uno::UNO_QUERY_THROW );
+ uno::Reference< awt::XControlModel > xControlModel( xControl->getModel(), uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW );
+
+ try {
+ xPropSet->setPropertyValue( rPropName, rPropValue );
+ }
+ catch( const beans::UnknownPropertyException& )
+ {
+ OSL_ENSURE( false, "UpdateHandler::setControlProperty: caught an exception!" );
+ }
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::showControl( const rtl::OUString &rCtrlName, bool bShow )
+{
+ uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY );
+
+ if ( !xContainer.is() )
+ {
+ OSL_ENSURE( false, "UpdateHandler::showControl: could not get control container!" );
+ return;
+ }
+
+ uno::Reference< awt::XWindow > xWindow( xContainer->getControl( rCtrlName ), uno::UNO_QUERY );
+ if ( xWindow.is() )
+ xWindow->setVisible( bShow );
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::focusControl( DialogControls eID )
+{
+ uno::Reference< awt::XControlContainer > xContainer( mxUpdDlg, uno::UNO_QUERY );
+
+ if ( !xContainer.is() )
+ {
+ OSL_ENSURE( false, "UpdateHandler::focusControl: could not get control container!" );
+ return;
+ }
+
+ OSL_ENSURE( (eID < BUTTON_COUNT), "UpdateHandler::focusControl: id to big!" );
+
+ uno::Reference< awt::XWindow > xWindow( xContainer->getControl( msButtonIDs[(short)eID] ), uno::UNO_QUERY );
+ if ( xWindow.is() )
+ xWindow->setFocus();
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::insertControlModel( uno::Reference< awt::XControlModel > & rxDialogModel,
+ rtl::OUString const & rServiceName,
+ rtl::OUString const & rControlName,
+ awt::Rectangle const & rPosSize,
+ uno::Sequence< beans::NamedValue > const & rProps )
+{
+ uno::Reference< lang::XMultiServiceFactory > xFactory (rxDialogModel, uno::UNO_QUERY_THROW);
+ uno::Reference< awt::XControlModel > xModel (xFactory->createInstance (rServiceName), uno::UNO_QUERY_THROW);
+ uno::Reference< beans::XPropertySet > xPropSet (xModel, uno::UNO_QUERY_THROW);
+
+ for (sal_Int32 i = 0, n = rProps.getLength(); i < n; i++)
+ {
+ xPropSet->setPropertyValue (rProps[i].Name, rProps[i].Value);
+ }
+
+ // @see awt/UnoControlDialogElement.idl
+ xPropSet->setPropertyValue( UNISTRING("Name"), uno::Any (rControlName) );
+ xPropSet->setPropertyValue( UNISTRING("PositionX"), uno::Any (rPosSize.X) );
+ xPropSet->setPropertyValue( UNISTRING("PositionY"), uno::Any (rPosSize.Y) );
+ xPropSet->setPropertyValue( UNISTRING("Height"), uno::Any (rPosSize.Height) );
+ xPropSet->setPropertyValue( UNISTRING("Width"), uno::Any (rPosSize.Width) );
+
+ // insert by Name into DialogModel container
+ uno::Reference< container::XNameContainer > xContainer (rxDialogModel, uno::UNO_QUERY_THROW);
+ xContainer->insertByName( rControlName, uno::Any (uno::Reference< uno::XInterface >(xModel, uno::UNO_QUERY)));
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::setFullVersion( rtl::OUString& rString )
+{
+ if( !mxContext.is() )
+ throw uno::RuntimeException( UNISTRING( "getProductName: empty component context" ), *this );
+
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager( mxContext->getServiceManager() );
+
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException( UNISTRING( "getProductName: unable to obtain service manager from component context" ), *this );
+
+ uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider(
+ xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.configuration.ConfigurationProvider" ), mxContext ),
+ uno::UNO_QUERY_THROW);
+
+ beans::PropertyValue aProperty;
+ aProperty.Name = UNISTRING( "nodepath" );
+ aProperty.Value = uno::makeAny( UNISTRING("org.openoffice.Setup/Product") );
+
+ uno::Sequence< uno::Any > aArgumentList( 1 );
+ aArgumentList[0] = uno::makeAny( aProperty );
+
+ uno::Reference< uno::XInterface > xConfigAccess;
+ xConfigAccess = xConfigurationProvider->createInstanceWithArguments( UNISTRING("com.sun.star.configuration.ConfigurationAccess"),
+ aArgumentList );
+
+ uno::Reference< container::XNameAccess > xNameAccess( xConfigAccess, uno::UNO_QUERY_THROW );
+
+ rtl::OUString aProductVersion;
+ rtl::OUString aProductFullVersion;
+
+ xNameAccess->getByName(UNISTRING("ooSetupVersion")) >>= aProductVersion;
+ aProductFullVersion = aProductVersion;
+
+ sal_Int32 nVerIndex = rString.indexOf( aProductVersion );
+ if ( nVerIndex != -1 )
+ {
+ rtl::OUString aPackageVersion = UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":OOOPackageVersion}" );
+ rtl::Bootstrap::expandMacros( aPackageVersion );
+
+ if ( aPackageVersion.getLength() )
+ {
+ sal_Int32 nTokIndex = 0;
+ rtl::OUString aVersionMinor = aPackageVersion.getToken( 1, '.', nTokIndex );
+ rtl::OUString aVersionMicro;
+
+ if ( nTokIndex > 0 )
+ aVersionMicro = aPackageVersion.getToken( 0, '.', nTokIndex );
+
+ if ( aVersionMinor.getLength() == 0 )
+ aVersionMinor = UNISTRING( "0" );
+ if ( aVersionMicro.getLength() == 0 )
+ aVersionMicro = UNISTRING( "0" );
+
+ sal_Int32 nIndex = aProductFullVersion.indexOf( '.' );
+ if ( nIndex == -1 )
+ {
+ aProductFullVersion += UNISTRING( "." );
+ aProductFullVersion += aVersionMinor;
+ }
+ else
+ {
+ nIndex = aProductFullVersion.indexOf( '.', nIndex+1 );
+ }
+ if ( nIndex == -1 )
+ {
+ aProductFullVersion += UNISTRING( "." );
+ aProductFullVersion += aVersionMicro;
+ }
+ else
+ {
+ aProductFullVersion = aProductFullVersion.replaceAt( nIndex+1, aProductFullVersion.getLength()-nIndex-1, aVersionMicro );
+ }
+ }
+ rString = rString.replaceAt( nVerIndex, aProductVersion.getLength(), aProductFullVersion );
+ }
+}
+
+//--------------------------------------------------------------------
+bool UpdateHandler::showWarning( const rtl::OUString &rWarningText ) const
+{
+ bool bRet = false;
+
+ uno::Reference< awt::XControl > xControl( mxUpdDlg, uno::UNO_QUERY );
+ if ( !xControl.is() ) return bRet;
+
+ uno::Reference< awt::XWindowPeer > xPeer = xControl->getPeer();
+ if ( !xPeer.is() ) return bRet;
+
+ uno::Reference< awt::XToolkit > xToolkit = xPeer->getToolkit();
+ if ( !xToolkit.is() ) return bRet;
+
+ awt::WindowDescriptor aDescriptor;
+
+ sal_Int32 nWindowAttributes = awt::WindowAttribute::BORDER | awt::WindowAttribute::MOVEABLE | awt::WindowAttribute::CLOSEABLE;
+ nWindowAttributes |= awt::VclWindowPeerAttribute::YES_NO;
+ nWindowAttributes |= awt::VclWindowPeerAttribute::DEF_NO;
+
+ aDescriptor.Type = awt::WindowClass_MODALTOP;
+ aDescriptor.WindowServiceName = UNISTRING( "warningbox" );
+ aDescriptor.ParentIndex = -1;
+ aDescriptor.Parent = xPeer;
+ aDescriptor.Bounds = awt::Rectangle( 10, 10, 250, 150 );
+ aDescriptor.WindowAttributes = nWindowAttributes;
+
+ uno::Reference< awt::XMessageBox > xMsgBox( xToolkit->createWindow( aDescriptor ), uno::UNO_QUERY );
+ if ( xMsgBox.is() )
+ {
+ sal_Int16 nRet;
+ // xMsgBox->setCaptionText( msCancelTitle );
+ xMsgBox->setMessageText( rWarningText );
+ nRet = xMsgBox->execute();
+ if ( nRet == 2 ) // RET_YES == 2
+ bRet = true;
+ }
+
+ uno::Reference< lang::XComponent > xComponent( xMsgBox, uno::UNO_QUERY );
+ if ( xComponent.is() )
+ xComponent->dispose();
+
+ return bRet;
+}
+
+//--------------------------------------------------------------------
+bool UpdateHandler::showOverwriteWarning() const
+{
+ return showWarning( msOverwriteWarning );
+}
+
+//--------------------------------------------------------------------
+#define BUTTON_HEIGHT 14
+#define BUTTON_WIDTH 50
+#define BUTTON_X_OFFSET 7
+#define BUTTON_Y_OFFSET 3
+#define LABEL_HEIGHT 10
+
+#define DIALOG_WIDTH 300
+#define DIALOG_BORDER 5
+#define INNER_BORDER 3
+#define TEXT_OFFSET 1
+#define BOX_HEIGHT1 ( LABEL_HEIGHT + 3*BUTTON_HEIGHT + 2*BUTTON_Y_OFFSET + 2*INNER_BORDER )
+#define BOX_HEIGHT2 50
+#define EDIT_WIDTH ( DIALOG_WIDTH - 2 * DIALOG_BORDER )
+#define BOX1_BTN_X ( DIALOG_BORDER + EDIT_WIDTH - BUTTON_WIDTH - INNER_BORDER )
+#define BOX1_BTN_Y ( DIALOG_BORDER + LABEL_HEIGHT + INNER_BORDER)
+#define THROBBER_WIDTH 14
+#define THROBBER_HEIGHT 14
+#define THROBBER_X_POS ( DIALOG_BORDER + 8 )
+#define THROBBER_Y_POS ( DIALOG_BORDER + 23 )
+#define BUTTON_BAR_HEIGHT 24
+#define LABEL_OFFSET ( LABEL_HEIGHT + 4 )
+#define DIALOG_HEIGHT ( BOX_HEIGHT1 + BOX_HEIGHT2 + LABEL_OFFSET + BUTTON_BAR_HEIGHT + 3 * DIALOG_BORDER )
+#define LABEL_Y_POS ( 2 * DIALOG_BORDER + BOX_HEIGHT1 )
+#define EDIT2_Y_POS ( LABEL_Y_POS + LABEL_HEIGHT )
+#define BUTTON_BAR_Y_POS ( EDIT2_Y_POS + DIALOG_BORDER + BOX_HEIGHT2 )
+#define BUTTON_Y_POS ( BUTTON_BAR_Y_POS + 8 )
+#define CLOSE_BTN_X ( DIALOG_WIDTH - DIALOG_BORDER - BUTTON_WIDTH )
+#define INSTALL_BTN_X ( CLOSE_BTN_X - 2 * BUTTON_X_OFFSET - BUTTON_WIDTH )
+#define DOWNLOAD_BTN_X ( INSTALL_BTN_X - BUTTON_X_OFFSET - BUTTON_WIDTH )
+#define PROGRESS_WIDTH 80
+#define PROGRESS_HEIGHT 10
+#define PROGRESS_X_POS ( DIALOG_BORDER + 8 )
+#define PROGRESS_Y_POS ( DIALOG_BORDER + 2*LABEL_OFFSET )
+
+//--------------------------------------------------------------------
+void UpdateHandler::showControls( short nControls )
+{
+ // The buttons from CANCEL_BUTTON to RESUME_BUTTON will be shown or
+ // hidden on demand
+ short nShiftMe;
+ for ( int i = 0; i <= (int)RESUME_BUTTON; i++ )
+ {
+ nShiftMe = (short)(nControls >> i);
+ showControl( msButtonIDs[i], (bool)(nShiftMe & 0x01) );
+ }
+
+ nShiftMe = (short)(nControls >> THROBBER_CTRL);
+ startThrobber( (bool)(nShiftMe & 0x01) );
+
+ nShiftMe = (short)(nControls >> PROGRESS_CTRL);
+ showControl( CTRL_PROGRESS, (bool)(nShiftMe & 0x01) );
+ showControl( TEXT_PERCENT, (bool)(nShiftMe & 0x01) );
+
+ // Status text needs to be smaller, when there are buttons at the right side of the dialog
+ if ( ( nControls & ( (1<<CANCEL_BUTTON) + (1<<PAUSE_BUTTON) + (1<<RESUME_BUTTON) ) ) != 0 )
+ setControlProperty( TEXT_STATUS, UNISTRING("Width"), uno::Any( sal_Int32(EDIT_WIDTH - BUTTON_WIDTH - 2*INNER_BORDER - TEXT_OFFSET ) ) );
+ else
+ setControlProperty( TEXT_STATUS, UNISTRING("Width"), uno::Any( sal_Int32(EDIT_WIDTH - 2*TEXT_OFFSET ) ) );
+
+ // Status text needs to be taller, when we show the progress bar
+ if ( ( nControls & ( 1<<PROGRESS_CTRL ) ) != 0 )
+ setControlProperty( TEXT_STATUS, UNISTRING("Height"), uno::Any( sal_Int32(LABEL_HEIGHT) ) );
+ else
+ setControlProperty( TEXT_STATUS, UNISTRING("Height"), uno::Any( sal_Int32(BOX_HEIGHT1 - 4*TEXT_OFFSET - LABEL_HEIGHT ) ) );
+}
+
+//--------------------------------------------------------------------
+void UpdateHandler::createDialog()
+{
+ if ( !mxContext.is() )
+ {
+ OSL_ASSERT( false );
+ return;
+ }
+
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager( mxContext->getServiceManager() );
+
+ if( xServiceManager.is() )
+ {
+ uno::Reference< frame::XDesktop > xDesktop(
+ xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.frame.Desktop"), mxContext ),
+ uno::UNO_QUERY );
+ if ( xDesktop.is() )
+ xDesktop->addTerminateListener( this );
+ }
+
+ loadStrings();
+
+ uno::Reference< lang::XMultiComponentFactory > xFactory( mxContext->getServiceManager(), uno::UNO_QUERY_THROW );
+ uno::Reference< awt::XControlModel > xControlModel( xFactory->createInstanceWithContext(
+ UNISTRING("com.sun.star.awt.UnoControlDialogModel"),
+ mxContext), uno::UNO_QUERY_THROW );
+ {
+ // @see awt/UnoControlDialogModel.idl
+ uno::Reference< beans::XPropertySet > xPropSet( xControlModel, uno::UNO_QUERY_THROW );
+
+ xPropSet->setPropertyValue( UNISTRING("Title"), uno::Any( msDlgTitle ) );
+ xPropSet->setPropertyValue( UNISTRING("Closeable"), uno::Any( true ) );
+ xPropSet->setPropertyValue( UNISTRING("Enabled"), uno::Any( true ) );
+ xPropSet->setPropertyValue( UNISTRING("Moveable"), uno::Any( true ) );
+ xPropSet->setPropertyValue( UNISTRING("Sizeable"), uno::Any( true ) );
+ xPropSet->setPropertyValue( UNISTRING("DesktopAsParent"), uno::Any( true ) );
+ xPropSet->setPropertyValue( UNISTRING("PositionX"), uno::Any(sal_Int32( 100 )) );
+ xPropSet->setPropertyValue( UNISTRING("PositionY"), uno::Any(sal_Int32( 100 )) );
+ xPropSet->setPropertyValue( UNISTRING("Width"), uno::Any(sal_Int32( DIALOG_WIDTH )) );
+ xPropSet->setPropertyValue( UNISTRING("Height"), uno::Any(sal_Int32( DIALOG_HEIGHT )) );
+ xPropSet->setPropertyValue( UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_DLG ) ) );
+ }
+ { // Label (fixed text) <status>
+ uno::Sequence< beans::NamedValue > aProps(1);
+
+ setProperty( aProps, 0, UNISTRING("Label"), uno::Any( msStatusFL ) );
+
+ insertControlModel( xControlModel, FIXED_TEXT_MODEL, UNISTRING( "fixedLineStatus" ),
+ awt::Rectangle( DIALOG_BORDER+1, DIALOG_BORDER, EDIT_WIDTH-2, LABEL_HEIGHT ),
+ aProps );
+ }
+ { // box around <status> text
+ uno::Sequence< beans::NamedValue > aProps;
+
+ insertControlModel( xControlModel, GROUP_BOX_MODEL, UNISTRING( "StatusBox" ),
+ awt::Rectangle( DIALOG_BORDER, DIALOG_BORDER + LABEL_HEIGHT, EDIT_WIDTH, BOX_HEIGHT1 - LABEL_HEIGHT ),
+ aProps );
+ }
+ { // Text (multiline edit) <status>
+ uno::Sequence< beans::NamedValue > aProps(7);
+
+ setProperty( aProps, 0, UNISTRING("Text"), uno::Any( substVariables(msChecking) ) );
+ setProperty( aProps, 1, UNISTRING("Border"), uno::Any( sal_Int16( 0 ) ) );
+ setProperty( aProps, 2, UNISTRING("PaintTransparent"), uno::Any( true ) );
+ setProperty( aProps, 3, UNISTRING("MultiLine"), uno::Any( true ) );
+ setProperty( aProps, 4, UNISTRING("ReadOnly"), uno::Any( true ) );
+ setProperty( aProps, 5, UNISTRING("AutoVScroll"), uno::Any( true ) );
+ setProperty( aProps, 6, UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_STATUS ) ) );
+
+ insertControlModel( xControlModel, EDIT_FIELD_MODEL, TEXT_STATUS,
+ awt::Rectangle( DIALOG_BORDER + TEXT_OFFSET,
+ DIALOG_BORDER + LABEL_HEIGHT + TEXT_OFFSET,
+ EDIT_WIDTH - 2*TEXT_OFFSET,
+ BOX_HEIGHT1 - 4*TEXT_OFFSET - LABEL_HEIGHT ),
+ aProps );
+ }
+ { // Text (edit) <percent>
+ uno::Sequence< beans::NamedValue > aProps(4);
+
+ setProperty( aProps, 0, UNISTRING("Text"), uno::Any( msPercent ) );
+ setProperty( aProps, 1, UNISTRING("Border"), uno::Any( sal_Int16( 0 ) ) );
+ setProperty( aProps, 2, UNISTRING("PaintTransparent"), uno::Any( true ) );
+ setProperty( aProps, 3, UNISTRING("ReadOnly"), uno::Any( true ) );
+
+ insertControlModel( xControlModel, EDIT_FIELD_MODEL, TEXT_PERCENT,
+ awt::Rectangle( PROGRESS_X_POS + PROGRESS_WIDTH + DIALOG_BORDER,
+ PROGRESS_Y_POS,
+ EDIT_WIDTH - PROGRESS_WIDTH - BUTTON_WIDTH - 2*DIALOG_BORDER,
+ LABEL_HEIGHT ),
+ aProps );
+ }
+ { // pause button
+ uno::Sequence< beans::NamedValue > aProps(5);
+
+ setProperty( aProps, 0, UNISTRING("DefaultButton"), uno::Any( false ) );
+ setProperty( aProps, 1, UNISTRING("Enabled"), uno::Any( true ) );
+ setProperty( aProps, 2, UNISTRING("PushButtonType"), uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) );
+ setProperty( aProps, 3, UNISTRING("Label"), uno::Any( msPauseBtn ) );
+ setProperty( aProps, 4, UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_PAUSE ) ) );
+
+ insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[PAUSE_BUTTON],
+ awt::Rectangle( BOX1_BTN_X, BOX1_BTN_Y, BUTTON_WIDTH, BUTTON_HEIGHT ),
+ aProps );
+ }
+ { // resume button
+ uno::Sequence< beans::NamedValue > aProps(5);
+
+ setProperty( aProps, 0, UNISTRING("DefaultButton"), uno::Any( false ) );
+ setProperty( aProps, 1, UNISTRING("Enabled"), uno::Any( true ) );
+ setProperty( aProps, 2, UNISTRING("PushButtonType"), uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) );
+ setProperty( aProps, 3, UNISTRING("Label"), uno::Any( msResumeBtn ) );
+ setProperty( aProps, 4, UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_RESUME ) ) );
+
+ insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[RESUME_BUTTON],
+ awt::Rectangle( BOX1_BTN_X,
+ BOX1_BTN_Y + BUTTON_Y_OFFSET + BUTTON_HEIGHT,
+ BUTTON_WIDTH,
+ BUTTON_HEIGHT ),
+ aProps );
+ }
+ { // abort button
+ uno::Sequence< beans::NamedValue > aProps(5);
+
+ setProperty( aProps, 0, UNISTRING("DefaultButton"), uno::Any( false ) );
+ setProperty( aProps, 1, UNISTRING("Enabled"), uno::Any( true ) );
+ setProperty( aProps, 2, UNISTRING("PushButtonType"), uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) );
+ setProperty( aProps, 3, UNISTRING("Label"), uno::Any( msCancelBtn ) );
+ setProperty( aProps, 4, UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_CANCEL ) ) );
+
+ insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[CANCEL_BUTTON],
+ awt::Rectangle( BOX1_BTN_X,
+ BOX1_BTN_Y + (2*(BUTTON_HEIGHT+BUTTON_Y_OFFSET)),
+ BUTTON_WIDTH,
+ BUTTON_HEIGHT ),
+ aProps );
+ }
+ { // Label (FixedText) <description>
+ uno::Sequence< beans::NamedValue > aProps(1);
+
+ setProperty( aProps, 0, UNISTRING("Label"), uno::Any( msDescription ) );
+
+ insertControlModel( xControlModel, FIXED_TEXT_MODEL, UNISTRING( "fixedTextDescription" ),
+ awt::Rectangle( DIALOG_BORDER+1, LABEL_Y_POS, EDIT_WIDTH-2, LABEL_HEIGHT ),
+ aProps );
+ }
+ { // box around <description> text
+ uno::Sequence< beans::NamedValue > aProps;
+
+ insertControlModel( xControlModel, GROUP_BOX_MODEL, UNISTRING( "DescriptionBox" ),
+ awt::Rectangle( DIALOG_BORDER, EDIT2_Y_POS, EDIT_WIDTH, BOX_HEIGHT2 ),
+ aProps );
+ }
+ { // Text (MultiLineEdit) <description>
+ uno::Sequence< beans::NamedValue > aProps(7);
+
+ setProperty( aProps, 0, UNISTRING("Text"), uno::Any( rtl::OUString() ) );
+ setProperty( aProps, 1, UNISTRING("Border"), uno::Any( sal_Int16( 0 ) ) );
+ setProperty( aProps, 2, UNISTRING("PaintTransparent"), uno::Any( true ) );
+ setProperty( aProps, 3, UNISTRING("MultiLine"), uno::Any( true ) );
+ setProperty( aProps, 4, UNISTRING("ReadOnly"), uno::Any( true ) );
+ setProperty( aProps, 5, UNISTRING("AutoVScroll"), uno::Any( true ) );
+ setProperty( aProps, 6, UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_DESCRIPTION ) ) );
+
+ insertControlModel( xControlModel, EDIT_FIELD_MODEL, TEXT_DESCRIPTION,
+ awt::Rectangle( DIALOG_BORDER + TEXT_OFFSET,
+ EDIT2_Y_POS + 2*TEXT_OFFSET,
+ EDIT_WIDTH - 3*TEXT_OFFSET,
+ BOX_HEIGHT2 - 3*TEXT_OFFSET ),
+ aProps );
+ }
+ { // @see awt/UnoControlFixedLineModel.idl
+ uno::Sequence< beans::NamedValue > aProps(1);
+
+ setProperty( aProps, 0, UNISTRING("Orientation"), uno::Any( sal_Int32( 0 ) ) );
+
+ insertControlModel( xControlModel, FIXED_LINE_MODEL, UNISTRING("fixedLine"),
+ awt::Rectangle( 0, BUTTON_BAR_Y_POS, DIALOG_WIDTH, 5 ),
+ aProps );
+ }
+ { // close button // @see awt/UnoControlButtonModel.idl
+ uno::Sequence< beans::NamedValue > aProps(5);
+
+ setProperty( aProps, 0, UNISTRING("DefaultButton"), uno::Any( false ) );
+ setProperty( aProps, 1, UNISTRING("Enabled"), uno::Any( true ) );
+ // [property] short PushButtonType
+ // with own "ButtonActionListener"
+ setProperty( aProps, 2, UNISTRING("PushButtonType"), uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) );
+ // with default ActionListener => endDialog().
+ // setProperty( aProps, 2, UNISTRING("PushButtonType"), uno::Any( sal_Int16(awt::PushButtonType_CANCEL) ) );
+ // [property] string Label // only if PushButtonType_STANDARD
+ setProperty( aProps, 3, UNISTRING("Label"), uno::Any( msClose ) );
+ setProperty( aProps, 4, UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_CLOSE ) ) );
+
+ insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[ CLOSE_BUTTON ],
+ awt::Rectangle( CLOSE_BTN_X, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ),
+ aProps );
+ }
+ { // install button
+ uno::Sequence< beans::NamedValue > aProps(5);
+
+ setProperty( aProps, 0, UNISTRING("DefaultButton"), uno::Any( false ) );
+ setProperty( aProps, 1, UNISTRING("Enabled"), uno::Any( true ) );
+ setProperty( aProps, 2, UNISTRING("PushButtonType"), uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) );
+ setProperty( aProps, 3, UNISTRING("Label"), uno::Any( msInstall ) );
+ setProperty( aProps, 4, UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_INSTALL ) ) );
+
+ insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[INSTALL_BUTTON],
+ awt::Rectangle( INSTALL_BTN_X, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ),
+ aProps );
+ }
+ { // download button
+ uno::Sequence< beans::NamedValue > aProps(5);
+
+ setProperty( aProps, 0, UNISTRING("DefaultButton"), uno::Any( false ) );
+ setProperty( aProps, 1, UNISTRING("Enabled"), uno::Any( true ) );
+ setProperty( aProps, 2, UNISTRING("PushButtonType"), uno::Any( sal_Int16(awt::PushButtonType_STANDARD) ) );
+ setProperty( aProps, 3, UNISTRING("Label"), uno::Any( msDownload ) );
+ setProperty( aProps, 4, UNISTRING("HelpURL"), uno::Any( UNISTRING( "HID:" ) + rtl::OUString::valueOf( (sal_Int32) HID_CHECK_FOR_UPD_DOWNLOAD ) ) );
+
+ insertControlModel ( xControlModel, BUTTON_MODEL, msButtonIDs[DOWNLOAD_BUTTON],
+ awt::Rectangle( DOWNLOAD_BTN_X, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ),
+ aProps );
+ }
+ { // help button
+ uno::Sequence< beans::NamedValue > aProps(3);
+
+ setProperty( aProps, 0, UNISTRING("DefaultButton"), uno::Any( false ) );
+ setProperty( aProps, 1, UNISTRING("Enabled"), uno::Any( true ) );
+ setProperty( aProps, 2, UNISTRING("PushButtonType"), uno::Any( sal_Int16(awt::PushButtonType_HELP) ) );
+
+ insertControlModel( xControlModel, BUTTON_MODEL, msButtonIDs[HELP_BUTTON],
+ awt::Rectangle( DIALOG_BORDER, BUTTON_Y_POS, BUTTON_WIDTH, BUTTON_HEIGHT ),
+ aProps );
+ }
+ { // @see awt/UnoControlThrobberModel.idl
+ uno::Sequence< beans::NamedValue > aProps;
+
+ insertControlModel( xControlModel, UNISTRING("com.sun.star.awt.UnoThrobberControlModel"), CTRL_THROBBER,
+ awt::Rectangle( THROBBER_X_POS, THROBBER_Y_POS, THROBBER_WIDTH, THROBBER_HEIGHT),
+ aProps );
+ }
+ { // @see awt/UnoControlProgressBarModel.idl
+ uno::Sequence< beans::NamedValue > aProps(4);
+ setProperty( aProps, 0, UNISTRING("Enabled"), uno::Any( true ) );
+ setProperty( aProps, 1, UNISTRING("ProgressValue"), uno::Any( sal_Int32( 0 ) ) );
+ setProperty( aProps, 2, UNISTRING("ProgressValueMax"), uno::Any( sal_Int32( 100 ) ) );
+ setProperty( aProps, 3, UNISTRING("ProgressValueMin"), uno::Any( sal_Int32( 0 ) ) );
+
+ insertControlModel( xControlModel, UNISTRING("com.sun.star.awt.UnoControlProgressBarModel"), CTRL_PROGRESS,
+ awt::Rectangle( PROGRESS_X_POS, PROGRESS_Y_POS, PROGRESS_WIDTH, PROGRESS_HEIGHT ),
+ aProps);
+ }
+
+ uno::Reference< awt::XControl > xControl(
+ xFactory->createInstanceWithContext( UNISTRING("com.sun.star.awt.UnoControlDialog"), mxContext),
+ uno::UNO_QUERY_THROW );
+ xControl->setModel( xControlModel );
+
+ if ( mbVisible == false )
+ {
+ uno::Reference< awt::XWindow > xWindow( xControl, uno::UNO_QUERY );
+
+ if ( xWindow.is() )
+ xWindow->setVisible( false );
+ }
+
+ xControl->createPeer( NULL, NULL );
+ {
+ uno::Reference< awt::XControlContainer > xContainer (xControl, uno::UNO_QUERY);
+ for ( int i = 0; i < HELP_BUTTON; i++ )
+ {
+ uno::Reference< awt::XButton > xButton ( xContainer->getControl( msButtonIDs[i] ), uno::UNO_QUERY);
+ if (xButton.is())
+ {
+ xButton->setActionCommand( msButtonIDs[i] );
+ xButton->addActionListener( this );
+ }
+ }
+ }
+
+ mxUpdDlg.set( xControl, uno::UNO_QUERY_THROW );
+ mnLastCtrlState = -1;
+}
diff --git a/extensions/source/update/check/updatehdl.hrc b/extensions/source/update/check/updatehdl.hrc
new file mode 100644
index 000000000000..906a2e2a5db7
--- /dev/null
+++ b/extensions/source/update/check/updatehdl.hrc
@@ -0,0 +1,83 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatehdl.hrc,v $
+ * $Revision: 1.4 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #define RID_UPDATE_HDL_START 1200
+
+ #define RID_UPDATE_STR_CHECKING RID_UPDATE_HDL_START + 1
+ #define RID_UPDATE_STR_NO_UPD_FOUND RID_UPDATE_HDL_START + 2
+ #define RID_UPDATE_STR_UPD_FOUND RID_UPDATE_HDL_START + 3
+ #define RID_UPDATE_STR_DLG_TITLE RID_UPDATE_HDL_START + 4
+ #define RID_UPDATE_STR_DOWNLOAD_ERR RID_UPDATE_HDL_START + 5
+ #define RID_UPDATE_STR_DOWNLOAD_WARN RID_UPDATE_HDL_START + 6
+ #define RID_UPDATE_STR_DOWNLOADING RID_UPDATE_HDL_START + 7
+ #define RID_UPDATE_STR_READY_INSTALL RID_UPDATE_HDL_START + 8
+ #define RID_UPDATE_STR_CANCEL_TITLE RID_UPDATE_HDL_START + 9
+ #define RID_UPDATE_STR_CANCEL_DOWNLOAD RID_UPDATE_HDL_START + 10
+ #define RID_UPDATE_STR_BEGIN_INSTALL RID_UPDATE_HDL_START + 11
+ #define RID_UPDATE_STR_INSTALL_NOW RID_UPDATE_HDL_START + 12
+ #define RID_UPDATE_STR_INSTALL_LATER RID_UPDATE_HDL_START + 13
+ #define RID_UPDATE_STR_CHECKING_ERR RID_UPDATE_HDL_START + 14
+ #define RID_UPDATE_STR_OVERWRITE_WARNING RID_UPDATE_HDL_START + 15
+ #define RID_UPDATE_STR_DOWNLOAD_PAUSE RID_UPDATE_HDL_START + 16
+ #define RID_UPDATE_STR_DOWNLOAD_UNAVAIL RID_UPDATE_HDL_START + 17
+ #define RID_UPDATE_STR_PERCENT RID_UPDATE_HDL_START + 18
+ #define RID_UPDATE_STR_DOWNLOAD_DESCR RID_UPDATE_HDL_START + 19
+ #define RID_UPDATE_STR_INSTALL_ERROR RID_UPDATE_HDL_START + 20
+
+ #define RID_UPDATE_FT_DESCRIPTION RID_UPDATE_HDL_START + 25
+ #define RID_UPDATE_FT_STATUS RID_UPDATE_HDL_START + 26
+
+ #define RID_UPDATE_BTN_CLOSE RID_UPDATE_HDL_START + 30
+ #define RID_UPDATE_BTN_DOWNLOAD RID_UPDATE_HDL_START + 31
+ #define RID_UPDATE_BTN_INSTALL RID_UPDATE_HDL_START + 32
+ #define RID_UPDATE_BTN_PAUSE RID_UPDATE_HDL_START + 33
+ #define RID_UPDATE_BTN_RESUME RID_UPDATE_HDL_START + 34
+ #define RID_UPDATE_BTN_CANCEL RID_UPDATE_HDL_START + 35
+
+ #define RID_UPDATE_BUBBLE_TEXT_START RID_UPDATE_HDL_START + 40
+ #define RID_UPDATE_BUBBLE_UPDATE_AVAIL RID_UPDATE_BUBBLE_TEXT_START + 0
+ #define RID_UPDATE_BUBBLE_UPDATE_NO_DOWN RID_UPDATE_BUBBLE_TEXT_START + 1
+ #define RID_UPDATE_BUBBLE_AUTO_START RID_UPDATE_BUBBLE_TEXT_START + 2
+ #define RID_UPDATE_BUBBLE_DOWNLOADING RID_UPDATE_BUBBLE_TEXT_START + 3
+ #define RID_UPDATE_BUBBLE_DOWNLOAD_PAUSED RID_UPDATE_BUBBLE_TEXT_START + 4
+ #define RID_UPDATE_BUBBLE_ERROR_DOWNLOADING RID_UPDATE_BUBBLE_TEXT_START + 5
+ #define RID_UPDATE_BUBBLE_DOWNLOAD_AVAIL RID_UPDATE_BUBBLE_TEXT_START + 6
+ #define RID_UPDATE_BUBBLE_EXT_UPD_AVAIL RID_UPDATE_BUBBLE_TEXT_START + 7
+
+ #define RID_UPDATE_BUBBLE_T_TEXT_START RID_UPDATE_HDL_START + 50
+ #define RID_UPDATE_BUBBLE_T_UPDATE_AVAIL RID_UPDATE_BUBBLE_T_TEXT_START + 0
+ #define RID_UPDATE_BUBBLE_T_UPDATE_NO_DOWN RID_UPDATE_BUBBLE_T_TEXT_START + 1
+ #define RID_UPDATE_BUBBLE_T_AUTO_START RID_UPDATE_BUBBLE_T_TEXT_START + 2
+ #define RID_UPDATE_BUBBLE_T_DOWNLOADING RID_UPDATE_BUBBLE_T_TEXT_START + 3
+ #define RID_UPDATE_BUBBLE_T_DOWNLOAD_PAUSED RID_UPDATE_BUBBLE_T_TEXT_START + 4
+ #define RID_UPDATE_BUBBLE_T_ERROR_DOWNLOADING RID_UPDATE_BUBBLE_T_TEXT_START + 5
+ #define RID_UPDATE_BUBBLE_T_DOWNLOAD_AVAIL RID_UPDATE_BUBBLE_T_TEXT_START + 6
+ #define RID_UPDATE_BUBBLE_T_EXT_UPD_AVAIL RID_UPDATE_BUBBLE_T_TEXT_START + 7
+
diff --git a/extensions/source/update/check/updatehdl.hxx b/extensions/source/update/check/updatehdl.hxx
new file mode 100644
index 000000000000..9b33098f30f1
--- /dev/null
+++ b/extensions/source/update/check/updatehdl.hxx
@@ -0,0 +1,218 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatehdl.hxx,v $
+ * $Revision: 1.5.94.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_UPDATE_HDL_HXX
+#define INCLUDED_UPDATE_HDL_HXX
+
+#include "boost/utility.hpp"
+#include <osl/mutex.hxx>
+#include "com/sun/star/uno/Any.h"
+#ifndef _COM_SUN_STAR_UNO_REFERENCE_HPP_
+#include "com/sun/star/uno/Reference.h"
+#endif
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "com/sun/star/awt/Rectangle.hpp"
+#include "com/sun/star/awt/XActionListener.hpp"
+#include "com/sun/star/awt/XControlModel.hpp"
+#include "com/sun/star/awt/XDialog.hpp"
+#include "com/sun/star/awt/XTopWindowListener.hpp"
+#include "com/sun/star/beans/NamedValue.hpp"
+#include "com/sun/star/frame/XTerminateListener.hpp"
+#include <com/sun/star/resource/XResourceBundle.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include "cppuhelper/implbase4.hxx"
+
+#include "actionlistener.hxx"
+
+enum DialogControls
+{
+ CANCEL_BUTTON = 0,
+ PAUSE_BUTTON,
+ RESUME_BUTTON,
+ INSTALL_BUTTON,
+ DOWNLOAD_BUTTON,
+ CLOSE_BUTTON,
+ HELP_BUTTON,
+ BUTTON_COUNT,
+ THROBBER_CTRL,
+ PROGRESS_CTRL
+};
+
+enum UpdateState {
+ UPDATESTATE_CHECKING = 0,
+ UPDATESTATE_ERROR_CHECKING,
+ UPDATESTATE_NO_UPDATE_AVAIL,
+ UPDATESTATE_UPDATE_AVAIL,
+ UPDATESTATE_UPDATE_NO_DOWNLOAD,
+ UPDATESTATE_AUTO_START,
+ UPDATESTATE_DOWNLOADING,
+ UPDATESTATE_DOWNLOAD_PAUSED,
+ UPDATESTATE_ERROR_DOWNLOADING,
+ UPDATESTATE_DOWNLOAD_AVAIL,
+ UPDATESTATE_EXT_UPD_AVAIL,
+ UPDATESTATES_COUNT
+};
+
+class UpdateHandler : ::boost::noncopyable,
+ public cppu::WeakImplHelper4< com::sun::star::awt::XActionListener,
+ com::sun::star::awt::XTopWindowListener,
+ com::sun::star::task::XInteractionHandler,
+ com::sun::star::frame::XTerminateListener >
+{
+private:
+ com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > mxContext;
+ com::sun::star::uno::Reference< com::sun::star::awt::XDialog > mxUpdDlg;
+ com::sun::star::uno::Reference< com::sun::star::task::XInteractionHandler > mxInteractionHdl;
+ rtl::Reference< IActionListener > mxActionListener;
+
+ UpdateState meCurState;
+ UpdateState meLastState;
+ sal_Int32 mnPercent;
+ short mnLastCtrlState;
+ bool mbDownloadBtnHasDots;
+ bool mbVisible;
+ bool mbStringsLoaded;
+ bool mbMinimized;
+ bool mbListenerAdded;
+
+ osl::Mutex maMutex;
+
+ rtl::OUString msNextVersion;
+ rtl::OUString msDownloadPath;
+ rtl::OUString msDownloadFile;
+ rtl::OUString msDescriptionMsg;
+ rtl::OUString msChecking; // RID_UPDATE_STR_CHECKING
+ rtl::OUString msCheckingError; // RID_UPDATE_STR_CHECKING_ERR
+ rtl::OUString msNoUpdFound; // RID_UPDATE_STR_NO_UPD_FOUND
+ rtl::OUString msUpdFound; // RID_UPDATE_STR_UPD_FOUND
+ rtl::OUString msDlgTitle; // RID_UPDATE_STR_DLG_TITLE
+ rtl::OUString msDownloadPause; // RID_UPDATE_STR_DOWNLOAD_PAUSE
+ rtl::OUString msDownloadError; // RID_UPDATE_STR_DOWNLOAD_ERR
+ rtl::OUString msDownloadWarning; // RID_UPDATE_STR_DOWNLOAD_WARN
+ rtl::OUString msDownloadDescr; // RID_UPDATE_STR_DOWNLOAD_WARN
+ rtl::OUString msDownloadNotAvail; // RID_UPDATE_STR_DOWNLOAD_UNAVAIL
+ rtl::OUString msDownloading; // RID_UPDATE_STR_DOWNLOADING
+ rtl::OUString msReady2Install; // RID_UPDATE_STR_READY_INSTALL
+ rtl::OUString msCancelTitle; // RID_UPDATE_STR_CANCEL_TITLE
+ rtl::OUString msCancelMessage; // RID_UPDATE_STR_CANCEL_DOWNLOAD
+ rtl::OUString msInstallMessage; // RID_UPDATE_STR_BEGIN_INSTALL
+ rtl::OUString msInstallNow; // RID_UPDATE_STR_INSTALL_NOW
+ rtl::OUString msInstallLater; // RID_UPDATE_STR_INSTALL_LATER
+ rtl::OUString msInstallError; // RID_UPDATE_STR_INSTALL_ERROR
+ rtl::OUString msOverwriteWarning; // RID_UPDATE_STR_OVERWRITE_WARNING
+ rtl::OUString msPercent; // RID_UPDATE_STR_PERCENT
+ rtl::OUString msStatusFL; // RID_UPDATE_FT_STATUS
+ rtl::OUString msDescription; // RID_UPDATE_FT_DESCRIPTION
+ rtl::OUString msClose; // RID_UPDATE_BTN_CLOSE
+ rtl::OUString msDownload; // RID_UPDATE_BTN_DOWNLOAD
+ rtl::OUString msInstall; // RID_UPDATE_BTN_INSTALL
+ rtl::OUString msPauseBtn; // RID_UPDATE_BTN_PAUSE
+ rtl::OUString msResumeBtn; // RID_UPDATE_BTN_RESUME
+ rtl::OUString msCancelBtn; // RID_UPDATE_BTN_CANCEL
+ rtl::OUString msButtonIDs[ BUTTON_COUNT ];
+ rtl::OUString msBubbleTexts[ UPDATESTATES_COUNT ];
+ rtl::OUString msBubbleTitles[ UPDATESTATES_COUNT ];
+
+ void createDialog();
+ void updateState( UpdateState eNewState );
+ void startThrobber( bool bStart = true );
+ void setControlProperty( const rtl::OUString &rCtrlName,
+ const rtl::OUString &rPropName,
+ const com::sun::star::uno::Any &rPropValue );
+ void showControl( const rtl::OUString &rCtrlName, bool bShow = true );
+ void showControls( short nControls );
+ void focusControl( DialogControls eID );
+ void enableControls( short nCtrlState );
+ void setDownloadBtnLabel( bool bAppendDots );
+ void loadStrings();
+ rtl::OUString loadString( const com::sun::star::uno::Reference< com::sun::star::resource::XResourceBundle > xBundle,
+ sal_Int32 nResourceId ) const;
+ rtl::OUString substVariables( const rtl::OUString &rSource ) const;
+ static void setProperty( com::sun::star::uno::Sequence< com::sun::star::beans::NamedValue > &rProps,
+ const int nIndex, const rtl::OUString &rPropName, const com::sun::star::uno::Any &rPropValue )
+ { rProps[ nIndex ].Name = rPropName; rProps[ nIndex ].Value = rPropValue; }
+ static void insertControlModel( com::sun::star::uno::Reference< com::sun::star::awt::XControlModel > & rxDialogModel,
+ rtl::OUString const & rServiceName,
+ rtl::OUString const & rControlName,
+ com::sun::star::awt::Rectangle const & rPosSize,
+ com::sun::star::uno::Sequence< com::sun::star::beans::NamedValue > const & rProps );
+
+ void setFullVersion( rtl::OUString& rString );
+ void searchAndReplaceAll( rtl::OUString &rText, const rtl::OUString &rWhat, const rtl::OUString &rWith ) const;
+
+public:
+ UpdateHandler( const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > & rxContext,
+ const rtl::Reference< IActionListener > & rxActionListener );
+ virtual ~UpdateHandler();
+
+ bool isVisible() const;
+ bool isMinimized() const { return mbMinimized; }
+ void setVisible( bool bVisible = true );
+ void setProgress( sal_Int32 nPercent );
+ void setNextVersion( const rtl::OUString &rNextVersion ) { msNextVersion = rNextVersion; }
+ void setDownloadPath( const rtl::OUString &rPath ) { msDownloadPath = rPath; }
+ void setDownloadFile( const rtl::OUString &rPath );
+ void setErrorMessage( const rtl::OUString &rErrorMsg );
+ void setDescription( const rtl::OUString &rDescription ){ msDescriptionMsg = rDescription; }
+
+ void setState( UpdateState eState );
+ rtl::OUString getBubbleText( UpdateState eState );
+ rtl::OUString getBubbleTitle( UpdateState eState );
+ rtl::OUString getDefaultInstErrMsg();
+ bool showWarning( const rtl::OUString &rWarning ) const;
+ bool showOverwriteWarning() const;
+
+ // Allows runtime exceptions to be thrown by const methods
+ inline SAL_CALL operator com::sun::star::uno::Reference< com::sun::star::uno::XInterface > () const
+ { return const_cast< cppu::OWeakObject * > (static_cast< cppu::OWeakObject const * > (this)); };
+
+ // XActionListener
+ virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject &rObj ) throw( com::sun::star::uno::RuntimeException );
+ virtual void SAL_CALL actionPerformed( com::sun::star::awt::ActionEvent const & rEvent) throw( com::sun::star::uno::RuntimeException );
+
+ // XTopWindowListener
+ virtual void SAL_CALL windowOpened( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL windowClosing( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL windowClosed( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL windowMinimized( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL windowNormalized( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL windowActivated( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL windowDeactivated( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
+
+ // XInteractionHandler
+ virtual void SAL_CALL handle( const com::sun::star::uno::Reference< com::sun::star::task::XInteractionRequest >& Request )
+ throw( com::sun::star::uno::RuntimeException );
+
+ // XTerminateListener
+ virtual void SAL_CALL queryTermination( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::frame::TerminationVetoException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL notifyTermination( const ::com::sun::star::lang::EventObject& e ) throw (::com::sun::star::uno::RuntimeException);
+};
+
+#endif /* INCLUDED_UPDATE_HDL_HXX */
diff --git a/extensions/source/update/check/updatehdl.src b/extensions/source/update/check/updatehdl.src
new file mode 100644
index 000000000000..7e846d3d9185
--- /dev/null
+++ b/extensions/source/update/check/updatehdl.src
@@ -0,0 +1,252 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatehdl.src,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "updatehdl.hrc"
+
+String RID_UPDATE_STR_CHECKING
+{
+ Text [ en-US ] = "Checking...";
+};
+
+String RID_UPDATE_STR_CHECKING_ERR
+{
+ Text [ en-US ] = "Checking for an update failed.";
+};
+
+String RID_UPDATE_STR_NO_UPD_FOUND
+{
+ Text [ en-US ] = "%PRODUCTNAME %PRODUCTVERSION is up to date.";
+};
+
+String RID_UPDATE_STR_UPD_FOUND
+{
+ Text [ en-US ] = "%PRODUCTNAME %NEXTVERSION is available.\n\nThe installed version is %PRODUCTNAME %PRODUCTVERSION.\n\nNote: Before downloading an update, please ensure that you have sufficient access rights to install it.\nA password, usually the administrator's or root password, may be required.";
+};
+
+String RID_UPDATE_STR_DLG_TITLE
+{
+ Text [ en-US ] = "Check for Updates";
+};
+
+String RID_UPDATE_STR_DOWNLOAD_PAUSE
+{
+ Text [ en-US ] = "Downloading %PRODUCTNAME %NEXTVERSION paused at...";
+};
+
+String RID_UPDATE_STR_DOWNLOAD_ERR
+{
+ Text [ en-US ] = "Downloading %PRODUCTNAME %NEXTVERSION stalled at";
+};
+
+String RID_UPDATE_STR_DOWNLOAD_WARN
+{
+ Text [ en-US ] = "The download location is: %DOWNLOAD_PATH.\n\nUnder Tools – Options... - %PRODUCTNAME – Online Update you can change the download location.";
+};
+
+String RID_UPDATE_STR_DOWNLOAD_DESCR
+{
+ Text [ en-US ] = "%FILE_NAME has been downloaded to %DOWNLOAD_PATH.";
+};
+
+String RID_UPDATE_STR_DOWNLOAD_UNAVAIL
+{
+ Text [ en-US ] = "The automatic download of the update is currently not available.\n\nClick 'Download...' to download %PRODUCTNAME %NEXTVERSION manually from the web site.";
+};
+
+String RID_UPDATE_STR_DOWNLOADING
+{
+ Text [ en-US ] = "Downloading %PRODUCTNAME %NEXTVERSION...";
+};
+
+String RID_UPDATE_STR_READY_INSTALL
+{
+ Text [ en-US ] = "Download of %PRODUCTNAME %NEXTVERSION completed. Ready for installation.";
+};
+
+String RID_UPDATE_STR_CANCEL_TITLE
+{
+ Text [ en-US ] = "%PRODUCTNAME %PRODUCTVERSION";
+};
+
+String RID_UPDATE_STR_CANCEL_DOWNLOAD
+{
+ Text [ en-US ] = "Do you really want to cancel the download?";
+};
+
+String RID_UPDATE_STR_BEGIN_INSTALL
+{
+ Text [ en-US ] = "To install the update, %PRODUCTNAME %PRODUCTVERSION needs to be closed. Do you want to install the update now?";
+};
+
+String RID_UPDATE_STR_INSTALL_NOW
+{
+ Text [ en-US ] = "Install ~now";
+};
+
+String RID_UPDATE_STR_INSTALL_LATER
+{
+ Text [ en-US ] = "Install ~later";
+};
+
+String RID_UPDATE_STR_INSTALL_ERROR
+{
+ Text [ en-US ] = "Could not run the installer application, please run %FILE_NAME in %DOWNLOAD_PATH manually.";
+};
+
+String RID_UPDATE_STR_OVERWRITE_WARNING
+{
+ Text [ en-US ] = "A file with that name already exists! Do you want to overwrite the existing file?";
+};
+
+String RID_UPDATE_STR_PERCENT
+{
+ Text [ en-US ] = "%PERCENT%";
+};
+
+String RID_UPDATE_FT_STATUS
+{
+ Text [ en-US ] = "Status";
+};
+
+String RID_UPDATE_FT_DESCRIPTION
+{
+ Text [ en-US ] = "Description";
+};
+
+String RID_UPDATE_BTN_CLOSE
+{
+ Text [ en-US ] = "Close";
+};
+
+String RID_UPDATE_BTN_DOWNLOAD
+{
+ Text [ en-US ] = "~Download";
+};
+
+String RID_UPDATE_BTN_INSTALL
+{
+ Text [ en-US ] = "~Install";
+};
+
+String RID_UPDATE_BTN_PAUSE
+{
+ Text [ en-US ] = "~Pause";
+};
+
+String RID_UPDATE_BTN_RESUME
+{
+ Text [ en-US ] = "~Resume";
+};
+
+String RID_UPDATE_BTN_CANCEL
+{
+ Text [ en-US ] = "Cancel";
+};
+
+String RID_UPDATE_BUBBLE_T_UPDATE_AVAIL
+{
+ Text [ en-US ] = "%PRODUCTNAME update available";
+};
+
+String RID_UPDATE_BUBBLE_UPDATE_AVAIL
+{
+ Text [ en-US ] = "Click here to start the download.";
+};
+
+String RID_UPDATE_BUBBLE_T_UPDATE_NO_DOWN
+{
+ Text [ en-US ] = "%PRODUCTNAME update available";
+};
+
+String RID_UPDATE_BUBBLE_UPDATE_NO_DOWN
+{
+ Text [ en-US ] = "Click here for more information.";
+};
+
+String RID_UPDATE_BUBBLE_T_AUTO_START
+{
+ Text [ en-US ] = "%PRODUCTNAME update available";
+};
+
+String RID_UPDATE_BUBBLE_AUTO_START
+{
+ Text [ en-US ] = "Download of update begins.";
+};
+
+String RID_UPDATE_BUBBLE_T_DOWNLOADING
+{
+ Text [ en-US ] = "Download of update in progress";
+};
+
+String RID_UPDATE_BUBBLE_DOWNLOADING
+{
+ Text [ en-US ] = "";
+};
+
+String RID_UPDATE_BUBBLE_T_DOWNLOAD_PAUSED
+{
+ Text [ en-US ] = "Download of update paused";
+};
+
+String RID_UPDATE_BUBBLE_DOWNLOAD_PAUSED
+{
+ Text [ en-US ] = "Click here to resume.";
+};
+
+String RID_UPDATE_BUBBLE_T_ERROR_DOWNLOADING
+{
+ Text [ en-US ] = "Download of update stalled";
+};
+
+String RID_UPDATE_BUBBLE_ERROR_DOWNLOADING
+{
+ Text [ en-US ] = "Click here for more information.";
+};
+
+String RID_UPDATE_BUBBLE_T_DOWNLOAD_AVAIL
+{
+ Text [ en-US ] = "Download of update completed";
+};
+
+String RID_UPDATE_BUBBLE_DOWNLOAD_AVAIL
+{
+ Text [ en-US ] = "Click here to start the installation.";
+};
+
+String RID_UPDATE_BUBBLE_T_EXT_UPD_AVAIL
+{
+ Text [ en-US ] = "Updates for extensions available";
+};
+
+String RID_UPDATE_BUBBLE_EXT_UPD_AVAIL
+{
+ Text [ en-US ] = "Click here for more information.";
+};
+
diff --git a/extensions/source/update/check/updateinfo.hxx b/extensions/source/update/check/updateinfo.hxx
new file mode 100644
index 000000000000..3de0fcbea24e
--- /dev/null
+++ b/extensions/source/update/check/updateinfo.hxx
@@ -0,0 +1,89 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updateinfo.hxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _UPDATE_INFO_INCLUDED_
+#define _UPDATE_INFO_INCLUDED_
+
+#include <rtl/ustring.hxx>
+#include <vector>
+
+struct DownloadSource
+{
+ bool IsDirect;
+ rtl::OUString URL;
+
+ DownloadSource(bool bIsDirect, const rtl::OUString& aURL) : IsDirect(bIsDirect), URL(aURL) {};
+ DownloadSource(const DownloadSource& ds) : IsDirect(ds.IsDirect), URL(ds.URL) {};
+
+ DownloadSource & operator=( const DownloadSource & ds ) { IsDirect = ds.IsDirect; URL = ds.URL; return *this; };
+};
+
+struct ReleaseNote
+{
+ sal_uInt8 Pos;
+ rtl::OUString URL;
+ sal_uInt8 Pos2;
+ rtl::OUString URL2;
+
+ ReleaseNote(sal_uInt8 pos, const rtl::OUString aURL) : Pos(pos), URL(aURL), Pos2(0), URL2() {};
+ ReleaseNote(sal_uInt8 pos, const rtl::OUString aURL, sal_uInt8 pos2, const rtl::OUString aURL2) : Pos(pos), URL(aURL), Pos2(pos2), URL2(aURL2) {};
+
+ ReleaseNote(const ReleaseNote& rn) :Pos(rn.Pos), URL(rn.URL), Pos2(rn.Pos2), URL2(rn.URL2) {};
+ ReleaseNote & operator=( const ReleaseNote& rn) { Pos=rn.Pos; URL=rn.URL; Pos2=rn.Pos2; URL2=rn.URL2; return *this; };
+};
+
+struct UpdateInfo
+{
+ rtl::OUString BuildId;
+ rtl::OUString Version;
+ rtl::OUString Description;
+ std::vector< DownloadSource > Sources;
+ std::vector< ReleaseNote > ReleaseNotes;
+
+ UpdateInfo() : BuildId(), Version(), Description(), Sources(), ReleaseNotes() {};
+ UpdateInfo(const UpdateInfo& ui) : BuildId(ui.BuildId), Version(ui.Version), Description(ui.Description), Sources(ui.Sources), ReleaseNotes(ui.ReleaseNotes) {};
+ inline UpdateInfo & operator=( const UpdateInfo& ui );
+};
+
+UpdateInfo & UpdateInfo::operator=( const UpdateInfo& ui )
+{
+ BuildId = ui.BuildId;
+ Version = ui.Version;
+ Description = ui.Description;
+ Sources = ui.Sources;
+ ReleaseNotes = ui.ReleaseNotes;
+ return *this;
+}
+
+
+// Returns the URL of the release note for the given position
+rtl::OUString getReleaseNote(const UpdateInfo& rInfo, sal_uInt8 pos, bool autoDownloadEnabled=false);
+
+#endif
diff --git a/extensions/source/update/check/updateprotocol.cxx b/extensions/source/update/check/updateprotocol.cxx
new file mode 100644
index 000000000000..2794f299928c
--- /dev/null
+++ b/extensions/source/update/check/updateprotocol.cxx
@@ -0,0 +1,336 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updateprotocol.cxx,v $
+ * $Revision: 1.11.70.1 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+#include <com/sun/star/xml/xpath/XXPathAPI.hpp>
+
+#include "updateprotocol.hxx"
+#include "updatecheckconfig.hxx"
+
+#ifndef _COM_SUN_STAR_DEPLOYMENT_UPDATEINFORMATINENTRY_HPP_
+#include <com/sun/star/deployment/UpdateInformationEntry.hpp>
+#endif
+#include <com/sun/star/deployment/XPackageInformationProvider.hpp>
+
+
+#include <rtl/ref.hxx>
+#include <rtl/uri.hxx>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/bootstrap.hxx>
+#include <osl/process.h>
+
+#include <cppuhelper/implbase1.hxx>
+
+namespace css = com::sun::star ;
+namespace container = css::container ;
+namespace deployment = css::deployment ;
+namespace lang = css::lang ;
+namespace uno = css::uno ;
+namespace task = css::task ;
+namespace xml = css::xml ;
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+//------------------------------------------------------------------------------
+
+static bool
+getBootstrapData(
+ uno::Sequence< ::rtl::OUString > & rRepositoryList,
+ ::rtl::OUString & rBuildID,
+ ::rtl::OUString & rInstallSetID)
+{
+ rBuildID = UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":ProductBuildid}" );
+ rtl::Bootstrap::expandMacros( rBuildID );
+ if ( ! rBuildID.getLength() )
+ return false;
+
+ rInstallSetID = UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateID}" );
+ rtl::Bootstrap::expandMacros( rInstallSetID );
+ if ( ! rInstallSetID.getLength() )
+ return false;
+
+ rtl::OUString aValue( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateURL}" ) );
+ rtl::Bootstrap::expandMacros( aValue );
+
+ if( aValue.getLength() > 0 )
+ {
+ rRepositoryList.realloc(1);
+ rRepositoryList[0] = aValue;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+
+// Returns 'true' if successfully connected to the update server
+bool
+checkForUpdates(
+ UpdateInfo& o_rUpdateInfo,
+ uno::Reference< uno::XComponentContext > const & rxContext,
+ uno::Reference< task::XInteractionHandler > const & rxInteractionHandler,
+ const uno::Reference< deployment::XUpdateInformationProvider >& rUpdateInfoProvider)
+{
+ OSL_TRACE("checking for updates ..\n");
+
+ ::rtl::OUString myArch;
+ ::rtl::OUString myOS;
+
+ rtl::Bootstrap::get(UNISTRING("_OS"), myOS);
+ rtl::Bootstrap::get(UNISTRING("_ARCH"), myArch);
+
+ uno::Sequence< ::rtl::OUString > aRepositoryList;
+ ::rtl::OUString aBuildID;
+ ::rtl::OUString aInstallSetID;
+
+ if( ! ( getBootstrapData(aRepositoryList, aBuildID, aInstallSetID) && (aRepositoryList.getLength() > 0) ) )
+ return false;
+
+ if( !rxContext.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "checkForUpdates: empty component context" ), uno::Reference< uno::XInterface >() );
+
+ OSL_ASSERT( rxContext->getServiceManager().is() );
+
+ // XPath implementation
+ uno::Reference< xml::xpath::XXPathAPI > xXPath(
+ rxContext->getServiceManager()->createInstanceWithContext( UNISTRING( "com.sun.star.xml.xpath.XPathAPI" ), rxContext ),
+ uno::UNO_QUERY_THROW);
+
+ xXPath->registerNS( UNISTRING("inst"), UNISTRING("http://installation.openoffice.org/description") );
+
+ if( rxInteractionHandler.is() )
+ rUpdateInfoProvider->setInteractionHandler(rxInteractionHandler);
+
+ try
+ {
+ uno::Reference< container::XEnumeration > aUpdateInfoEnumeration =
+ rUpdateInfoProvider->getUpdateInformationEnumeration( aRepositoryList, aInstallSetID );
+
+ if ( !aUpdateInfoEnumeration.is() )
+ return false; // something went wrong ..
+
+ rtl::OUStringBuffer aBuffer;
+ aBuffer.appendAscii("/child::inst:description[inst:os=\'");
+ aBuffer.append( myOS );
+ aBuffer.appendAscii("\' and inst:arch=\'");
+ aBuffer.append( myArch );
+ aBuffer.appendAscii("\' and inst:buildid>");
+ aBuffer.append( aBuildID );
+ aBuffer.appendAscii("]");
+
+ rtl::OUString aXPathExpression = aBuffer.makeStringAndClear();
+
+ while( aUpdateInfoEnumeration->hasMoreElements() )
+ {
+ deployment::UpdateInformationEntry aEntry;
+
+ if( aUpdateInfoEnumeration->nextElement() >>= aEntry )
+ {
+ uno::Reference< xml::dom::XNode > xNode( aEntry.UpdateDocument.get() );
+ uno::Reference< xml::dom::XNodeList > xNodeList;
+ try {
+ xNodeList = xXPath->selectNodeList(xNode, aXPathExpression
+ + UNISTRING("/inst:update/attribute::src"));
+ } catch (css::xml::xpath::XPathException &) {
+ // ignore
+ }
+
+/*
+ o_rUpdateInfo.Sources.push_back( DownloadSource(true,
+ UNISTRING("http://openoffice.bouncer.osuosl.org/?product=OpenOffice.org&os=solarissparcwjre&lang=en-US&version=2.2.1") ) );
+*/
+
+ sal_Int32 i, imax = xNodeList->getLength();
+ for( i = 0; i < imax; ++i )
+ {
+ uno::Reference< xml::dom::XNode > xNode2( xNodeList->item(i) );
+
+ if( xNode2.is() )
+ {
+ uno::Reference< xml::dom::XElement > xParent(xNode2->getParentNode(), uno::UNO_QUERY_THROW);
+ rtl::OUString aType = xParent->getAttribute(UNISTRING("type"));
+ bool bIsDirect = ( sal_False == aType.equalsIgnoreAsciiCaseAscii("text/html") );
+
+ o_rUpdateInfo.Sources.push_back( DownloadSource(bIsDirect, xNode2->getNodeValue()) );
+ }
+ }
+
+ uno::Reference< xml::dom::XNode > xNode2;
+ try {
+ xNode2 = xXPath->selectSingleNode(xNode, aXPathExpression
+ + UNISTRING("/inst:version/text()"));
+ } catch (css::xml::xpath::XPathException &) {
+ // ignore
+ }
+
+ if( xNode2.is() )
+ o_rUpdateInfo.Version = xNode2->getNodeValue();
+
+ try {
+ xNode2 = xXPath->selectSingleNode(xNode, aXPathExpression
+ + UNISTRING("/inst:buildid/text()"));
+ } catch (css::xml::xpath::XPathException &) {
+ // ignore
+ }
+
+ if( xNode2.is() )
+ o_rUpdateInfo.BuildId = xNode2->getNodeValue();
+
+ o_rUpdateInfo.Description = aEntry.Description;
+
+ // Release Notes
+ try {
+ xNodeList = xXPath->selectNodeList(xNode, aXPathExpression
+ + UNISTRING("/inst:relnote"));
+ } catch (css::xml::xpath::XPathException &) {
+ // ignore
+ }
+ imax = xNodeList->getLength();
+ for( i = 0; i < imax; ++i )
+ {
+ uno::Reference< xml::dom::XElement > xRelNote(xNodeList->item(i), uno::UNO_QUERY);
+ if( xRelNote.is() )
+ {
+ sal_Int32 pos = xRelNote->getAttribute(UNISTRING("pos")).toInt32();
+
+ ReleaseNote aRelNote((sal_uInt8) pos, xRelNote->getAttribute(UNISTRING("src")));
+
+ if( xRelNote->hasAttribute(UNISTRING("src2")) )
+ {
+ pos = xRelNote->getAttribute(UNISTRING("pos2")).toInt32();
+ aRelNote.Pos2 = (sal_Int8) pos;
+ aRelNote.URL2 = xRelNote->getAttribute(UNISTRING("src2"));
+ }
+
+ o_rUpdateInfo.ReleaseNotes.push_back(aRelNote);
+ }
+ }
+/*
+ o_rUpdateInfo.ReleaseNotes.push_back(
+ ReleaseNote(1, UNISTRING("http://qa.openoffice.org/tests/online_update_test.html"))
+ );
+*/
+
+ if( o_rUpdateInfo.Sources.size() > 0 )
+ return true;
+ }
+ }
+ }
+ catch( ... )
+ {
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+bool storeExtensionUpdateInfos( const uno::Reference< uno::XComponentContext > & rxContext,
+ const uno::Sequence< uno::Sequence< rtl::OUString > > &rUpdateInfos )
+{
+ if ( rUpdateInfos.hasElements() )
+ {
+ rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( rxContext );
+
+ for ( sal_Int32 i = rUpdateInfos.getLength() - 1; i >= 0; i-- )
+ {
+ aConfig->storeExtensionVersion( rUpdateInfos[i][0], rUpdateInfos[i][1] );
+ }
+ }
+ return rUpdateInfos.hasElements();
+}
+
+//------------------------------------------------------------------------------
+// Returns 'true' if there are updates for any extension
+
+bool checkForExtensionUpdates( const uno::Reference< uno::XComponentContext > & rxContext )
+{
+ uno::Sequence< uno::Sequence< rtl::OUString > > aUpdateList;
+
+ uno::Reference< deployment::XPackageInformationProvider > xInfoProvider;
+ try
+ {
+ uno::Any aValue( rxContext->getValueByName(
+ UNISTRING( "/singletons/com.sun.star.deployment.PackageInformationProvider" ) ) );
+ OSL_VERIFY( aValue >>= xInfoProvider );
+ }
+ catch( const uno::Exception& )
+ {
+ OSL_ENSURE( false, "checkForExtensionUpdates: could not create the PackageInformationProvider!" );
+ }
+
+ if ( !xInfoProvider.is() ) return false;
+
+ aUpdateList = xInfoProvider->isUpdateAvailable( ::rtl::OUString() );
+ storeExtensionUpdateInfos( rxContext, aUpdateList );
+
+ return aUpdateList.hasElements();
+}
+
+//------------------------------------------------------------------------------
+// Returns 'true' if there are any pending updates for any extension (offline check)
+
+bool checkForPendingUpdates( const uno::Reference< uno::XComponentContext > & rxContext )
+{
+ uno::Sequence< uno::Sequence< rtl::OUString > > aExtensionList;
+ uno::Reference< deployment::XPackageInformationProvider > xInfoProvider;
+ try
+ {
+ uno::Any aValue( rxContext->getValueByName(
+ UNISTRING( "/singletons/com.sun.star.deployment.PackageInformationProvider" ) ) );
+ OSL_VERIFY( aValue >>= xInfoProvider );
+ }
+ catch( const uno::Exception& )
+ {
+ OSL_ENSURE( false, "checkForExtensionUpdates: could not create the PackageInformationProvider!" );
+ }
+
+ if ( !xInfoProvider.is() ) return false;
+
+ bool bPendingUpdateFound = false;
+
+ aExtensionList = xInfoProvider->getExtensionList();
+ if ( aExtensionList.hasElements() )
+ {
+ rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( rxContext );
+
+ for ( sal_Int32 i = aExtensionList.getLength() - 1; i >= 0; i-- )
+ {
+ bPendingUpdateFound = aConfig->checkExtensionVersion( aExtensionList[i][0], aExtensionList[i][1] );
+ if ( bPendingUpdateFound )
+ break;
+ }
+ }
+
+ return bPendingUpdateFound;
+}
diff --git a/extensions/source/update/check/updateprotocol.hxx b/extensions/source/update/check/updateprotocol.hxx
new file mode 100644
index 000000000000..92fd663612ac
--- /dev/null
+++ b/extensions/source/update/check/updateprotocol.hxx
@@ -0,0 +1,59 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updateprotocol.hxx,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/task/XInteractionHandler.hpp>
+#include <com/sun/star/deployment/UpdateInformationProvider.hpp>
+
+#include <vector>
+#include "updateinfo.hxx"
+
+// Returns 'true' if successfully connected to the update server
+bool checkForUpdates(
+ UpdateInfo& o_rUpdateInfo,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::task::XInteractionHandler >& rxInteractionHandler,
+ const ::com::sun::star::uno::Reference< ::com::sun::star::deployment::XUpdateInformationProvider >& rxProvider
+);
+
+// Returns 'true' if there are updates for any extension
+bool checkForExtensionUpdates(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext
+);
+
+bool checkForPendingUpdates(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext
+);
+
+bool storeExtensionUpdateInfos(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext,
+ const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Sequence< rtl::OUString > > &rUpdateInfos
+);
+
diff --git a/extensions/source/update/check/updateprotocoltest.cxx b/extensions/source/update/check/updateprotocoltest.cxx
new file mode 100644
index 000000000000..df1a07430e35
--- /dev/null
+++ b/extensions/source/update/check/updateprotocoltest.cxx
@@ -0,0 +1,97 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updateprotocoltest.cxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+
+#include <cppuhelper/bootstrap.hxx>
+
+#include "updateprotocol.hxx"
+
+#include <sal/main.h>
+#include <osl/process.h>
+#include <stdio.h>
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+namespace task = ::com::sun::star::task;
+namespace uno = ::com::sun::star::uno;
+
+// -----------------------------------------------------------------------
+
+SAL_IMPLEMENT_MAIN()
+{
+ (void) argv;
+ (void) argc;
+
+ if( osl_getCommandArgCount() != 0 )
+ {
+ fprintf(stderr, "Usage: updateprotocoltest\n");
+ return -1;
+ }
+
+ // create the initial component context
+ uno::Reference< uno::XComponentContext > rComponentContext = cppu::defaultBootstrap_InitialComponentContext();
+
+ // initialize UCB
+ uno::Sequence< uno::Any > theArguments(2);
+ theArguments[0] = uno::makeAny( UNISTRING( "Local") );
+ theArguments[1] = uno::makeAny( UNISTRING( "Office") );
+
+ uno::Reference< uno::XInterface > xUCB =
+ rComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ UNISTRING( "com.sun.star.ucb.UniversalContentBroker" ),
+ theArguments,
+ rComponentContext );
+
+
+ rtl::OUString aURL;
+ rtl::OUString aVersion;
+
+ try
+ {
+ if( checkForUpdates(rComponentContext, uno::Reference< task::XInteractionHandler > (), aURL, aVersion) )
+ {
+ OSL_TRACE( "Update found: %s on %s",
+ rtl::OUStringToOString( aVersion, RTL_TEXTENCODING_UTF8).getStr(),
+ rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8).getStr());
+ }
+ else
+ {
+ OSL_TRACE( "no updates found" );
+ }
+ }
+ catch( ... )
+ {
+ OSL_TRACE( "unhandled exception caught" );
+ }
+
+ return 0;
+}
diff --git a/extensions/source/update/check/updchk.xml b/extensions/source/update/check/updchk.xml
new file mode 100644
index 000000000000..25d5d361e1d0
--- /dev/null
+++ b/extensions/source/update/check/updchk.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd">
+<module-description xmlns:xlink="http://www.w3.org/1999/xlink">
+ <module-name>updchk</module-name>
+ <component-description>
+ <author> Oliver Braun </author>
+ <name>vnd.sun.UpdateCheck</name>
+ <description> The </description>
+ <loader-name>com.sun.star.loader.SharedLibrary</loader-name>
+ <language>c++</language>
+ <status value="beta"/>
+ <supported-service>com.sun.star.setup.UpdateCheck</supported-service>
+ <service-dependency>...</service-dependency>
+ <type>com.sun.star.beans.NamedValue</type>
+ <type>com.sun.star.beans.PropertyValue</type>
+ <type>com.sun.star.container.XNameReplace</type>
+ <type>com.sun.star.deployment.UpdateInformationProvider</type>
+ <type>com.sun.star.frame.DispatchResultEvent</type>
+ <type>com.sun.star.frame.DispatchResultState</type>
+ <type>com.sun.star.frame.XFrame</type>
+ <type>com.sun.star.io.XInputStream</type>
+ <type>com.sun.star.io.XOutputStream</type>
+ <type>com.sun.star.lang.XComponent</type>
+ <type>com.sun.star.lang.XMultiComponentFactory</type>
+ <type>com.sun.star.lang.XMultiServiceFactory</type>
+ <type>com.sun.star.lang.XServiceInfo</type>
+ <type>com.sun.star.lang.XSingleComponentFactory</type>
+ <type>com.sun.star.lang.XSingleServiceFactory</type>
+ <type>com.sun.star.lang.XTypeProvider</type>
+ <type>com.sun.star.registry.XRegistryKey</type>
+ <type>com.sun.star.system.SystemShellExecuteFlags</type>
+ <type>com.sun.star.system.XSystemShellExecute</type>
+ <type>com.sun.star.task.XInteractionHandler</type>
+ <type>com.sun.star.task.XJob</type>
+ <type>com.sun.star.uno.TypeClass</type>
+ <type>com.sun.star.uno.XAggregation</type>
+ <type>com.sun.star.uno.XComponentContext</type>
+ <type>com.sun.star.uno.XCurrentContext</type>
+ <type>com.sun.star.uno.XWeak</type>
+ <type>com.sun.star.util.XChangesBatch</type>
+ <type>com.sun.star.xml.xpath.XXPathAPI</type>
+ </component-description>
+ <project-build-dependency>cppuhelper</project-build-dependency>
+ <project-build-dependency>cppu</project-build-dependency>
+ <project-build-dependency>sal</project-build-dependency>
+ <runtime-module-dependency>cppuhelper3$(COM)</runtime-module-dependency>
+ <runtime-module-dependency>cppu3</runtime-module-dependency>
+ <runtime-module-dependency>sal3</runtime-module-dependency>
+</module-description>
diff --git a/extensions/source/update/exports.map b/extensions/source/update/exports.map
new file mode 100644
index 000000000000..ba501f9ae076
--- /dev/null
+++ b/extensions/source/update/exports.map
@@ -0,0 +1,10 @@
+UDK_3_0_0 {
+ global:
+ GetVersionInfo;
+ component_getImplementationEnvironment;
+ component_getFactory;
+ component_writeInfo;
+
+ local:
+ *;
+};
diff --git a/extensions/source/update/feed/makefile.mk b/extensions/source/update/feed/makefile.mk
new file mode 100644
index 000000000000..ecb5957df9b7
--- /dev/null
+++ b/extensions/source/update/feed/makefile.mk
@@ -0,0 +1,74 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.4 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..$/..$/..
+
+PRJNAME=extensions
+TARGET=updatefeed
+
+LIBTARGET=NO
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ---
+
+.INCLUDE : settings.mk
+
+# no "lib" prefix
+DLLPRE =
+
+.IF "$(SYSTEM_ZLIB)" == "YES"
+CFLAGS+=-DSYSTEM_ZLIB
+.ENDIF
+
+# --- Files ---
+
+
+SLOFILES=\
+ $(SLO)$/updatefeed.obj \
+
+SHL1NOCHECK=TRUE
+SHL1TARGET=$(TARGET).uno
+SHL1OBJS=$(SLOFILES)
+
+SHL1IMPLIB=i$(SHL1TARGET)
+SHL1STDLIBS= \
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
+ $(SALLIB) \
+ $(ZLIB3RDLIB)
+
+SHL1VERSIONMAP=..$/exports.map
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+DEF1NAME=$(SHL1TARGET)
+
+# --- Targets ---
+
+.INCLUDE : target.mk
+
diff --git a/extensions/source/update/feed/test/makefile.mk b/extensions/source/update/feed/test/makefile.mk
new file mode 100644
index 000000000000..6d95cbbf1e7a
--- /dev/null
+++ b/extensions/source/update/feed/test/makefile.mk
@@ -0,0 +1,62 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..$/..$/..$/..
+
+PRJNAME=extensions
+TARGET=updatefeedtest
+
+TARGETTYPE=CUI
+ENABLE_EXCEPTIONS=TRUE
+
+INCPRE=$(OUT)$/inc$/updatefeed
+
+# --- Settings ---
+
+.INCLUDE : settings.mk
+
+# --- Files ---
+
+
+SLOFILES=\
+ $(SLO)$/updatefeedtest.obj \
+
+APP1TARGET=$(TARGET)
+APP1OBJS=$(SLOFILES)
+
+APP1STDLIBS= \
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
+ $(SALLIB)
+
+# --- Targets ---
+
+.INCLUDE : target.mk
+
diff --git a/extensions/source/update/feed/test/updatefeedtest.cxx b/extensions/source/update/feed/test/updatefeedtest.cxx
new file mode 100644
index 000000000000..df56649fd6c0
--- /dev/null
+++ b/extensions/source/update/feed/test/updatefeedtest.cxx
@@ -0,0 +1,109 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatefeedtest.cxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+#include <comphelper/processfactory.hxx>
+
+#include <cppuhelper/servicefactory.hxx>
+#include <cppuhelper/bootstrap.hxx>
+
+#include <com/sun/star/lang/XInitialization.hpp>
+
+
+#include <com/sun/star/deployment/UpdateInformationProvider.hpp>
+
+#include <sal/main.h>
+#include <osl/process.h>
+#include <stdio.h>
+
+namespace deployment = ::com::sun::star::deployment;
+namespace lang = ::com::sun::star::lang;
+namespace uno = ::com::sun::star::uno;
+namespace xml = ::com::sun::star::xml;
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+// -----------------------------------------------------------------------
+
+SAL_IMPLEMENT_MAIN()
+{
+ (void) argv;
+ (void) argc;
+
+ if( osl_getCommandArgCount() != 1 )
+ {
+ fprintf(stderr, "Usage: updatefeedtest <url>\n");
+ return -1;
+ }
+
+ // create the initial component context
+ uno::Reference< uno::XComponentContext > rComponentContext = cppu::defaultBootstrap_InitialComponentContext();
+
+ // initialize UCB
+ uno::Sequence< uno::Any > theArguments(2);
+ theArguments[0] = uno::makeAny( UNISTRING( "Local") );
+ theArguments[1] = uno::makeAny( UNISTRING( "Office") );
+
+ uno::Reference< uno::XInterface > xUCB =
+ rComponentContext->getServiceManager()->createInstanceWithArgumentsAndContext(
+ UNISTRING( "com.sun.star.ucb.UniversalContentBroker" ),
+ theArguments,
+ rComponentContext );
+
+ // retrieve the update information provider
+ uno::Reference< deployment::XUpdateInformationProvider > rUpdateInformationProvider =
+ deployment::UpdateInformationProvider::create( rComponentContext );
+
+ uno::Sequence< rtl::OUString > theURLs(1);
+ osl_getCommandArg( 0, &theURLs[0].pData );
+ // theURLs[0] = UNISTRING( "http://localhost/~olli/atomfeed.xml" );
+
+ rtl::OUString aExtension = UNISTRING( "MyExtension" );
+
+ try
+ {
+ uno::Sequence< uno::Reference< xml::dom::XElement > > theUpdateInfo =
+ rUpdateInformationProvider->getUpdateInformation( theURLs, aExtension );
+
+ OSL_TRACE( "getUpdateInformation returns %d element(s)", theUpdateInfo.getLength() );
+ }
+ catch( const uno::Exception & e )
+ {
+ OSL_TRACE( "exception caught: %s", rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr());
+ }
+ catch( ... )
+ {
+ OSL_TRACE( "exception of undetermined type caught" );
+ }
+
+
+ return 0;
+}
diff --git a/extensions/source/update/feed/updatefeed.cxx b/extensions/source/update/feed/updatefeed.cxx
new file mode 100644
index 000000000000..bed6bed85bc3
--- /dev/null
+++ b/extensions/source/update/feed/updatefeed.cxx
@@ -0,0 +1,1180 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatefeed.cxx,v $
+ * $Revision: 1.11.52.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+
+#include <cppuhelper/implbase1.hxx>
+#include <cppuhelper/implbase5.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <com/sun/star/beans/Property.hpp>
+#include <com/sun/star/beans/XPropertySetInfo.hpp>
+#include <com/sun/star/beans/PropertyValue.hpp>
+#include <com/sun/star/container/XNameAccess.hpp>
+#include <com/sun/star/deployment/UpdateInformationEntry.hpp>
+#include <com/sun/star/deployment/UpdateInformationProvider.hpp>
+#include <com/sun/star/io/XActiveDataSink.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/task/XPasswordContainer.hpp>
+#include "com/sun/star/task/NoMasterException.hpp"
+#include "com/sun/star/ucb/AuthenticationRequest.hpp"
+#ifndef _COM_SUN_STAR_UCB_XCOMMMANDENVIRONMENT_HPP_
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_XWEBDAVCOMMMANDENVIRONMENT_HPP_
+#include <com/sun/star/ucb/XWebDAVCommandEnvironment.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_XCOMMMANDPROCESSOR2_HPP_
+#include <com/sun/star/ucb/XCommandProcessor2.hpp>
+#endif
+#ifndef _COM_SUN_STAR_UCB_XCONTENTIDNETIFIERFACTORY_HPP_
+#include <com/sun/star/ucb/XContentIdentifierFactory.hpp>
+#endif
+#include <com/sun/star/ucb/XContentProvider.hpp>
+#include "com/sun/star/ucb/XInteractionSupplyAuthentication.hpp"
+#include <com/sun/star/ucb/OpenCommandArgument2.hpp>
+#include <com/sun/star/ucb/OpenMode.hpp>
+#include <com/sun/star/sdbc/XRow.hpp>
+#include <com/sun/star/xml/dom/XDocumentBuilder.hpp>
+#include <com/sun/star/xml/xpath/XXPathAPI.hpp>
+
+#include <rtl/ref.hxx>
+#include <rtl/memory.h>
+#include <rtl/bootstrap.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <osl/process.h>
+#include <osl/conditn.hxx>
+
+#ifndef _ZLIB_H
+#ifdef SYSTEM_ZLIB
+#include "zlib.h"
+#else
+#include "zlib/zlib.h"
+#endif
+#endif
+
+namespace beans = com::sun::star::beans ;
+namespace container = com::sun::star::container ;
+namespace deployment = com::sun::star::deployment ;
+namespace io = com::sun::star::io ;
+namespace lang = com::sun::star::lang ;
+namespace task = com::sun::star::task ;
+namespace ucb = com::sun::star::ucb ;
+namespace uno = com::sun::star::uno ;
+namespace xml = com::sun::star::xml ;
+namespace sdbc = com::sun::star::sdbc ;
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+//------------------------------------------------------------------------------
+
+namespace
+{
+
+#ifdef DEBUG
+
+class InputStreamWrapper : public ::cppu::WeakImplHelper1< io::XInputStream >
+{
+ uno::Reference< io::XInputStream > m_xStream;
+
+public:
+ InputStreamWrapper(const uno::Reference< io::XInputStream >& rxStream) :
+ m_xStream(rxStream) {};
+
+ virtual sal_Int32 SAL_CALL readBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
+ throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
+ {
+ sal_Int32 n = m_xStream->readBytes(aData, nBytesToRead);
+ if ( n )
+ OSL_TRACE( "Read [%d] bytes: %s\n", n, aData.get()->elements );
+ return n;
+ };
+ virtual sal_Int32 SAL_CALL readSomeBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
+ throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
+ {
+ sal_Int32 n = m_xStream->readSomeBytes(aData, nMaxBytesToRead);
+ if ( n )
+ OSL_TRACE( "Read [%d] bytes: %s\n", n, aData.get()->elements );
+ return n;
+ };
+ virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
+ throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
+ { m_xStream->skipBytes(nBytesToSkip); };
+ virtual sal_Int32 SAL_CALL available()
+ throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
+ { return m_xStream->available(); };
+ virtual void SAL_CALL closeInput( )
+ throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
+ {};
+};
+
+#define INPUT_STREAM(i) new InputStreamWrapper(i)
+#else
+#define INPUT_STREAM(i) i
+#endif
+
+//------------------------------------------------------------------------------
+
+class ActiveDataSink : public ::cppu::WeakImplHelper1< io::XActiveDataSink >
+{
+ uno::Reference< io::XInputStream > m_xStream;
+
+public:
+ ActiveDataSink() {};
+
+ inline operator uno::Reference< io::XActiveDataSink > () { return this; };
+
+ virtual uno::Reference< io::XInputStream > SAL_CALL getInputStream()
+ throw (uno::RuntimeException) { return m_xStream; };
+ virtual void SAL_CALL setInputStream( uno::Reference< io::XInputStream > const & rStream )
+ throw (uno::RuntimeException) { m_xStream = rStream; };
+};
+
+//------------------------------------------------------------------------------
+
+class InflateInputStream : public ::cppu::WeakImplHelper1< io::XInputStream >
+{
+ uno::Reference< io::XInputStream > m_xStream;
+
+ uno::Sequence < sal_Int8 > m_aBuffer;
+ sal_Int32 m_nOffset;
+ bool m_bRead;
+
+ rtl::OUString m_aContentEncoding;
+
+ void readIntoMemory();
+
+public:
+ InflateInputStream(const uno::Reference< io::XInputStream >& rxStream,const rtl::OUString& rContentEncoding) :
+ m_xStream(rxStream), m_nOffset(0), m_bRead(false), m_aContentEncoding(rContentEncoding) {};
+
+ virtual sal_Int32 SAL_CALL readBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
+ throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL readSomeBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
+ throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
+ { readIntoMemory(); return readBytes(aData, nMaxBytesToRead ); };
+ virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
+ throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
+ {
+ readIntoMemory();
+ if( m_nOffset + nBytesToSkip < m_aBuffer.getLength() )
+ m_nOffset += nBytesToSkip;
+ else
+ m_nOffset = m_aBuffer.getLength();
+ };
+ virtual sal_Int32 SAL_CALL available()
+ throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
+ { readIntoMemory(); return m_aBuffer.getLength() - m_nOffset; };
+ virtual void SAL_CALL closeInput( )
+ throw (io::NotConnectedException, io::IOException, uno::RuntimeException)
+ { m_xStream->closeInput(); };
+};
+
+
+sal_Int32 SAL_CALL
+InflateInputStream::readBytes(uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
+ throw (io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
+{
+ readIntoMemory();
+ sal_Int32 nAvailable = available();
+ sal_Int32 nBytesToCopy = nAvailable < nBytesToRead ? nAvailable : nBytesToRead;
+ if( nBytesToCopy > 0 )
+ {
+ aData.realloc(nBytesToCopy);
+ rtl_copyMemory(aData.getArray(), m_aBuffer.getConstArray() + m_nOffset, nBytesToCopy);
+ m_nOffset += nBytesToCopy;
+ }
+
+ return nBytesToCopy;
+};
+
+void InflateInputStream::readIntoMemory()
+{
+ if( !m_bRead && m_xStream.is() )
+ {
+ const sal_Int32 nBytesRequested = 4096;
+
+ uno::Sequence < sal_Int8 > aTempBuffer(nBytesRequested);
+ uno::Sequence < sal_Int8 > aCompressedBuffer;
+ sal_Int32 nBytesRead;
+
+ m_bRead = true;
+
+ do
+ {
+ nBytesRead = m_xStream->readBytes(aTempBuffer, nBytesRequested);
+
+ if( nBytesRead > 0 )
+ {
+ sal_Int32 nOffset = aCompressedBuffer.getLength();
+ aCompressedBuffer.realloc( nOffset + nBytesRead );
+
+ rtl_copyMemory(aCompressedBuffer.getArray() + nOffset, aTempBuffer.getConstArray(), nBytesRead);
+ }
+ }
+ while( nBytesRead == nBytesRequested );
+
+ z_stream *pStream = new z_stream;
+ /* memset to 0 to set zalloc/opaque etc */
+ rtl_zeroMemory (pStream, sizeof(*pStream));
+
+ int windowSize = 15;
+ int headerOffset = 0;
+
+ if( m_aContentEncoding.equalsAscii("gzip") )
+ {
+ sal_uInt8 magic[2];
+ magic[0] = *((sal_uInt8 *) aCompressedBuffer.getConstArray());
+ magic[1] = *((sal_uInt8 *) aCompressedBuffer.getConstArray() + 1);
+
+ if( (magic[0] == 0x1f) && (magic[1] == 0x8b) )
+ {
+ windowSize = -14;
+ headerOffset = 10;
+ }
+ }
+
+ pStream->next_in = (unsigned char *) aCompressedBuffer.getConstArray();
+ pStream->avail_in = aCompressedBuffer.getLength();
+
+ pStream->next_in += headerOffset;
+ pStream->avail_in -= headerOffset;
+
+ if( Z_OK == inflateInit2(pStream, windowSize) )
+ {
+ int result;
+
+ do
+ {
+ sal_Int32 nOffset = m_aBuffer.getLength();
+ m_aBuffer.realloc(nOffset + 4096);
+
+ pStream->next_out = reinterpret_cast < unsigned char* > ( m_aBuffer.getArray() + nOffset );
+ pStream->avail_out = 4096;
+
+ result = ::inflate(pStream, Z_FINISH);
+
+ if( result == Z_STREAM_END )
+ break;
+
+ } while( result == Z_BUF_ERROR );
+
+ inflateEnd(pStream);
+ m_aBuffer.realloc(pStream->total_out);
+
+ }
+
+ if (pStream != NULL)
+ {
+ delete pStream;
+ pStream = NULL;
+ }
+ }
+}
+
+//------------------------------------------------------------------------------
+
+class UpdateInformationProvider :
+ public ::cppu::WeakImplHelper5< deployment::XUpdateInformationProvider,
+ ucb::XCommandEnvironment,
+ ucb::XWebDAVCommandEnvironment,
+ lang::XServiceInfo,
+ task::XInteractionHandler >
+{
+public:
+ static uno::Reference< uno::XInterface > createInstance(const uno::Reference<uno::XComponentContext>& xContext);
+
+ static uno::Sequence< rtl::OUString > getServiceNames();
+ static rtl::OUString getImplName();
+
+ uno::Reference< xml::dom::XElement > getDocumentRoot(const uno::Reference< xml::dom::XNode >& rxNode);
+ uno::Reference< xml::dom::XNode > getChildNode(const uno::Reference< xml::dom::XNode >& rxNode, const rtl::OUString& rName);
+
+
+ // XUpdateInformationService
+ virtual uno::Sequence< uno::Reference< xml::dom::XElement > > SAL_CALL
+ getUpdateInformation(
+ uno::Sequence< rtl::OUString > const & repositories,
+ rtl::OUString const & extensionId
+ ) throw (uno::Exception, uno::RuntimeException);
+
+ virtual void SAL_CALL cancel()
+ throw (uno::RuntimeException);
+
+ virtual void SAL_CALL setInteractionHandler(
+ uno::Reference< task::XInteractionHandler > const & handler )
+ throw (uno::RuntimeException);
+
+ virtual uno::Reference< container::XEnumeration > SAL_CALL
+ getUpdateInformationEnumeration(
+ uno::Sequence< rtl::OUString > const & repositories,
+ rtl::OUString const & extensionId
+ ) throw (uno::Exception, uno::RuntimeException);
+
+ // XCommandEnvironment
+ virtual uno::Reference< task::XInteractionHandler > SAL_CALL getInteractionHandler()
+ throw ( uno::RuntimeException );
+
+ virtual uno::Reference< ucb::XProgressHandler > SAL_CALL getProgressHandler()
+ throw ( uno::RuntimeException ) { return uno::Reference< ucb::XProgressHandler >(); };
+
+ // XWebDAVCommandEnvironment
+ virtual uno::Sequence< beans::NamedValue > SAL_CALL getUserRequestHeaders(
+ const rtl::OUString&, const rtl::OUString& )
+ throw ( uno::RuntimeException ) { return m_aRequestHeaderList; };
+
+ // XServiceInfo
+ virtual rtl::OUString SAL_CALL getImplementationName()
+ throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName)
+ throw (uno::RuntimeException);
+ virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames()
+ throw (uno::RuntimeException);
+
+ // XInteractionHandler
+ virtual void SAL_CALL handle( const uno::Reference< task::XInteractionRequest >& rRequest )
+ throw( uno::RuntimeException );
+
+protected:
+
+ virtual ~UpdateInformationProvider();
+ static uno::Any getConfigurationItem(uno::Reference<lang::XMultiServiceFactory> const & configurationProvider, rtl::OUString const & node, rtl::OUString const & item);
+
+private:
+ uno::Reference< io::XInputStream > load(const rtl::OUString& rURL);
+
+ void storeCommandInfo( sal_Int32 nCommandId,
+ uno::Reference< ucb::XCommandProcessor > const & rxCommandProcessor);
+
+ bool initPasswordContainer( uno::Reference< task::XPasswordContainer > * pContainer );
+
+ UpdateInformationProvider(const uno::Reference<uno::XComponentContext>& xContext,
+ const uno::Reference< ucb::XContentIdentifierFactory >& xContentIdFactory,
+ const uno::Reference< ucb::XContentProvider >& xContentProvider,
+ const uno::Reference< xml::dom::XDocumentBuilder >& xDocumentBuilder,
+ const uno::Reference< xml::xpath::XXPathAPI >& xXPathAPI);
+
+ const uno::Reference< uno::XComponentContext> m_xContext;
+
+ const uno::Reference< ucb::XContentIdentifierFactory > m_xContentIdFactory;
+ const uno::Reference< ucb::XContentProvider > m_xContentProvider;
+ const uno::Reference< xml::dom::XDocumentBuilder > m_xDocumentBuilder;
+ const uno::Reference< xml::xpath::XXPathAPI > m_xXPathAPI;
+
+ uno::Sequence< beans::NamedValue > m_aRequestHeaderList;
+
+ uno::Reference< ucb::XCommandProcessor > m_xCommandProcessor;
+ uno::Reference< task::XInteractionHandler > m_xInteractionHandler;
+
+ osl::Mutex m_aMutex;
+ osl::Condition m_bCancelled;
+
+ sal_Int32 m_nCommandId;
+};
+
+//------------------------------------------------------------------------------
+
+class UpdateInformationEnumeration : public ::cppu::WeakImplHelper1< container::XEnumeration >
+{
+public:
+ UpdateInformationEnumeration(const uno::Reference< xml::dom::XNodeList >& xNodeList,
+ const uno::Reference< UpdateInformationProvider > xUpdateInformationProvider) :
+ m_xUpdateInformationProvider(xUpdateInformationProvider),
+ m_xNodeList(xNodeList),
+ m_nNodes(xNodeList.is() ? xNodeList->getLength() : 0),
+ m_nCount(0)
+ {
+ };
+
+ virtual ~UpdateInformationEnumeration() {};
+
+ // XEnumeration
+ sal_Bool SAL_CALL hasMoreElements() throw (uno::RuntimeException) { return m_nCount < m_nNodes; };
+ uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
+ {
+ OSL_ASSERT( m_xNodeList.is() );
+ OSL_ASSERT( m_xUpdateInformationProvider.is() );
+
+ if( !(m_nCount < m_nNodes ) )
+ throw container::NoSuchElementException(rtl::OUString::valueOf(m_nCount), *this);
+
+ try
+ {
+ deployment::UpdateInformationEntry aEntry;
+
+ uno::Reference< xml::dom::XNode > xAtomEntryNode( m_xNodeList->item(m_nCount++) );
+
+ uno::Reference< xml::dom::XNode > xSummaryNode(
+ m_xUpdateInformationProvider->getChildNode( xAtomEntryNode, UNISTRING( "summary/text()" ) )
+ );
+
+ if( xSummaryNode.is() )
+ aEntry.Description = xSummaryNode->getNodeValue();
+
+ uno::Reference< xml::dom::XNode > xContentNode(
+ m_xUpdateInformationProvider->getChildNode( xAtomEntryNode, UNISTRING( "content" ) ) );
+
+ if( xContentNode.is() )
+ aEntry.UpdateDocument = m_xUpdateInformationProvider->getDocumentRoot(xContentNode);
+
+ return uno::makeAny(aEntry);
+ }
+
+ // action has been aborted
+ catch( ucb::CommandAbortedException const & e)
+ { throw lang::WrappedTargetException( UNISTRING( "Command aborted" ), *this, uno::makeAny(e) ); }
+
+ // let runtime exception pass
+ catch( uno::RuntimeException const & ) { throw; }
+
+ // document not accessible
+ catch( uno::Exception const & e)
+ { throw lang::WrappedTargetException( UNISTRING( "Document not accessible" ), *this, uno::makeAny(e) ); }
+ }
+
+private:
+ const uno::Reference< UpdateInformationProvider > m_xUpdateInformationProvider;
+ const uno::Reference< xml::dom::XNodeList > m_xNodeList;
+ const sal_Int32 m_nNodes;
+ sal_Int32 m_nCount;
+};
+
+//------------------------------------------------------------------------------
+
+class SingleUpdateInformationEnumeration : public ::cppu::WeakImplHelper1< container::XEnumeration >
+{
+public:
+ SingleUpdateInformationEnumeration(const uno::Reference< xml::dom::XElement >& xElement)
+ : m_nCount(0) { m_aEntry.UpdateDocument = xElement; };
+ virtual ~SingleUpdateInformationEnumeration() {};
+
+ // XEnumeration
+ sal_Bool SAL_CALL hasMoreElements() throw (uno::RuntimeException) { return 0 == m_nCount; };
+ uno::Any SAL_CALL nextElement() throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException)
+ {
+ if( m_nCount > 0 )
+ throw container::NoSuchElementException(rtl::OUString::valueOf(m_nCount), *this);
+
+ ++m_nCount;
+ return uno::makeAny(m_aEntry);
+ };
+
+private:
+ sal_uInt8 m_nCount;
+ deployment::UpdateInformationEntry m_aEntry;
+};
+
+
+//------------------------------------------------------------------------------
+
+UpdateInformationProvider::UpdateInformationProvider(
+ const uno::Reference<uno::XComponentContext>& xContext,
+ const uno::Reference< ucb::XContentIdentifierFactory >& xContentIdFactory,
+ const uno::Reference< ucb::XContentProvider >& xContentProvider,
+ const uno::Reference< xml::dom::XDocumentBuilder >& xDocumentBuilder,
+ const uno::Reference< xml::xpath::XXPathAPI >& xXPathAPI
+) : m_xContext(xContext), m_xContentIdFactory(xContentIdFactory),
+ m_xContentProvider(xContentProvider), m_xDocumentBuilder(xDocumentBuilder),
+ m_xXPathAPI(xXPathAPI), m_aRequestHeaderList(2)
+{
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException(
+ UNISTRING("unable to obtain service manager from component context"),
+ uno::Reference< uno::XInterface >());
+
+ uno::Reference< lang::XMultiServiceFactory > xConfigurationProvider(
+ xServiceManager->createInstanceWithContext(
+ UNISTRING("com.sun.star.configuration.ConfigurationProvider"),
+ xContext ),
+ uno::UNO_QUERY_THROW);
+
+ rtl::OUStringBuffer buf;
+ rtl::OUString name;
+ getConfigurationItem(
+ xConfigurationProvider,
+ UNISTRING("org.openoffice.Setup/Product"),
+ UNISTRING("ooName")) >>= name;
+ buf.append(name);
+ buf.append(sal_Unicode(' '));
+ rtl::OUString version;
+ getConfigurationItem(
+ xConfigurationProvider,
+ UNISTRING("org.openoffice.Setup/Product"),
+ UNISTRING("ooSetupVersion")) >>= version;
+ buf.append(version);
+ rtl::OUString edition(
+ UNISTRING(
+ "${${BRAND_BASE_DIR}/program/edition/edition.ini:"
+ "EDITIONNAME}"));
+ rtl::Bootstrap::expandMacros(edition);
+ if (edition.getLength() != 0) {
+ buf.append(sal_Unicode(' '));
+ buf.append(edition);
+ }
+ rtl::OUString extension;
+ getConfigurationItem(
+ xConfigurationProvider,
+ UNISTRING("org.openoffice.Setup/Product"),
+ UNISTRING("ooSetupExtension")) >>= extension;
+ if (extension.getLength() != 0) {
+ buf.append(sal_Unicode(' '));
+ buf.append(extension);
+ }
+ rtl::OUString product(buf.makeStringAndClear());
+
+ rtl::OUString aBaseBuildId( UNISTRING( "${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" ) );
+ rtl::Bootstrap::expandMacros( aBaseBuildId );
+
+ rtl::OUString aBrandBuildId( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" ) );
+ rtl::Bootstrap::expandMacros( aBrandBuildId );
+
+ rtl::OUString aUserAgent( UNISTRING( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":UpdateUserAgent}" ) );
+ rtl::Bootstrap::expandMacros( aUserAgent );
+
+ if ( ! aBaseBuildId.equals( aBrandBuildId ) )
+ {
+ sal_Int32 nIndex = aUserAgent.indexOf( aBrandBuildId, 0 );
+ if ( nIndex != -1 )
+ aUserAgent = aUserAgent.replaceAt( nIndex, aBrandBuildId.getLength(), aBaseBuildId );
+ }
+
+ for (sal_Int32 i = 0;;) {
+ i = aUserAgent.indexOfAsciiL(
+ RTL_CONSTASCII_STRINGPARAM("<PRODUCT>"), i);
+ if (i == -1) {
+ break;
+ }
+ aUserAgent = aUserAgent.replaceAt(
+ i, RTL_CONSTASCII_LENGTH("<PRODUCT>"), product);
+ i += product.getLength();
+ }
+
+ m_aRequestHeaderList[0].Name = UNISTRING("Accept-Language");
+ m_aRequestHeaderList[0].Value = getConfigurationItem( xConfigurationProvider, UNISTRING("org.openoffice.Setup/L10N"), UNISTRING("ooLocale") );
+ m_aRequestHeaderList[1].Name = UNISTRING("Accept-Encoding");
+ m_aRequestHeaderList[1].Value = uno::makeAny( UNISTRING("gzip,deflate") );
+
+ if( aUserAgent.getLength() > 0 )
+ {
+ m_aRequestHeaderList.realloc(3);
+ m_aRequestHeaderList[2].Name = UNISTRING("User-Agent");
+ m_aRequestHeaderList[2].Value = uno::makeAny(aUserAgent);
+ }
+}
+
+//------------------------------------------------------------------------------
+uno::Reference< uno::XInterface >
+UpdateInformationProvider::createInstance(const uno::Reference<uno::XComponentContext>& xContext)
+{
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "unable to obtain service manager from component context" ),
+ uno::Reference< uno::XInterface > ());
+
+ uno::Reference< ucb::XContentIdentifierFactory > xContentIdFactory(
+ xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.ucb.UniversalContentBroker" ), xContext ),
+ uno::UNO_QUERY_THROW);
+
+ uno::Reference< ucb::XContentProvider > xContentProvider(xContentIdFactory, uno::UNO_QUERY_THROW);
+
+ uno::Reference< xml::dom::XDocumentBuilder > xDocumentBuilder(
+ xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.xml.dom.DocumentBuilder" ), xContext ),
+ uno::UNO_QUERY_THROW);
+
+ uno::Reference< xml::xpath::XXPathAPI > xXPath(
+ xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.xml.xpath.XPathAPI" ), xContext ),
+ uno::UNO_QUERY_THROW);
+
+ xXPath->registerNS( UNISTRING("atom"), UNISTRING("http://www.w3.org/2005/Atom") );
+
+ return *new UpdateInformationProvider(xContext, xContentIdFactory, xContentProvider, xDocumentBuilder, xXPath);
+}
+
+//------------------------------------------------------------------------------
+
+UpdateInformationProvider::~UpdateInformationProvider()
+{
+}
+
+//------------------------------------------------------------------------------
+
+uno::Any
+UpdateInformationProvider::getConfigurationItem(uno::Reference<lang::XMultiServiceFactory> const & configurationProvider, rtl::OUString const & node, rtl::OUString const & item)
+{
+ beans::PropertyValue aProperty;
+ aProperty.Name = UNISTRING("nodepath");
+ aProperty.Value = uno::makeAny(node);
+
+ uno::Sequence< uno::Any > aArgumentList( 1 );
+ aArgumentList[0] = uno::makeAny( aProperty );
+
+ uno::Reference< container::XNameAccess > xNameAccess(
+ configurationProvider->createInstanceWithArguments(
+ UNISTRING("com.sun.star.configuration.ConfigurationAccess"),
+ aArgumentList ),
+ uno::UNO_QUERY_THROW);
+
+ return xNameAccess->getByName(item);
+}
+
+//------------------------------------------------------------------------------
+
+void
+UpdateInformationProvider::storeCommandInfo(
+ sal_Int32 nCommandId,
+ uno::Reference< ucb::XCommandProcessor > const & rxCommandProcessor)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+
+ m_nCommandId = nCommandId;
+ m_xCommandProcessor = rxCommandProcessor;
+}
+
+//------------------------------------------------------------------------------
+
+bool UpdateInformationProvider::initPasswordContainer( uno::Reference< task::XPasswordContainer > * pContainer )
+{
+ OSL_ENSURE( pContainer, "specification violation" );
+
+ if ( !pContainer->is() )
+ {
+ uno::Reference<uno::XComponentContext> xContext(m_xContext);
+
+ if( !xContext.is() )
+ throw uno::RuntimeException( UNISTRING( "UpdateInformationProvider: empty component context" ), *this );
+
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
+
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException( UNISTRING( "UpdateInformationProvider: unable to obtain service manager from component context" ), *this );
+
+ *pContainer = uno::Reference< task::XPasswordContainer >(
+ xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.task.PasswordContainer" ), xContext ),
+ uno::UNO_QUERY);
+ }
+
+ OSL_ENSURE(pContainer->is(), "unexpected situation");
+ return pContainer->is();
+}
+
+//------------------------------------------------------------------------------
+
+uno::Reference< io::XInputStream >
+UpdateInformationProvider::load(const rtl::OUString& rURL)
+{
+ uno::Reference< ucb::XContentIdentifier > xId = m_xContentIdFactory->createContentIdentifier(rURL);
+
+ if( !xId.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "unable to obtain universal content id" ), *this);
+
+ uno::Reference< ucb::XCommandProcessor > xCommandProcessor(m_xContentProvider->queryContent(xId), uno::UNO_QUERY_THROW);
+ rtl::Reference< ActiveDataSink > aSink(new ActiveDataSink());
+
+ ucb::OpenCommandArgument2 aOpenArgument;
+ aOpenArgument.Mode = ucb::OpenMode::DOCUMENT;
+ aOpenArgument.Priority = 32768;
+ aOpenArgument.Sink = *aSink;
+
+ ucb::Command aCommand;
+ aCommand.Name = UNISTRING("open");
+ aCommand.Argument = uno::makeAny(aOpenArgument);
+
+ sal_Int32 nCommandId = xCommandProcessor->createCommandIdentifier();
+
+ storeCommandInfo(nCommandId, xCommandProcessor);
+ try
+ {
+ uno::Any aResult = xCommandProcessor->execute(aCommand, nCommandId,
+ static_cast < XCommandEnvironment *> (this));
+ }
+ catch( const uno::Exception & /* e */ )
+ {
+ storeCommandInfo(0, uno::Reference< ucb::XCommandProcessor > ());
+
+ uno::Reference< ucb::XCommandProcessor2 > xCommandProcessor2(xCommandProcessor, uno::UNO_QUERY);
+ if( xCommandProcessor2.is() )
+ xCommandProcessor2->releaseCommandIdentifier(nCommandId);
+
+ throw;
+ }
+
+ uno::Sequence< beans::Property > aProps( 1 );
+ aProps[0].Name = UNISTRING( "Content-Encoding" );
+
+ aCommand.Name = UNISTRING("getPropertyValues");
+ aCommand.Argument = uno::makeAny( aProps );
+
+ sal_Bool bCompressed = sal_False;
+ rtl::OUString aContentEncoding;
+
+ try
+ {
+ uno::Any aResult = xCommandProcessor->execute(aCommand, 0,
+ static_cast < XCommandEnvironment *> (this));
+ uno::Reference< sdbc::XRow > xPropList( aResult, uno::UNO_QUERY );
+ if ( xPropList.is() ) {
+ aContentEncoding = xPropList->getString(1);
+ if( aContentEncoding.equalsAscii("gzip") || aContentEncoding.equalsAscii("deflate"))
+ bCompressed = sal_True;
+ }
+ }
+ catch( const uno::Exception &e )
+ {
+ OSL_TRACE( "Caught exception: %s\n",
+ rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
+ }
+
+ storeCommandInfo(0, uno::Reference< ucb::XCommandProcessor > ());
+
+ uno::Reference< ucb::XCommandProcessor2 > xCommandProcessor2(xCommandProcessor, uno::UNO_QUERY);
+ if( xCommandProcessor2.is() )
+ xCommandProcessor2->releaseCommandIdentifier(nCommandId);
+
+ if ( bCompressed )
+ return INPUT_STREAM( new InflateInputStream( aSink->getInputStream(), aContentEncoding ) );
+ else
+ return INPUT_STREAM(aSink->getInputStream());
+}
+
+//------------------------------------------------------------------------------
+
+// TODO: docu content node
+
+uno::Reference< xml::dom::XElement >
+UpdateInformationProvider::getDocumentRoot(const uno::Reference< xml::dom::XNode >& rxNode)
+{
+ OSL_ASSERT(m_xDocumentBuilder.is());
+
+ uno::Reference< xml::dom::XElement > xElement(rxNode, uno::UNO_QUERY_THROW);
+
+ // load the document referenced in 'src' attribute ..
+ if( xElement->hasAttribute( UNISTRING("src") ) )
+ {
+ uno::Reference< xml::dom::XDocument > xUpdateXML =
+ m_xDocumentBuilder->parse(load(xElement->getAttribute( UNISTRING("src") )));
+
+ OSL_ASSERT( xUpdateXML.is() );
+
+ if( xUpdateXML.is() )
+ return xUpdateXML->getDocumentElement();
+ }
+ // .. or return the (single) child element
+ else
+ {
+ uno::Reference< xml::dom::XNodeList> xChildNodes = rxNode->getChildNodes();
+
+ // ignore possible #text nodes
+ sal_Int32 nmax = xChildNodes->getLength();
+ for(sal_Int32 n=0; n < nmax; n++)
+ {
+ uno::Reference< xml::dom::XElement > xChildElement(xChildNodes->item(n), uno::UNO_QUERY);
+ if( xChildElement.is() )
+ {
+ /* Copy the content to a dedicated document since XXPathAPI->selectNodeList
+ * seems to evaluate expression always relative to the root node.
+ */
+ uno::Reference< xml::dom::XDocument > xUpdateXML = m_xDocumentBuilder->newDocument();
+ xUpdateXML->appendChild( xUpdateXML->importNode(xChildElement.get(), sal_True ) );
+ return xUpdateXML->getDocumentElement();
+ }
+ }
+ }
+
+ return uno::Reference< xml::dom::XElement > ();
+}
+
+//------------------------------------------------------------------------------
+
+uno::Reference< xml::dom::XNode >
+UpdateInformationProvider::getChildNode(const uno::Reference< xml::dom::XNode >& rxNode,
+ const rtl::OUString& rName)
+{
+ OSL_ASSERT(m_xXPathAPI.is());
+ try {
+ return m_xXPathAPI->selectSingleNode(rxNode, UNISTRING( "./atom:" ) + rName);
+ } catch (xml::xpath::XPathException &) {
+ // ignore
+ return 0;
+ }
+}
+
+//------------------------------------------------------------------------------
+
+uno::Reference< container::XEnumeration > SAL_CALL
+UpdateInformationProvider::getUpdateInformationEnumeration(
+ uno::Sequence< rtl::OUString > const & repositories,
+ rtl::OUString const & extensionId
+) throw (uno::Exception, uno::RuntimeException)
+{
+ OSL_ASSERT(m_xDocumentBuilder.is());
+
+ // reset cancelled flag
+ m_bCancelled.reset();
+
+ for(sal_Int32 n=0; n<repositories.getLength(); n++)
+ {
+ try
+ {
+ uno::Reference< xml::dom::XDocument > xDocument = m_xDocumentBuilder->parse(load(repositories[n]));
+ uno::Reference< xml::dom::XElement > xElement;
+
+ if( xDocument.is() )
+ xElement = xDocument->getDocumentElement();
+
+ if( xElement.is() )
+ {
+ if( xElement->getNodeName().equalsAsciiL("feed", 4) )
+ {
+ rtl::OUString aXPathExpression;
+
+ if( extensionId.getLength() > 0 )
+ aXPathExpression = UNISTRING("//atom:entry/atom:category[@term=\'") + extensionId + UNISTRING("\']/..");
+ else
+ aXPathExpression = UNISTRING("//atom:entry");
+
+ uno::Reference< xml::dom::XNodeList > xNodeList;
+ try {
+ xNodeList = m_xXPathAPI->selectNodeList(xDocument.get(),
+ aXPathExpression);
+ } catch (xml::xpath::XPathException &) {
+ // ignore
+ }
+
+ return new UpdateInformationEnumeration(xNodeList, this);
+ }
+ else
+ {
+ return new SingleUpdateInformationEnumeration(xElement);
+ }
+ }
+
+ if( m_bCancelled.check() )
+ break;
+ }
+ // rethrow runtime exceptions
+ catch( uno::RuntimeException const & ) { throw; }
+
+ // rethrow only if last url in the list
+ catch( uno::Exception const & )
+ {
+ if( n+1 >= repositories.getLength() )
+ throw;
+ }
+ }
+
+ return uno::Reference< container::XEnumeration >();
+}
+
+//------------------------------------------------------------------------------
+
+uno::Sequence< uno::Reference< xml::dom::XElement > > SAL_CALL
+UpdateInformationProvider::getUpdateInformation(
+ uno::Sequence< rtl::OUString > const & repositories,
+ rtl::OUString const & extensionId
+) throw (uno::Exception, uno::RuntimeException)
+{
+ uno::Reference< container::XEnumeration > xEnumeration(
+ getUpdateInformationEnumeration(repositories, extensionId)
+ );
+
+ uno::Sequence< uno::Reference< xml::dom::XElement > > aRet;
+
+ if( xEnumeration.is() )
+ {
+ while( xEnumeration->hasMoreElements() )
+ {
+ try
+ {
+ deployment::UpdateInformationEntry aEntry;
+ if( (xEnumeration->nextElement() >>= aEntry ) && aEntry.UpdateDocument.is() )
+ {
+ sal_Int32 n = aRet.getLength();
+ aRet.realloc(n + 1);
+ aRet[n] = aEntry.UpdateDocument;
+ }
+ }
+
+ catch( const lang::WrappedTargetException& e )
+ {
+ // command aborted, return what we have got so far
+ if( e.TargetException.isExtractableTo( ::cppu::UnoType< ::com::sun::star::ucb::CommandAbortedException >::get() ) )
+ {
+ break;
+ }
+
+ // ignore files that can't be loaded
+ }
+ }
+ }
+
+ return aRet;
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL
+UpdateInformationProvider::cancel() throw (uno::RuntimeException)
+{
+ m_bCancelled.set();
+
+ osl::MutexGuard aGuard(m_aMutex);
+ if( m_xCommandProcessor.is() )
+ m_xCommandProcessor->abort(m_nCommandId);
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL
+UpdateInformationProvider::setInteractionHandler(
+ uno::Reference< task::XInteractionHandler > const & handler )
+ throw (uno::RuntimeException)
+{
+ osl::MutexGuard aGuard(m_aMutex);
+ m_xInteractionHandler = handler;
+}
+
+//------------------------------------------------------------------------------
+
+uno::Reference< task::XInteractionHandler > SAL_CALL
+UpdateInformationProvider::getInteractionHandler()
+ throw ( uno::RuntimeException )
+{
+ osl::MutexGuard aGuard( m_aMutex );
+
+ if ( m_xInteractionHandler.is() )
+ return m_xInteractionHandler;
+ else
+ return this;
+}
+//------------------------------------------------------------------------------
+
+uno::Sequence< rtl::OUString >
+UpdateInformationProvider::getServiceNames()
+{
+ uno::Sequence< rtl::OUString > aServiceList(1);
+ aServiceList[0] = UNISTRING( "com.sun.star.deployment.UpdateInformationProvider");
+ return aServiceList;
+};
+
+//------------------------------------------------------------------------------
+
+rtl::OUString
+UpdateInformationProvider::getImplName()
+{
+ return UNISTRING( "vnd.sun.UpdateInformationProvider");
+}
+
+//------------------------------------------------------------------------------
+
+rtl::OUString SAL_CALL
+UpdateInformationProvider::getImplementationName() throw (uno::RuntimeException)
+{
+ return getImplName();
+}
+
+//------------------------------------------------------------------------------
+
+uno::Sequence< rtl::OUString > SAL_CALL
+UpdateInformationProvider::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return getServiceNames();
+}
+
+//------------------------------------------------------------------------------
+
+sal_Bool SAL_CALL
+UpdateInformationProvider::supportsService( rtl::OUString const & serviceName ) throw (uno::RuntimeException)
+{
+ uno::Sequence< rtl::OUString > aServiceNameList = getServiceNames();
+
+ for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ )
+ if( aServiceNameList[n].equals(serviceName) )
+ return sal_True;
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+
+void SAL_CALL UpdateInformationProvider::handle( uno::Reference< task::XInteractionRequest > const & rRequest)
+ throw (uno::RuntimeException)
+{
+ uno::Any aAnyRequest( rRequest->getRequest() );
+ ucb::AuthenticationRequest aAuthenticationRequest;
+
+ if ( aAnyRequest >>= aAuthenticationRequest )
+ {
+ uno::Sequence< uno::Reference< task::XInteractionContinuation > > xContinuations = rRequest->getContinuations();
+ uno::Reference< task::XInteractionHandler > xIH;
+ uno::Reference< ucb::XInteractionSupplyAuthentication > xSupplyAuthentication;
+ uno::Reference< task::XPasswordContainer > xContainer;
+
+ for ( sal_Int32 i = 0; i < xContinuations.getLength(); ++i )
+ {
+ xSupplyAuthentication = uno::Reference< ucb::XInteractionSupplyAuthentication >(
+ xContinuations[i], uno::UNO_QUERY );
+ if ( xSupplyAuthentication.is() )
+ break;
+ }
+
+ // xContainer works with userName passwdSequences pairs:
+ if ( xSupplyAuthentication.is() &&
+ aAuthenticationRequest.HasUserName &&
+ aAuthenticationRequest.HasPassword &&
+ initPasswordContainer( &xContainer ) )
+ {
+ xIH = getInteractionHandler();
+ try
+ {
+ if ( aAuthenticationRequest.UserName.getLength() == 0 )
+ {
+ task::UrlRecord aRec( xContainer->find( aAuthenticationRequest.ServerName, xIH ) );
+ if ( aRec.UserList.getLength() != 0 )
+ {
+ if ( xSupplyAuthentication->canSetUserName() )
+ xSupplyAuthentication->setUserName( aRec.UserList[0].UserName.getStr() );
+ if ( xSupplyAuthentication->canSetPassword() )
+ {
+ OSL_ENSURE( aRec.UserList[0].Passwords.getLength() != 0, "empty password list" );
+ xSupplyAuthentication->setPassword( aRec.UserList[0].Passwords[0].getStr() );
+ }
+ if ( aRec.UserList[0].Passwords.getLength() > 1 )
+ {
+ if ( aAuthenticationRequest.HasRealm )
+ {
+ if ( xSupplyAuthentication->canSetRealm() )
+ xSupplyAuthentication->setRealm( aRec.UserList[0].Passwords[1].getStr() );
+ }
+ else if ( xSupplyAuthentication->canSetAccount() )
+ xSupplyAuthentication->setAccount( aRec.UserList[0].Passwords[1].getStr() );
+ }
+ xSupplyAuthentication->select();
+ return;
+ }
+ }
+ else
+ {
+ task::UrlRecord aRec(xContainer->findForName( aAuthenticationRequest.ServerName,
+ aAuthenticationRequest.UserName,
+ xIH));
+ if ( aRec.UserList.getLength() != 0 )
+ {
+ OSL_ENSURE( aRec.UserList[0].Passwords.getLength() != 0, "empty password list" );
+ if ( !aAuthenticationRequest.HasPassword ||
+ ( aAuthenticationRequest.Password != aRec.UserList[0].Passwords[0] ) )
+ {
+ if ( xSupplyAuthentication->canSetUserName() )
+ xSupplyAuthentication->setUserName( aRec.UserList[0].UserName.getStr() );
+ if ( xSupplyAuthentication->canSetPassword() )
+ xSupplyAuthentication->setPassword(aRec.UserList[0].Passwords[0].getStr());
+ if ( aRec.UserList[0].Passwords.getLength() > 1 )
+ {
+ if ( aAuthenticationRequest.HasRealm )
+ {
+ if ( xSupplyAuthentication->canSetRealm() )
+ xSupplyAuthentication->setRealm(aRec.UserList[0].Passwords[1].getStr());
+ }
+ else if ( xSupplyAuthentication->canSetAccount() )
+ xSupplyAuthentication->setAccount(aRec.UserList[0].Passwords[1].getStr());
+ }
+ xSupplyAuthentication->select();
+ return;
+ }
+ }
+ }
+ }
+ catch (task::NoMasterException const &)
+ {} // user did not enter master password
+ }
+ }
+}
+
+} // anonymous namespace
+
+//------------------------------------------------------------------------------
+
+static uno::Reference<uno::XInterface> SAL_CALL
+createInstance(uno::Reference<uno::XComponentContext> const & xContext)
+{
+ return UpdateInformationProvider::createInstance(xContext);
+}
+
+//------------------------------------------------------------------------------
+
+static const cppu::ImplementationEntry kImplementations_entries[] =
+{
+ {
+ createInstance,
+ UpdateInformationProvider::getImplName,
+ UpdateInformationProvider::getServiceNames,
+ cppu::createSingleComponentFactory,
+ NULL,
+ 0
+ },
+ { NULL, NULL, NULL, NULL, NULL, 0 }
+} ;
+
+//------------------------------------------------------------------------------
+
+extern "C" void SAL_CALL
+component_getImplementationEnvironment( const sal_Char **aEnvTypeName, uno_Environment **)
+{
+ *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" sal_Bool SAL_CALL
+component_writeInfo(void *pServiceManager, void *pRegistryKey)
+{
+ return cppu::component_writeInfoHelper(
+ pServiceManager,
+ pRegistryKey,
+ kImplementations_entries
+ );
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" void *
+component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
+{
+ return cppu::component_getFactoryHelper(
+ pszImplementationName,
+ pServiceManager,
+ pRegistryKey,
+ kImplementations_entries) ;
+}
+
diff --git a/extensions/source/update/feed/updatefeed.xml b/extensions/source/update/feed/updatefeed.xml
new file mode 100644
index 000000000000..1b0557db3db2
--- /dev/null
+++ b/extensions/source/update/feed/updatefeed.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd">
+<module-description xmlns:xlink="http://www.w3.org/1999/xlink">
+ <module-name>updatefeed</module-name>
+ <component-description>
+ <author> Oliver Braun </author>
+ <name>vnd.sun.UpdateCheck</name>
+ <description> The </description>
+ <loader-name>com.sun.star.loader.SharedLibrary</loader-name>
+ <language>c++</language>
+ <status value="beta"/>
+ <supported-service>com.sun.star.deployment.UpdateInformationProvider</supported-service>
+ <service-dependency>...</service-dependency>
+ <type>com.sun.star.beans.NamedValue</type>
+ <type>com.sun.star.beans.PropertyValue</type>
+ <type>com.sun.star.container.XNameReplace</type>
+ <type>com.sun.star.deployment.UpdateInformationProvider</type>
+ <type>com.sun.star.io.XInputStream</type>
+ <type>com.sun.star.io.XOutputStream</type>
+ <type>com.sun.star.lang.XComponent</type>
+ <type>com.sun.star.lang.XInitialization</type>
+ <type>com.sun.star.lang.XMultiComponentFactory</type>
+ <type>com.sun.star.lang.XMultiServiceFactory</type>
+ <type>com.sun.star.lang.XServiceInfo</type>
+ <type>com.sun.star.lang.XSingleComponentFactory</type>
+ <type>com.sun.star.lang.XSingleServiceFactory</type>
+ <type>com.sun.star.lang.XTypeProvider</type>
+ <type>com.sun.star.registry.XRegistryKey</type>
+ <type>com.sun.star.task.XInteractionHandler</type>
+ <type>com.sun.star.ucb.PostCommandArgument2</type>
+ <type>com.sun.star.ucb.XCommandEnvironment</type>
+ <type>com.sun.star.ucb.XCommandProcessor2</type>
+ <type>com.sun.star.ucb.XContentIdentifierFactory</type>
+ <type>com.sun.star.ucb.XContentProvider</type>
+ <type>com.sun.star.ucb.XProgressHandler</type>
+ <type>com.sun.star.uno.TypeClass</type>
+ <type>com.sun.star.uno.XAggregation</type>
+ <type>com.sun.star.uno.XComponentContext</type>
+ <type>com.sun.star.uno.XCurrentContext</type>
+ <type>com.sun.star.uno.XWeak</type>
+ <type>com.sun.star.util.XChangesBatch</type>
+ </component-description>
+ <project-build-dependency>cppuhelper</project-build-dependency>
+ <project-build-dependency>cppu</project-build-dependency>
+ <project-build-dependency>sal</project-build-dependency>
+ <runtime-module-dependency>cppuhelper3$(COM)</runtime-module-dependency>
+ <runtime-module-dependency>cppu3</runtime-module-dependency>
+ <runtime-module-dependency>sal3</runtime-module-dependency>
+</module-description>
diff --git a/extensions/source/update/tools/makefile.mk b/extensions/source/update/tools/makefile.mk
new file mode 100644
index 000000000000..1abf7817aa27
--- /dev/null
+++ b/extensions/source/update/tools/makefile.mk
@@ -0,0 +1,72 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.3 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ = ..$/..$/..
+PRJNAME = extensions
+TARGET = ztool
+LIBTARGET = NO
+TARGETTYPE = CUI
+ENABLE_EXCEPTIONS=TRUE
+
+.INCLUDE: settings.mk
+
+OBJFILES = \
+ $(OBJ)$/ztool.obj
+
+APP1TARGET = ztool
+APP1OBJS = $(OBJ)$/ztool.obj
+APP1STDLIBS = $(TOOLSLIB)
+
+#APP1TARGET = ztool
+#APP1OBJS = $(OBJ)$/ztool.obj
+#.IF "$(GUI)" == "UNX"
+#APP1STDLIBS = $(TOOLSLIB)
+#.ELSE
+#APP1LIBS = $(LB)$/itools.lib
+#.ENDIF
+
+#APP2TARGET = urltest
+#APP2OBJS = $(OBJ)$/urltest.obj
+#.IF "$(GUI)" == "UNX"
+#APP2STDLIBS = $(TOOLSLIB) $(VOSLIB) $(SALLIB) $(CPPULIB) $(CPPUHELPERLIB)
+#.ELSE
+#APP2STDLIBS = $(LB)$/itools.lib ivos.lib isal.lib icppu.lib icppuhelper.lib
+#.ENDIF
+
+# APP3TARGET = tldem
+# APP3OBJS = $(OBJ)$/tldem.obj
+# .IF "$(GUI)" == "UNX"
+# APP3STDLIBS = $(TOOLSLIB)
+# .ELSE
+# APP3STDLIBS = $(LB)$/itools.lib
+# .ENDIF
+
+.INCLUDE: target.mk
diff --git a/extensions/source/update/tools/ztool.cxx b/extensions/source/update/tools/ztool.cxx
new file mode 100644
index 000000000000..2408b6bf65ce
--- /dev/null
+++ b/extensions/source/update/tools/ztool.cxx
@@ -0,0 +1,66 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ztool.cxx,v $
+ * $Revision: 1.3 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include <stdio.h>
+
+#include <tools/stream.hxx>
+#include <tools/zcodec.hxx>
+
+void show_usage()
+{
+ fputs("ztool usage: ztool <source> <dest>\n", stderr);
+}
+
+int
+#ifdef WNT
+__cdecl
+#endif
+main( int argc, char **argv )
+{
+ if ( argc != 3 )
+ {
+ show_usage();
+ return -1;
+ }
+ UniString aInName = UniString::CreateFromAscii( argv[1] );
+ UniString aOutName = UniString::CreateFromAscii( argv[2] );
+ SvFileStream aInFile( aInName, STREAM_READ );
+ SvFileStream aOutFile( aOutName, STREAM_WRITE | STREAM_TRUNC );
+
+ ZCodec aCompressor;
+ aCompressor.BeginCompression();
+ aCompressor.Compress( aInFile, aOutFile );
+ aCompressor.EndCompression();
+
+ return 0;
+}
+
+
diff --git a/extensions/source/update/ui/makefile.mk b/extensions/source/update/ui/makefile.mk
new file mode 100644
index 000000000000..135e7e1e730f
--- /dev/null
+++ b/extensions/source/update/ui/makefile.mk
@@ -0,0 +1,78 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2008 by Sun Microsystems, Inc.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# $RCSfile: makefile.mk,v $
+#
+# $Revision: 1.6 $
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+PRJ=..$/..$/..
+
+PRJNAME=extensions
+TARGET=updchkui
+
+LIBTARGET=NO
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings ---
+
+.INCLUDE : settings.mk
+
+# --- Files ---
+
+SLOFILES=\
+ $(SLO)$/updatecheckui.obj
+
+SRS1NAME=$(TARGET)
+SRC1FILES=\
+ updatecheckui.src
+
+RESLIB1NAME=updchk
+RESLIB1IMAGES=$(PRJ)$/source$/update$/ui
+RESLIB1SRSFILES= $(SRS)$/updchkui.srs
+RESLIB1DEPN= updatecheckui.src updatecheckui.hrc
+
+SHL1NOCHECK=TRUE
+SHL1TARGET=updchk$(DLLPOSTFIX)
+SHL1OBJS=$(SLOFILES)
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+
+SHL1IMPLIB=i$(SHL1TARGET)
+SHL1STDLIBS= \
+ $(COMPHELPERLIB) \
+ $(CPPUHELPERLIB) \
+ $(CPPULIB) \
+ $(SALLIB) \
+ $(VCLLIB) \
+ $(TOOLSLIB)
+
+SHL1VERSIONMAP=..$/exports.map
+SHL1DEF=$(MISC)$/$(SHL1TARGET).def
+DEF1NAME=$(SHL1TARGET)
+
+# --- Targets ---
+
+.INCLUDE : target.mk
+
diff --git a/extensions/source/update/ui/updatecheckui.cxx b/extensions/source/update/ui/updatecheckui.cxx
new file mode 100644
index 000000000000..c5ac7f485ca4
--- /dev/null
+++ b/extensions/source/update/ui/updatecheckui.cxx
@@ -0,0 +1,1086 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatecheckui.cxx,v $
+ * $Revision: 1.19.18.2 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+
+#include <list>
+
+#include <cppuhelper/implbase3.hxx>
+#include <cppuhelper/implementationentry.hxx>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/lang/XComponent.hpp>
+#include <com/sun/star/document/XEventListener.hpp>
+#include <com/sun/star/document/XEventBroadcaster.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/graphic/XGraphicProvider.hpp>
+#include <com/sun/star/task/XJob.hpp>
+
+#include <comphelper/processfactory.hxx>
+
+#include <vos/mutex.hxx>
+#include <osl/mutex.hxx>
+
+#include <vcl/window.hxx>
+#include <vcl/floatwin.hxx>
+#include <vcl/timer.hxx>
+#include <vcl/menu.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/msgbox.hxx>
+#include <vcl/lineinfo.hxx>
+#include <vcl/imagebtn.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+#include <sfx2/sfx.hrc>
+#include "rtl/ustrbuf.hxx"
+
+#include "updatecheckui.hrc"
+
+#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
+
+#define MSG_ERR_NO_WEBBROWSER_FOUND (RID_SFX_APP_START + 7)
+#define DEFAULT_MENUBAR_HEIGHT 24
+
+#define PROPERTY_TITLE RTL_CONSTASCII_STRINGPARAM("BubbleHeading")
+#define PROPERTY_TEXT RTL_CONSTASCII_STRINGPARAM("BubbleText")
+#define PROPERTY_IMAGE RTL_CONSTASCII_STRINGPARAM("BubbleImageURL")
+#define PROPERTY_SHOW_BUBBLE RTL_CONSTASCII_STRINGPARAM("BubbleVisible")
+#define PROPERTY_CLICK_HDL RTL_CONSTASCII_STRINGPARAM("MenuClickHDL")
+#define PROPERTY_SHOW_MENUICON RTL_CONSTASCII_STRINGPARAM("MenuIconVisible")
+
+#define START_TIMER 1
+
+using namespace ::com::sun::star;
+
+//------------------------------------------------------------------------------
+
+static uno::Sequence< rtl::OUString > getServiceNames()
+{
+ uno::Sequence< rtl::OUString > aServiceList(1);
+ aServiceList[0] = UNISTRING( "com.sun.star.setup.UpdateCheckUI");
+ return aServiceList;
+}
+
+//------------------------------------------------------------------------------
+
+static rtl::OUString getImplementationName()
+{
+ return UNISTRING( "vnd.sun.UpdateCheckUI");
+}
+
+//------------------------------------------------------------------------------
+
+namespace
+{
+
+//------------------------------------------------------------------------------
+class BubbleWindow : public FloatingWindow
+{
+ Point maTipPos;
+ Region maBounds;
+ Polygon maRectPoly;
+ Polygon maTriPoly;
+ XubString maBubbleTitle;
+ XubString maBubbleText;
+ Image maBubbleImage;
+ Size maMaxTextSize;
+ Rectangle maTitleRect;
+ Rectangle maTextRect;
+ long mnTipOffset;
+
+private:
+ void RecalcTextRects();
+
+public:
+ BubbleWindow( Window* pParent, const XubString& rTitle,
+ const XubString& rText, const Image& rImage );
+ ~BubbleWindow();
+
+ virtual void MouseButtonDown( const MouseEvent& rMEvt );
+ virtual void Paint( const Rectangle& rRect );
+ void Resize();
+ void Show( BOOL bVisible = TRUE, USHORT nFlags = SHOW_NOACTIVATE );
+ void SetTipPosPixel( const Point& rTipPos ) { maTipPos = rTipPos; }
+ void SetTitleAndText( const XubString& rTitle, const XubString& rText,
+ const Image& rImage );
+};
+
+//------------------------------------------------------------------------------
+class UpdateCheckUI : public ::cppu::WeakImplHelper3
+ < lang::XServiceInfo, document::XEventListener, beans::XPropertySet >
+{
+ uno::Reference< uno::XComponentContext > m_xContext;
+ uno::Reference< task::XJob > mrJob;
+ rtl::OUString maBubbleTitle;
+ rtl::OUString maBubbleText;
+ rtl::OUString maBubbleImageURL;
+ Image maBubbleImage;
+ BubbleWindow* mpBubbleWin;
+ SystemWindow* mpIconSysWin;
+ MenuBar* mpIconMBar;
+ ResMgr* mpUpdResMgr;
+ ResMgr* mpSfxResMgr;
+ Timer maWaitTimer;
+ Timer maTimeoutTimer;
+ Link maWindowEventHdl;
+ Link maApplicationEventHdl;
+ bool mbShowBubble;
+ bool mbShowMenuIcon;
+ bool mbBubbleChanged;
+ USHORT mnIconID;
+
+private:
+ DECL_LINK( ClickHdl, USHORT* );
+ DECL_LINK( HighlightHdl, MenuBar::MenuBarButtonCallbackArg* );
+ DECL_LINK( WaitTimeOutHdl, Timer* );
+ DECL_LINK( TimeOutHdl, Timer* );
+ DECL_LINK( UserEventHdl, UpdateCheckUI* );
+ DECL_LINK( WindowEventHdl, VclWindowEvent* );
+ DECL_LINK( ApplicationEventHdl, VclSimpleEvent* );
+
+ BubbleWindow* GetBubbleWindow();
+ void RemoveBubbleWindow( bool bRemoveIcon );
+ Image GetMenuBarIcon( MenuBar* pMBar );
+ void AddMenuBarIcon( SystemWindow* pSysWin, bool bAddEventHdl );
+ Image GetBubbleImage( ::rtl::OUString &rURL );
+
+ uno::Reference< document::XEventBroadcaster > getGlobalEventBroadcaster() const
+ throw (uno::RuntimeException);
+
+public:
+ UpdateCheckUI(const uno::Reference<uno::XComponentContext>&);
+ virtual ~UpdateCheckUI();
+
+ // XServiceInfo
+ virtual rtl::OUString SAL_CALL getImplementationName()
+ throw (uno::RuntimeException);
+ virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName)
+ throw (uno::RuntimeException);
+ virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames()
+ throw (uno::RuntimeException);
+
+ // XEventListener
+ virtual void SAL_CALL notifyEvent(const document::EventObject& Event)
+ throw (uno::RuntimeException);
+ virtual void SAL_CALL disposing(const lang::EventObject& Event)
+ throw (uno::RuntimeException);
+
+ //XPropertySet
+ virtual uno::Reference< beans::XPropertySetInfo > SAL_CALL getPropertySetInfo(void)
+ throw ( uno::RuntimeException );
+ virtual void SAL_CALL setPropertyValue(const rtl::OUString& PropertyName, const uno::Any& aValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException );
+ virtual uno::Any SAL_CALL getPropertyValue(const rtl::OUString& PropertyName)
+ throw ( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
+ virtual void SAL_CALL addPropertyChangeListener(const rtl::OUString& PropertyName,
+ const uno::Reference< beans::XPropertyChangeListener > & aListener)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
+ virtual void SAL_CALL removePropertyChangeListener(const rtl::OUString& PropertyName,
+ const uno::Reference< beans::XPropertyChangeListener > & aListener)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
+ virtual void SAL_CALL addVetoableChangeListener(const rtl::OUString& PropertyName,
+ const uno::Reference< beans::XVetoableChangeListener > & aListener)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
+ virtual void SAL_CALL removeVetoableChangeListener(const rtl::OUString& PropertyName,
+ const uno::Reference< beans::XVetoableChangeListener > & aListener)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException );
+};
+
+//------------------------------------------------------------------------------
+UpdateCheckUI::UpdateCheckUI(const uno::Reference<uno::XComponentContext>& xContext) :
+ m_xContext(xContext)
+ , mpBubbleWin( NULL )
+ , mpIconSysWin( NULL )
+ , mpIconMBar( NULL )
+ , mbShowBubble( false )
+ , mbShowMenuIcon( false )
+ , mbBubbleChanged( false )
+ , mnIconID( 0 )
+{
+ mpUpdResMgr = ResMgr::CreateResMgr( "updchk" );
+ mpSfxResMgr = ResMgr::CreateResMgr( "sfx" );
+
+ maBubbleImage = GetBubbleImage( maBubbleImageURL );
+
+ maWaitTimer.SetTimeout( 400 );
+ maWaitTimer.SetTimeoutHdl( LINK( this, UpdateCheckUI, WaitTimeOutHdl ) );
+
+ maTimeoutTimer.SetTimeout( 10000 );
+ maTimeoutTimer.SetTimeoutHdl( LINK( this, UpdateCheckUI, TimeOutHdl ) );
+
+ uno::Reference< document::XEventBroadcaster > xBroadcaster( getGlobalEventBroadcaster() );
+ xBroadcaster->addEventListener( this );
+
+ maWindowEventHdl = LINK( this, UpdateCheckUI, WindowEventHdl );
+ maApplicationEventHdl = LINK( this, UpdateCheckUI, ApplicationEventHdl );
+ Application::AddEventListener( maApplicationEventHdl );
+}
+
+//------------------------------------------------------------------------------
+UpdateCheckUI::~UpdateCheckUI()
+{
+ Application::RemoveEventListener( maApplicationEventHdl );
+ RemoveBubbleWindow( true );
+ delete mpUpdResMgr;
+ delete mpSfxResMgr;
+}
+
+//------------------------------------------------------------------------------
+uno::Reference<document::XEventBroadcaster>
+UpdateCheckUI::getGlobalEventBroadcaster() const throw (uno::RuntimeException)
+{
+ if( !m_xContext.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheckUI: empty component context" ),
+ uno::Reference< uno::XInterface >() );
+
+ uno::Reference< lang::XMultiComponentFactory > xServiceManager(m_xContext->getServiceManager());
+
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheckUI: unable to obtain service manager from component context" ),
+ uno::Reference< uno::XInterface >() );
+
+ return uno::Reference<document::XEventBroadcaster> (
+ xServiceManager->createInstanceWithContext(
+ UNISTRING( "com.sun.star.frame.GlobalEventBroadcaster" ),
+ m_xContext),
+ uno::UNO_QUERY_THROW);
+}
+
+//------------------------------------------------------------------------------
+rtl::OUString SAL_CALL
+UpdateCheckUI::getImplementationName() throw (uno::RuntimeException)
+{
+ return ::getImplementationName();
+}
+
+//------------------------------------------------------------------------------
+uno::Sequence< rtl::OUString > SAL_CALL
+UpdateCheckUI::getSupportedServiceNames() throw (uno::RuntimeException)
+{
+ return ::getServiceNames();
+}
+
+//------------------------------------------------------------------------------
+sal_Bool SAL_CALL
+UpdateCheckUI::supportsService( rtl::OUString const & serviceName ) throw (uno::RuntimeException)
+{
+ uno::Sequence< rtl::OUString > aServiceNameList = ::getServiceNames();
+
+ for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ )
+ if( aServiceNameList[n].equals(serviceName) )
+ return sal_True;
+
+ return sal_False;
+}
+
+//------------------------------------------------------------------------------
+Image UpdateCheckUI::GetMenuBarIcon( MenuBar* pMBar )
+{
+ sal_uInt32 nResID;
+ Window *pMBarWin = pMBar->GetWindow();
+ sal_uInt32 nMBarHeight = 20;
+
+ if ( pMBarWin )
+ nMBarHeight = pMBarWin->GetOutputSizePixel().getHeight();
+
+ if ( Application::GetSettings().GetStyleSettings().GetHighContrastMode() ) {
+ if ( nMBarHeight >= 35 )
+ nResID = RID_UPDATE_AVAILABLE_26_HC;
+ else
+ nResID = RID_UPDATE_AVAILABLE_16_HC;
+ } else {
+ if ( nMBarHeight >= 35 )
+ nResID = RID_UPDATE_AVAILABLE_26;
+ else
+ nResID = RID_UPDATE_AVAILABLE_16;
+ }
+
+ return Image( ResId( nResID, *mpUpdResMgr ) );
+}
+
+//------------------------------------------------------------------------------
+Image UpdateCheckUI::GetBubbleImage( ::rtl::OUString &rURL )
+{
+ Image aImage;
+
+ if ( maBubbleImageURL.getLength() != 0 )
+ {
+ uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
+
+ if( !xServiceManager.is() )
+ throw uno::RuntimeException(
+ UNISTRING( "UpdateCheckUI: unable to obtain service manager from component context" ),
+ uno::Reference< uno::XInterface >() );
+
+ try
+ {
+ uno::Reference< graphic::XGraphicProvider > xGraphProvider(
+ xServiceManager->createInstance(
+ ::rtl::OUString::createFromAscii( "com.sun.star.graphic.GraphicProvider" ) ),
+ uno::UNO_QUERY );
+ if ( xGraphProvider.is() )
+ {
+ uno::Sequence< beans::PropertyValue > aMediaProps( 1 );
+ aMediaProps[0].Name = ::rtl::OUString::createFromAscii( "URL" );
+ aMediaProps[0].Value <<= rURL;
+
+ uno::Reference< graphic::XGraphic > xGraphic = xGraphProvider->queryGraphic( aMediaProps );
+ if ( xGraphic.is() )
+ {
+ aImage = Image( xGraphic );
+ }
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+
+ if ( aImage.GetSizePixel().Width() == 0 )
+ aImage = InfoBox::GetStandardImage();
+
+ return aImage;
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheckUI::AddMenuBarIcon( SystemWindow *pSysWin, bool bAddEventHdl )
+{
+ if ( ! mbShowMenuIcon )
+ return;
+
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ MenuBar *pActiveMBar = pSysWin->GetMenuBar();
+ if ( ( pSysWin != mpIconSysWin ) || ( pActiveMBar != mpIconMBar ) )
+ {
+ if ( bAddEventHdl && mpIconSysWin )
+ mpIconSysWin->RemoveEventListener( maWindowEventHdl );
+
+ RemoveBubbleWindow( true );
+
+ if ( pActiveMBar )
+ {
+ rtl::OUStringBuffer aBuf;
+ if( maBubbleTitle.getLength() )
+ aBuf.append( maBubbleTitle );
+ if( maBubbleText.getLength() )
+ {
+ if( maBubbleTitle.getLength() )
+ aBuf.appendAscii( "\n\n" );
+ aBuf.append( maBubbleText );
+ }
+
+ Image aImage = GetMenuBarIcon( pActiveMBar );
+ mnIconID = pActiveMBar->AddMenuBarButton( aImage,
+ LINK( this, UpdateCheckUI, ClickHdl ),
+ aBuf.makeStringAndClear()
+ );
+ pActiveMBar->SetMenuBarButtonHighlightHdl( mnIconID,
+ LINK( this, UpdateCheckUI, HighlightHdl ) );
+ }
+ mpIconMBar = pActiveMBar;
+ mpIconSysWin = pSysWin;
+ if ( bAddEventHdl && mpIconSysWin )
+ mpIconSysWin->AddEventListener( maWindowEventHdl );
+ }
+
+ if ( mbShowBubble && pActiveMBar )
+ {
+ mpBubbleWin = GetBubbleWindow();
+ if ( mpBubbleWin )
+ {
+ mpBubbleWin->Show( TRUE );
+ maTimeoutTimer.Start();
+ }
+ mbShowBubble = false;
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL UpdateCheckUI::notifyEvent(const document::EventObject& rEvent)
+ throw (uno::RuntimeException)
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ if( rEvent.EventName.compareToAscii( RTL_CONSTASCII_STRINGPARAM("OnPrepareViewClosing") ) == 0 )
+ {
+ RemoveBubbleWindow( true );
+ }
+}
+
+//------------------------------------------------------------------------------
+void SAL_CALL UpdateCheckUI::disposing(const lang::EventObject&)
+ throw (uno::RuntimeException)
+{
+}
+
+//------------------------------------------------------------------------------
+uno::Reference< beans::XPropertySetInfo > UpdateCheckUI::getPropertySetInfo(void)
+ throw ( uno::RuntimeException )
+{
+ return NULL;
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheckUI::setPropertyValue(const rtl::OUString& rPropertyName,
+ const uno::Any& rValue)
+ throw( beans::UnknownPropertyException, beans::PropertyVetoException,
+ lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException)
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ rtl::OUString aString;
+
+ if( rPropertyName.compareToAscii( PROPERTY_TITLE ) == 0 ) {
+ rValue >>= aString;
+ if ( aString != maBubbleTitle ) {
+ maBubbleTitle = aString;
+ mbBubbleChanged = true;
+ }
+ }
+ else if( rPropertyName.compareToAscii( PROPERTY_TEXT ) == 0 ) {
+ rValue >>= aString;
+ if ( aString != maBubbleText ) {
+ maBubbleText = aString;
+ mbBubbleChanged = true;
+ }
+ }
+ else if( rPropertyName.compareToAscii( PROPERTY_IMAGE ) == 0 ) {
+ rValue >>= aString;
+ if ( aString != maBubbleImageURL ) {
+ maBubbleImageURL = aString;
+ maBubbleImage = GetBubbleImage( maBubbleImageURL );
+ mbBubbleChanged = true;
+ }
+ }
+ else if( rPropertyName.compareToAscii( PROPERTY_SHOW_BUBBLE ) == 0 ) {
+ rValue >>= mbShowBubble;
+ if ( mbShowBubble )
+ Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
+ else if ( mpBubbleWin )
+ mpBubbleWin->Show( FALSE );
+ }
+ else if( rPropertyName.compareToAscii( PROPERTY_CLICK_HDL ) == 0 ) {
+ uno::Reference< task::XJob > aJob;
+ rValue >>= aJob;
+ if ( aJob.is() )
+ mrJob = aJob;
+ else
+ throw lang::IllegalArgumentException();
+ }
+ else if (rPropertyName.compareToAscii( PROPERTY_SHOW_MENUICON ) == 0) {
+ bool bShowMenuIcon = sal_False;
+ rValue >>= bShowMenuIcon;
+ if ( bShowMenuIcon != mbShowMenuIcon )
+ {
+ mbShowMenuIcon = bShowMenuIcon;
+ if ( bShowMenuIcon )
+ Application::PostUserEvent( LINK( this, UpdateCheckUI, UserEventHdl ) );
+ else
+ RemoveBubbleWindow( true );
+ }
+ }
+ else
+ throw beans::UnknownPropertyException();
+
+ if ( mbBubbleChanged && mpBubbleWin )
+ mpBubbleWin->Show( FALSE );
+}
+
+//------------------------------------------------------------------------------
+uno::Any UpdateCheckUI::getPropertyValue(const rtl::OUString& rPropertyName)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ uno::Any aRet;
+
+ if( rPropertyName.compareToAscii( PROPERTY_TITLE ) == 0 )
+ aRet = uno::makeAny( maBubbleTitle );
+ else if( rPropertyName.compareToAscii( PROPERTY_TEXT ) == 0 )
+ aRet = uno::makeAny( maBubbleText );
+ else if( rPropertyName.compareToAscii( PROPERTY_SHOW_BUBBLE ) == 0 )
+ aRet = uno::makeAny( mbShowBubble );
+ else if( rPropertyName.compareToAscii( PROPERTY_IMAGE ) == 0 )
+ aRet = uno::makeAny( maBubbleImageURL );
+ else if( rPropertyName.compareToAscii( PROPERTY_CLICK_HDL ) == 0 )
+ aRet = uno::makeAny( mrJob );
+ else if( rPropertyName.compareToAscii( PROPERTY_SHOW_MENUICON ) == 0 )
+ aRet = uno::makeAny( mbShowMenuIcon );
+ else
+ throw beans::UnknownPropertyException();
+
+ return aRet;
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheckUI::addPropertyChangeListener( const rtl::OUString& /*aPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ //no bound properties
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheckUI::removePropertyChangeListener( const rtl::OUString& /*aPropertyName*/,
+ const uno::Reference< beans::XPropertyChangeListener > & /*aListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ //no bound properties
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheckUI::addVetoableChangeListener( const rtl::OUString& /*aPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ //no vetoable properties
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheckUI::removeVetoableChangeListener( const rtl::OUString& /*aPropertyName*/,
+ const uno::Reference< beans::XVetoableChangeListener > & /*aListener*/)
+ throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException )
+{
+ //no vetoable properties
+}
+
+
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+BubbleWindow * UpdateCheckUI::GetBubbleWindow()
+{
+ if ( !mpIconSysWin )
+ return NULL;
+
+ Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
+ if( aIconRect.IsEmpty() )
+ return NULL;
+
+ BubbleWindow* pBubbleWin = mpBubbleWin;
+
+ if ( !pBubbleWin ) {
+ pBubbleWin = new BubbleWindow( mpIconSysWin,
+ XubString( maBubbleTitle ),
+ XubString( maBubbleText ),
+ maBubbleImage );
+ mbBubbleChanged = false;
+ }
+ else if ( mbBubbleChanged ) {
+ pBubbleWin->SetTitleAndText( XubString( maBubbleTitle ),
+ XubString( maBubbleText ),
+ maBubbleImage );
+ mbBubbleChanged = false;
+ }
+
+ Point aWinPos = aIconRect.BottomCenter();
+
+ pBubbleWin->SetTipPosPixel( aWinPos );
+
+ return pBubbleWin;
+}
+
+//------------------------------------------------------------------------------
+void UpdateCheckUI::RemoveBubbleWindow( bool bRemoveIcon )
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ maWaitTimer.Stop();
+ maTimeoutTimer.Stop();
+
+ if ( mpBubbleWin )
+ {
+ delete mpBubbleWin;
+ mpBubbleWin = NULL;
+ }
+
+ if ( bRemoveIcon )
+ {
+ try {
+ if ( mpIconMBar && ( mnIconID != 0 ) )
+ {
+ mpIconMBar->RemoveMenuBarButton( mnIconID );
+ mpIconMBar = NULL;
+ mnIconID = 0;
+ }
+ }
+ catch ( ... ) {
+ mpIconMBar = NULL;
+ mnIconID = 0;
+ }
+
+ mpIconSysWin = NULL;
+ }
+}
+
+// -----------------------------------------------------------------------
+IMPL_LINK( UpdateCheckUI, ClickHdl, USHORT*, EMPTYARG )
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ maWaitTimer.Stop();
+ if ( mpBubbleWin )
+ mpBubbleWin->Show( FALSE );
+
+ if ( mrJob.is() )
+ {
+ try {
+ uno::Sequence<beans::NamedValue> aEmpty;
+ mrJob->execute( aEmpty );
+ }
+ catch(const uno::Exception&) {
+ ErrorBox( NULL, ResId( MSG_ERR_NO_WEBBROWSER_FOUND, *mpSfxResMgr )).Execute();
+ }
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+IMPL_LINK( UpdateCheckUI, HighlightHdl, MenuBar::MenuBarButtonCallbackArg*, pData )
+{
+ if ( pData->bHighlight )
+ maWaitTimer.Start();
+ else
+ RemoveBubbleWindow( false );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+IMPL_LINK( UpdateCheckUI, WaitTimeOutHdl, Timer*, EMPTYARG )
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ mpBubbleWin = GetBubbleWindow();
+
+ if ( mpBubbleWin )
+ {
+ mpBubbleWin->Show();
+ }
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+IMPL_LINK( UpdateCheckUI, TimeOutHdl, Timer*, EMPTYARG )
+{
+ RemoveBubbleWindow( false );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+IMPL_LINK( UpdateCheckUI, UserEventHdl, UpdateCheckUI*, EMPTYARG )
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ Window *pTopWin = Application::GetFirstTopLevelWindow();
+ Window *pActiveWin = Application::GetActiveTopWindow();
+ SystemWindow *pActiveSysWin = NULL;
+
+ Window *pBubbleWin = NULL;
+ if ( mpBubbleWin )
+ pBubbleWin = mpBubbleWin;
+
+ if ( pActiveWin && ( pActiveWin != pBubbleWin ) && pActiveWin->IsTopWindow() )
+ pActiveSysWin = pActiveWin->GetSystemWindow();
+
+ if ( pActiveWin == pBubbleWin )
+ pActiveSysWin = NULL;
+
+ while ( !pActiveSysWin && pTopWin )
+ {
+ if ( ( pTopWin != pBubbleWin ) && pTopWin->IsTopWindow() )
+ pActiveSysWin = pTopWin->GetSystemWindow();
+ if ( !pActiveSysWin )
+ pTopWin = Application::GetNextTopLevelWindow( pTopWin );
+ }
+
+ if ( pActiveSysWin )
+ AddMenuBarIcon( pActiveSysWin, true );
+
+ return 0;
+}
+
+// -----------------------------------------------------------------------
+IMPL_LINK( UpdateCheckUI, WindowEventHdl, VclWindowEvent*, pEvent )
+{
+ ULONG nEventID = pEvent->GetId();
+
+ if ( VCLEVENT_OBJECT_DYING == nEventID )
+ {
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( mpIconSysWin == pEvent->GetWindow() )
+ {
+ mpIconSysWin->RemoveEventListener( maWindowEventHdl );
+ RemoveBubbleWindow( true );
+ }
+ }
+ else if ( VCLEVENT_WINDOW_MENUBARADDED == nEventID )
+ {
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+ Window *pWindow = pEvent->GetWindow();
+ if ( pWindow )
+ {
+ SystemWindow *pSysWin = pWindow->GetSystemWindow();
+ if ( pSysWin )
+ {
+ AddMenuBarIcon( pSysWin, false );
+ }
+ }
+ }
+ else if ( VCLEVENT_WINDOW_MENUBARREMOVED == nEventID )
+ {
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+ MenuBar *pMBar = (MenuBar*) pEvent->GetData();
+ if ( pMBar && ( pMBar == mpIconMBar ) )
+ RemoveBubbleWindow( true );
+ }
+ else if ( ( nEventID == VCLEVENT_WINDOW_MOVE ) ||
+ ( nEventID == VCLEVENT_WINDOW_RESIZE ) )
+ {
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+ if ( ( mpIconSysWin == pEvent->GetWindow() ) &&
+ ( mpBubbleWin != NULL ) && ( mpIconMBar != NULL ) )
+ {
+ Rectangle aIconRect = mpIconMBar->GetMenuBarButtonRectPixel( mnIconID );
+ Point aWinPos = aIconRect.BottomCenter();
+ mpBubbleWin->SetTipPosPixel( aWinPos );
+ if ( mpBubbleWin->IsVisible() )
+ mpBubbleWin->Show(); // This will recalc the screen positon of the bubble
+ }
+ }
+
+ return 0;
+}
+
+//------------------------------------------------------------------------------
+IMPL_LINK( UpdateCheckUI, ApplicationEventHdl, VclSimpleEvent *, pEvent)
+{
+ switch (pEvent->GetId())
+ {
+ case VCLEVENT_WINDOW_SHOW:
+ case VCLEVENT_WINDOW_ACTIVATE:
+ case VCLEVENT_WINDOW_GETFOCUS: {
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ Window *pWindow = static_cast< VclWindowEvent * >(pEvent)->GetWindow();
+ if ( pWindow && pWindow->IsTopWindow() )
+ {
+ SystemWindow *pSysWin = pWindow->GetSystemWindow();
+ MenuBar *pMBar = pSysWin->GetMenuBar();
+ if ( pSysWin && pMBar )
+ {
+ AddMenuBarIcon( pSysWin, true );
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+#define TIP_HEIGHT 15
+#define TIP_WIDTH 7
+#define TIP_RIGHT_OFFSET 18
+#define BUBBLE_BORDER 10
+#define TEXT_MAX_WIDTH 300
+#define TEXT_MAX_HEIGHT 200
+#define INITIAL_SHOW_TIME 10000
+
+//------------------------------------------------------------------------------
+BubbleWindow::BubbleWindow( Window* pParent, const XubString& rTitle,
+ const XubString& rText, const Image& rImage )
+ : FloatingWindow( pParent, WB_SYSTEMWINDOW
+ | WB_OWNERDRAWDECORATION
+ | WB_NOBORDER
+ )
+ , maBubbleTitle( rTitle )
+ , maBubbleText( rText )
+ , maBubbleImage( rImage )
+ , maMaxTextSize( TEXT_MAX_WIDTH, TEXT_MAX_HEIGHT )
+ , mnTipOffset( 0 )
+{
+ SetBackground( Wallpaper( GetSettings().GetStyleSettings().GetHelpColor() ) );
+}
+
+//------------------------------------------------------------------------------
+BubbleWindow::~BubbleWindow()
+{
+}
+
+//------------------------------------------------------------------------------
+void BubbleWindow::Resize()
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ FloatingWindow::Resize();
+
+ Size aSize = GetSizePixel();
+
+ if ( ( aSize.Height() < 20 ) || ( aSize.Width() < 60 ) )
+ return;
+
+ Rectangle aRect( 0, TIP_HEIGHT, aSize.Width(), aSize.Height() - TIP_HEIGHT );
+ maRectPoly = Polygon( aRect, 6, 6 );
+ Region aRegion( maRectPoly );
+ long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
+
+ Point aPointArr[4];
+ aPointArr[0] = Point( nTipOffset, TIP_HEIGHT );
+ aPointArr[1] = Point( nTipOffset, 0 );
+ aPointArr[2] = Point( nTipOffset + TIP_WIDTH , TIP_HEIGHT );
+ aPointArr[3] = Point( nTipOffset, TIP_HEIGHT );
+ maTriPoly = Polygon( 4, aPointArr );
+ Region aTriRegion( maTriPoly );
+
+ aRegion.Union( aTriRegion);
+ maBounds = aRegion;
+
+ SetWindowRegionPixel( maBounds );
+}
+
+//------------------------------------------------------------------------------
+void BubbleWindow::SetTitleAndText( const XubString& rTitle,
+ const XubString& rText,
+ const Image& rImage )
+{
+ maBubbleTitle = rTitle;
+ maBubbleText = rText;
+ maBubbleImage = rImage;
+
+ Resize();
+}
+
+//------------------------------------------------------------------------------
+void BubbleWindow::Paint( const Rectangle& )
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ LineInfo aThickLine( LINE_SOLID, 2 );
+
+ DrawPolyLine( maRectPoly, aThickLine );
+ DrawPolyLine( maTriPoly );
+
+ Color aOldLine = GetLineColor();
+ Size aSize = GetSizePixel();
+ long nTipOffset = aSize.Width() - TIP_RIGHT_OFFSET + mnTipOffset;
+
+ SetLineColor( GetSettings().GetStyleSettings().GetHelpColor() );
+ DrawLine( Point( nTipOffset+2, TIP_HEIGHT ),
+ Point( nTipOffset + TIP_WIDTH -1 , TIP_HEIGHT ),
+ aThickLine );
+ SetLineColor( aOldLine );
+
+ //Image aImage = InfoBox::GetStandardImage();
+ Size aImgSize = maBubbleImage.GetSizePixel();
+
+ DrawImage( Point( BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT ), maBubbleImage );
+
+ Font aOldFont = GetFont();
+ Font aBoldFont = aOldFont;
+ aBoldFont.SetWeight( WEIGHT_BOLD );
+
+ SetFont( aBoldFont );
+ Rectangle aTitleRect = maTitleRect;
+ aTitleRect.Move( aImgSize.Width(), 0 );
+ DrawText( aTitleRect, maBubbleTitle, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
+
+ SetFont( aOldFont );
+ Rectangle aTextRect = maTextRect;
+ aTextRect.Move( aImgSize.Width(), 0 );
+ DrawText( aTextRect, maBubbleText, TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
+}
+
+//------------------------------------------------------------------------------
+void BubbleWindow::MouseButtonDown( const MouseEvent& )
+{
+ Show( FALSE );
+}
+
+//------------------------------------------------------------------------------
+void BubbleWindow::Show( BOOL bVisible, USHORT nFlags )
+{
+ vos::OGuard aGuard( Application::GetSolarMutex() );
+
+ if ( !bVisible )
+ {
+ FloatingWindow::Show( bVisible );
+ return;
+ }
+
+ // don't show bubbles without a text
+ if ( ( maBubbleTitle.Len() == 0 ) && ( maBubbleText.Len() == 0 ) )
+ return;
+
+ Size aWindowSize = GetSizePixel();
+
+ // Image aImage = InfoBox::GetStandardImage();
+ Size aImgSize = maBubbleImage.GetSizePixel();
+
+ RecalcTextRects();
+
+ aWindowSize.setHeight( maTitleRect.GetHeight() * 7 / 4+ maTextRect.GetHeight() +
+ 3 * BUBBLE_BORDER + TIP_HEIGHT );
+
+ if ( maTitleRect.GetWidth() > maTextRect.GetWidth() )
+ aWindowSize.setWidth( maTitleRect.GetWidth() );
+ else
+ aWindowSize.setWidth( maTextRect.GetWidth() );
+
+ aWindowSize.setWidth( aWindowSize.Width() + 3 * BUBBLE_BORDER + aImgSize.Width() );
+
+ if ( aWindowSize.Height() < aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER )
+ aWindowSize.setHeight( aImgSize.Height() + TIP_HEIGHT + 2 * BUBBLE_BORDER );
+
+ Point aPos;
+ aPos.X() = maTipPos.X() - aWindowSize.Width() + TIP_RIGHT_OFFSET;
+ aPos.Y() = maTipPos.Y();
+ Point aScreenPos = GetParent()->OutputToAbsoluteScreenPixel( aPos );
+ if ( aScreenPos.X() < 0 )
+ {
+ mnTipOffset = aScreenPos.X();
+ aPos.X() -= mnTipOffset;
+ }
+ SetPosSizePixel( aPos, aWindowSize );
+
+ FloatingWindow::Show( bVisible, nFlags );
+}
+
+//------------------------------------------------------------------------------
+void BubbleWindow::RecalcTextRects()
+{
+ Size aTotalSize;
+ BOOL bFinished = FALSE;
+ Font aOldFont = GetFont();
+ Font aBoldFont = aOldFont;
+
+ aBoldFont.SetWeight( WEIGHT_BOLD );
+
+ while ( !bFinished )
+ {
+ SetFont( aBoldFont );
+
+ maTitleRect = GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize ),
+ maBubbleTitle,
+ TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
+
+ SetFont( aOldFont );
+ maTextRect = GetTextRect( Rectangle( Point( 0, 0 ), maMaxTextSize ),
+ maBubbleText,
+ TEXT_DRAW_MULTILINE | TEXT_DRAW_WORDBREAK );
+
+ if ( maTextRect.GetHeight() < 10 )
+ maTextRect.setHeight( 10 );
+
+ aTotalSize.setHeight( maTitleRect.GetHeight() +
+ aBoldFont.GetHeight() * 3 / 4 +
+ maTextRect.GetHeight() +
+ 3 * BUBBLE_BORDER + TIP_HEIGHT );
+ if ( aTotalSize.Height() > maMaxTextSize.Height() )
+ {
+ maMaxTextSize.Width() = maMaxTextSize.Width() * 3 / 2;
+ maMaxTextSize.Height() = maMaxTextSize.Height() * 3 / 2;
+ }
+ else
+ bFinished = TRUE;
+ }
+ maTitleRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT );
+ maTextRect.Move( 2*BUBBLE_BORDER, BUBBLE_BORDER + TIP_HEIGHT + maTitleRect.GetHeight() + aBoldFont.GetHeight() * 3 / 4 );
+}
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
+
+} // anonymous namespace
+
+//------------------------------------------------------------------------------
+
+static uno::Reference<uno::XInterface> SAL_CALL
+createInstance(const uno::Reference<uno::XComponentContext>& xContext)
+{
+ return *new UpdateCheckUI(xContext);
+}
+
+//------------------------------------------------------------------------------
+
+static const cppu::ImplementationEntry kImplementations_entries[] =
+{
+ {
+ createInstance,
+ getImplementationName,
+ getServiceNames,
+ cppu::createSingleComponentFactory,
+ NULL,
+ 0
+ },
+ { NULL, NULL, NULL, NULL, NULL, 0 }
+} ;
+
+//------------------------------------------------------------------------------
+
+extern "C" void SAL_CALL
+component_getImplementationEnvironment( const sal_Char **aEnvTypeName, uno_Environment **)
+{
+ *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" sal_Bool SAL_CALL
+component_writeInfo(void *pServiceManager, void *pRegistryKey)
+{
+ return cppu::component_writeInfoHelper(
+ pServiceManager,
+ pRegistryKey,
+ kImplementations_entries
+ );
+}
+
+//------------------------------------------------------------------------------
+
+extern "C" void *
+component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
+{
+ return cppu::component_getFactoryHelper(
+ pszImplementationName,
+ pServiceManager,
+ pRegistryKey,
+ kImplementations_entries) ;
+}
+
diff --git a/extensions/source/update/ui/updatecheckui.hrc b/extensions/source/update/ui/updatecheckui.hrc
new file mode 100644
index 000000000000..c1d27546f28f
--- /dev/null
+++ b/extensions/source/update/ui/updatecheckui.hrc
@@ -0,0 +1,39 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatecheckui.hrc,v $
+ * $Revision: 1.5 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+ #define RID_UPDATECHECKUI_START 1100
+
+ #define RID_UPDATE_AVAIL_IMAGES RID_UPDATECHECKUI_START + 1
+
+ #define RID_UPDATE_AVAILABLE_16 RID_UPDATECHECKUI_START + 1
+ #define RID_UPDATE_AVAILABLE_26 RID_UPDATECHECKUI_START + 2
+ #define RID_UPDATE_AVAILABLE_16_HC RID_UPDATECHECKUI_START + 3
+ #define RID_UPDATE_AVAILABLE_26_HC RID_UPDATECHECKUI_START + 4
+
diff --git a/extensions/source/update/ui/updatecheckui.src b/extensions/source/update/ui/updatecheckui.src
new file mode 100644
index 000000000000..8c7b70ab07be
--- /dev/null
+++ b/extensions/source/update/ui/updatecheckui.src
@@ -0,0 +1,54 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: updatecheckui.src,v $
+ * $Revision: 1.6 $
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "updatecheckui.hrc"
+
+#define STD_MASK_COLOR MaskColor = Color { Red = 0xFFFF; Green = 0x0000; Blue = 0xFFFF; };
+
+ Image RID_UPDATE_AVAILABLE_16
+ {
+ ImageBitmap = Bitmap{ file = "onlineupdate_16.png"; };
+ STD_MASK_COLOR
+ };
+ Image RID_UPDATE_AVAILABLE_26
+ {
+ ImageBitmap = Bitmap{ file = "onlineupdate_26.png"; };
+ STD_MASK_COLOR
+ };
+ Image RID_UPDATE_AVAILABLE_16_HC
+ {
+ ImageBitmap = Bitmap{ file = "onlineupdate_16_h.png"; };
+ STD_MASK_COLOR
+ };
+ Image RID_UPDATE_AVAILABLE_26_HC
+ {
+ ImageBitmap = Bitmap{ file = "onlineupdate_26_h.png"; };
+ STD_MASK_COLOR
+ };
diff --git a/extensions/source/update/ui/updchkui.xml b/extensions/source/update/ui/updchkui.xml
new file mode 100644
index 000000000000..a9005d8b255f
--- /dev/null
+++ b/extensions/source/update/ui/updchkui.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module-description PUBLIC "-//StarOffice//DTD ComponentDescription 1.0//EN" "module-description.dtd">
+<module-description xmlns:xlink="http://www.w3.org/1999/xlink">
+ <module-name>updchkui</module-name>
+ <component-description>
+ <author> Oliver Braun </author>
+ <name>vnd.sun.UpdateCheck</name>
+ <description> The </description>
+ <loader-name>com.sun.star.loader.SharedLibrary</loader-name>
+ <language>c++</language>
+ <status value="beta"/>
+ <supported-service>com.sun.star.setup.UpdateCheckUI</supported-service>
+ <service-dependency>...</service-dependency>
+ <type>com.sun.star.document.XEventBroadcaster</type>
+ <type>com.sun.star.document.XEventListener</type>
+ <type>com.sun.star.lang.XEventListener</type>
+ <type>com.sun.star.lang.XMultiComponentFactory</type>
+ <type>com.sun.star.lang.XServiceInfo</type>
+ <type>com.sun.star.lang.XSingleComponentFactory</type>
+ <type>com.sun.star.lang.XTypeProvider</type>
+ <type>com.sun.star.uno.TypeClass</type>
+ <type>com.sun.star.uno.XAggregation</type>
+ <type>com.sun.star.uno.XComponentContext</type>
+ <type>com.sun.star.uno.XCurrentContext</type>
+ <type>com.sun.star.uno.XWeak</type>
+ <type>com.sun.star.registry.XRegistryKey</type>
+ </component-description>
+ <project-build-dependency>cppuhelper</project-build-dependency>
+ <project-build-dependency>cppu</project-build-dependency>
+ <project-build-dependency>sal</project-build-dependency>
+ <runtime-module-dependency>cppuhelper3$(COM)</runtime-module-dependency>
+ <runtime-module-dependency>cppu3</runtime-module-dependency>
+ <runtime-module-dependency>sal3</runtime-module-dependency>
+</module-description>