[prev in list] [next in list] [prev in thread] [next in thread] 

List:       helix-client-cvs
Subject:    [Client-cvs] autoupgdmgr chxauinstaller.cpp, NONE,
From:       qluo () helixcommunity ! org
Date:       2008-04-29 23:56:06
Message-ID: 200804292357.m3TNv4CI029882 () mailer ! progressive-comp ! com
[Download RAW message or body]

Update of /cvsroot/client/autoupgdmgr
In directory cvs01.internal.helixcommunity.org:/tmp/cvs-serv444

Modified Files:
	autoupgdlib chxaunegotiator.cpp chxaunegotiator.h 
	chxautoupgrade.cpp 
Added Files:
	chxauinstaller.cpp chxcompcoll.cpp 
Log Message:
Auto update implementation.  CR: ping@real.com


Index: chxaunegotiator.h
===================================================================
RCS file: /cvsroot/client/autoupgdmgr/chxaunegotiator.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- chxaunegotiator.h	17 Jul 2007 23:30:04 -0000	1.1
+++ chxaunegotiator.h	29 Apr 2008 23:56:03 -0000	1.2
@@ -56,6 +56,29 @@
 #include "hxstring.h"
 #include "hxhttp.h"
 #include "hxinfcod.h"
+#include "ihxautoupgrademgr.h"
+#include "ihxausinks.h"
+
+#define REQ_UPGRADE_SERVER		"UpgradeServer"
+#define REQ_PRODUCT_NAME		"ProductName"
+#define REQ_PRODUCT_VERSION		"ProductVersion"
+#define REQ_REUQEST_TYPE		"RequestType"
+#define REQ_TYPE_AUTOMATIC		"RequestTypeAutomatic"
+#define REQ_LAST_UPGRADE_CHECK		"LastAutoUpgradeCheck"
+#define REQ_BANDWIDTH			"Bandwidth"
+
+#define	UPGRD_CMP_NAME			"CMP_Name"
+#define	UPGRD_CMP_VERSION		"CMP_Version"
+#define	UPGRD_CMP_DISPNAME		"CMP_DisplayName"
+#define	UPGRD_CMP_UPGRDURL		"CMP_UpgradeURL"
+#define	UPGRD_CMP_BACKUPURL		"CMP_BackupURL"
+#define	UPGRD_CMP_HELPURL		"CMP_HelpURL"
+#define	UPGRD_CMP_DESCRIPTION		"CMP_Description"
+#define	UPGRD_CMP_SPACE			"CMP_Space"
+#define	UPGRD_CMP_DOWNLOADSIZE		"CMP_DownloadSize"
+#define	UPGRD_CMP_SHOWFLAG		"CMP_ShowFlag"
+#define	UPGRD_CMP_STATE			"CMP_State"
+
 
 class CHXAUNegotiator    :   public IHXHttpResponse2
 {
@@ -69,37 +92,61 @@
     STDMETHOD_(ULONG32,Release)     (THIS);
 
     //  IHXHttpResponse methods
-    STDMETHOD(OnHeaders)        (THIS_ IHXValues* pHeaders);
-    STDMETHOD(OnDataReceived)   (THIS_ IHXBuffer* pBuffer);
-    STDMETHOD(OnGetDone)        (THIS_ HXBOOL bSuccess);
+    STDMETHOD(OnHeaders)	    (THIS_ IHXValues* pHeaders);
+    STDMETHOD(OnDataReceived)	    (THIS_ IHXBuffer* pBuffer);
+    STDMETHOD(OnGetDone)	    (THIS_ HXBOOL bSuccess);
         
     //  IHXHttpResponse2 methods
-    STDMETHOD(GetPostData)      (THIS_ REF(IHXBuffer*) pBuffer);
-    STDMETHOD(InitPost)         (THIS);
-    STDMETHOD(SetDataType)      (THIS_ UINT16 nDataType);
-    STDMETHOD(SetHeaders)       (THIS_ IHXValues* pHeaders);
+    STDMETHOD(GetPostData)	    (THIS_ REF(IHXBuffer*) pBuffer);
+    STDMETHOD(InitPost)		    (THIS);
+    STDMETHOD(SetDataType)	    (THIS_ UINT16 nDataType);
+    STDMETHOD(SetHeaders)	    (THIS_ IHXValues* pHeaders);
 
-    // 
-    HX_RESULT   Init            (IUnknown* pContext);
-    HX_RESULT   Negotiate       (void);
-    void        Close           (void);
+    HX_RESULT   Init		    (IUnknown* pContext);
+    HX_RESULT	AddAdviseSink	    (IHXUpgradeNegotiatorAdviseSink* pSink);
+    HX_RESULT	RemoveAdviseSink    (IHXUpgradeNegotiatorAdviseSink* pSink);
+    HX_RESULT   Negotiate	    (IHXValues* pRequest,  IHXUpgradeCollection* \
pUpgradeCollection); +    void        Close		    (void);
 
 private:
     INT32                           m_lRefCount;
-    CHXString                       m_szURL;
-    CHXString                       m_szDestination;
-    HXBOOL                          m_bInitialized;
-    HX_RESULT                       m_lastError;
     IUnknown*                       m_pContext;
     SPIHXCommonClassFactory         m_spCCF;
     SPIHXHttp                       m_spHTTP;
     SPIHXHttp2                      m_spHTTP2;
+    HXBOOL                          m_bInitialized;
+    CHXString                       m_strServerURL;
     SPIHXBuffer                     m_spAURequest;
+    SPIHXBuffer			    m_spResponseBuffer;
+    UINT32			    m_nCurrentBufferPosition;
 
-    CHXSimpleList*                  m_pSinkList;
+    IHXUpgradeNegotiatorAdviseSink*	    m_pSink;
+    IHXComponentDescriptorsCollection*	    m_pComponentsCollection;
+    // response header
+    UINT16			    m_nDaysBeforeNextCheck;
+    UINT32			    m_nHeaderStatus;
+
+    // available component 
+    HXBOOL			    m_hasComponent;
+    CHXString			    m_szCmpName;
+    CHXString			    m_szCmpVersion;
+    CHXString			    m_szCmpDisplayName;
+    CHXString			    m_szCmpUpgradeURL;
+    CHXString			    m_szCmpBackupURL;
+    CHXString			    m_szCmpHelpURL;
+    CHXString			    m_szCmpDescription;
+    UINT32			    m_ulCmpDiskSize;
+    UINT32			    m_ulCmpDownloadSize;
+    UINT16			    m_ulCmpShowFlag;
+    UINT16			    m_ulCmpState;
 
+    HX_RESULT			    AddAvailableComponentsToCollection(void);
+    HX_RESULT			    ValidateUpgradeResponse(void);
+    HX_RESULT			    ParseAUResponse(void);
+    HX_RESULT			    PrepareAURequest(IHXValues* pRequest, IHXUpgradeCollection* \
pUpgradeCollection); +    HX_RESULT			    SetServerURL(IHXValues* pRequest);
 
-    HX_RESULT   PrepareAURequest(void);
+    HX_RESULT			    HandleServerResponse(HXBOOL bSuccess);
 };
 
 #endif /* _CHXAUNEGOTIATOR_H_ */

--- NEW FILE: chxcompcoll.cpp ---
/* ***** BEGIN LICENSE BLOCK *****
 *
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 * 
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 * 
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 * 
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 * 
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 * 
 * Contributor(s):
 * 
 * ***** END LICENSE BLOCK ***** */

#include "hxcom.h"
#include "hxtypes.h"
#include "ihxpckts.h"
#include "pckunpck.h"
#include "chxcompcoll.h"

CHXComponentDescriptorsCollection::CHXComponentDescriptorsCollection(IUnknown* \
pContext):	  m_lRefCount(0),	
    m_pComponentsArray(NULL),
    m_pContext(pContext)
{
    HX_ADDREF(m_pContext);
}

CHXComponentDescriptorsCollection::~CHXComponentDescriptorsCollection(void)
{
    RemoveAll();
    HX_RELEASE(m_pContext);
}

/*
 * IUnknown methods
 */
STDMETHODIMP CHXComponentDescriptorsCollection::QueryInterface(REFIID riid, void** \
ppvObj) {
    QInterfaceList qiList[] =
        {
            { GET_IIDHANDLE(IID_IHXComponentDescriptorsCollection), \
                (IHXComponentDescriptorsCollection*)this },
            { GET_IIDHANDLE(IID_IUnknown), \
(IUnknown*)(IHXComponentDescriptorsCollection*)this },  };
    
    return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}

STDMETHODIMP_(ULONG32) CHXComponentDescriptorsCollection::AddRef(void)
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(ULONG32) CHXComponentDescriptorsCollection::Release(void)
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
        return m_lRefCount;
    }

    delete this;
    return 0;
}

/*
 * IHXComponentDescriptorsCollection methods
 */
STDMETHODIMP CHXComponentDescriptorsCollection::Create(REF(IHXComponentDescriptor*) \
pComponent) {
    HX_RESULT res = HXR_OK;

    IHXComponentDescriptor* pIDescriptor = NULL;
    CHXComponentDescriptor* pCDescriptor = new CHXComponentDescriptor(m_pContext);

    res = pCDescriptor->QueryInterface(IID_IHXComponentDescriptor, (void \
**)&pIDescriptor);  pComponent = SUCCEEDED(res) ? pIDescriptor : NULL;

    return res;
}

STDMETHODIMP CHXComponentDescriptorsCollection::Add(IHXComponentDescriptor* \
pComponent) {
    if (!m_pComponentsArray)
    {
	m_pComponentsArray = new CHXPtrArray;
	if (!m_pComponentsArray)
	{
	    return HXR_FAIL;
	}
    }

    return(m_pComponentsArray->Add(pComponent));
}

STDMETHODIMP CHXComponentDescriptorsCollection::RemoveAt(UINT32 index)
{
    if (m_pComponentsArray)
    {
	if ((UINT32)m_pComponentsArray->GetSize() > index)
	{
	    IHXComponentDescriptor* pComponent = \
(IHXComponentDescriptor*)(*m_pComponentsArray)[(int)index];  \
m_pComponentsArray->RemoveAt((int)index);  HX_RELEASE(pComponent);

	    return HXR_OK;
	}
    }

    return HXR_FAIL;
}

STDMETHODIMP CHXComponentDescriptorsCollection::Remove(IHXComponentDescriptor* \
pComponent) {
    if (m_pComponentsArray)
    {
	UINT32 size = m_pComponentsArray->GetSize();

	for(UINT32 index = 0;index < size;index++)
	{
	    IHXComponentDescriptor* pTmp = \
(IHXComponentDescriptor*)(*m_pComponentsArray)[(int)index];  if (pTmp == pComponent)
	    {
		m_pComponentsArray->RemoveAt((int)index);
		HX_RELEASE(pTmp);
		break;
	    }
	}
    }

    return HXR_OK;
}

STDMETHODIMP CHXComponentDescriptorsCollection::RemoveAll(void)
{
    if (m_pComponentsArray)
    {
	UINT32 size = m_pComponentsArray->GetSize();

	for(UINT32 index = 0;index < size;index++)
	{
	    IHXComponentDescriptor* pComponent = \
(IHXComponentDescriptor*)(*m_pComponentsArray)[(int)index];  HX_RELEASE(pComponent);
	}

	m_pComponentsArray->RemoveAll();
	HX_DELETE(m_pComponentsArray);
    }

    return HXR_OK;
}

STDMETHODIMP_(UINT32) CHXComponentDescriptorsCollection::GetCount(void)
{
    return m_pComponentsArray ? (m_pComponentsArray->GetSize()) : 0;
}

STDMETHODIMP CHXComponentDescriptorsCollection::GetAt(UINT32 index, \
REF(IHXComponentDescriptor*) pComponentOut) {
    if (m_pComponentsArray)
    {
	if ((UINT32)m_pComponentsArray->GetSize() > index)
	{
	    IHXComponentDescriptor* pComponent = \
(IHXComponentDescriptor*)(*m_pComponentsArray)[(int)index];  pComponent->AddRef();
	    pComponentOut = pComponent;
	    return HXR_OK;
	}
    }

    return HXR_FAIL;
}

/*
 *  CHXComponentDescriptor implementation
 */
CHXComponentDescriptor::CHXComponentDescriptor(IUnknown* pContext):	
    m_lRefCount(0),	
    m_pContext(pContext)
{
    HX_ADDREF(m_pContext);
    m_spCCF = m_pContext;
}

CHXComponentDescriptor::~CHXComponentDescriptor(void)
{
    HX_RELEASE(m_pContext);
}

/*
 * IUnknown methods
 */
STDMETHODIMP CHXComponentDescriptor::QueryInterface(REFIID riid, void** ppvObj)
{
    QInterfaceList qiList[] =
        {
            { GET_IIDHANDLE(IID_IHXComponentDescriptor), \
                (IHXComponentDescriptor*)this },
            { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXComponentDescriptor*)this \
},  };
    
    return ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);
}

STDMETHODIMP_(ULONG32) CHXComponentDescriptor::AddRef(void)
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(ULONG32) CHXComponentDescriptor::Release(void)
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
        return m_lRefCount;
    }

    delete this;
    return 0;
}

/*
 * IHXComponentDescriptor methods
 */
STDMETHODIMP CHXComponentDescriptor::SetProperty(const char* pName, IHXBuffer* \
pValue) {
    HX_RESULT res = HXR_OK;

    if (!m_spComponentPropertyValues)
    {
	m_spComponentPropertyValues = SPIHXValues(m_spCCF.Ptr(), CLSID_IHXValues, &res);
    }

    if (SUCCEEDED(res))
    {
	res = m_spComponentPropertyValues->SetPropertyBuffer(pName, pValue);
    }

    return res;
}

STDMETHODIMP CHXComponentDescriptor::GetProperty(const char* pName, REF(IHXBuffer*) \
pValue) {
    if (m_spComponentPropertyValues)
    {
	return (m_spComponentPropertyValues->GetPropertyBuffer(pName, pValue));
    }
    return HXR_FAIL;
}

STDMETHODIMP CHXComponentDescriptor::RemoveProperty(const char* pName)
{
    return HXR_NOTIMPL;
}

STDMETHODIMP_(UINT32) CHXComponentDescriptor::GetPropertyCount(void)
{
    return HXR_NOTIMPL;
}

STDMETHODIMP CHXComponentDescriptor::GetPropertyAt(UINT32 ulIndex, REF(const char*) \
pName, REF(IHXBuffer*) pValue) {
    return HXR_NOTIMPL;
}

STDMETHODIMP CHXComponentDescriptor::RemovePropertyAt(UINT32 ulIndex)
{
    return HXR_NOTIMPL;
}

STDMETHODIMP CHXComponentDescriptor::RemoveAll(void)
{
    return HXR_NOTIMPL;
}


Index: chxaunegotiator.cpp
===================================================================
RCS file: /cvsroot/client/autoupgdmgr/chxaunegotiator.cpp,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- chxaunegotiator.cpp	17 Jul 2007 23:30:04 -0000	1.1
+++ chxaunegotiator.cpp	29 Apr 2008 23:56:03 -0000	1.2
@@ -48,37 +48,41 @@
 
 #include "hxcom.h"
 
-#include <stdlib.h>
 #include "hxtypes.h"
-#include "timeval.h"
-#include "hxstring.h"
-#include "hxslist.h"
 #include "hxcomm.h"
 #include "chxaunegotiator.h"
 #include "upgpids.h"
+#include "hxupgrd.h"
 #include "hxwinver.h"
 #include "pckunpck.h"
 #include "md5.h"
+#include "chxcompcoll.h"
+#include "hxprefutil.h"
+
+#define RN_AUSERV_PASSWD		"guadalajara90048"
+#define RN_AUSERV_URL			"http://update.real.com/"
+#define MD5_DIGEST_SIZE			16
+#define TEXT_CHECKSUM_SIZE		32
+#define _MAX_INTERVAL			30
 
 #ifdef _DEBUG
 #undef HX_THIS_FILE
 static const char HX_THIS_FILE[] = __FILE__;
 #endif
 
-#define AUSERV_PASSWD   "guadalajara90048"
-#define AUSERV_URL      \
                "http://ipm-test02.prognet.com:9003/RealPlayer/6.0.14.520/win32/"
-
 CHXAUNegotiator::CHXAUNegotiator()
                 : m_lRefCount(0)
                 , m_pContext(NULL)
-                , m_pSinkList(NULL)
                 , m_bInitialized(FALSE)
-                , m_lastError(HXR_OK)
+                , m_pSink(NULL)
+                , m_nCurrentBufferPosition(0)
+                , m_pComponentsCollection(NULL)
 {
 }
 
 CHXAUNegotiator::~CHXAUNegotiator()
 {
+    Close();
 }
 
 STDMETHODIMP_(ULONG32) 
@@ -166,7 +170,11 @@
         goto exit;
     }
 
-    res = HXR_OK;
+    CHXComponentDescriptorsCollection* pCollection = new \
CHXComponentDescriptorsCollection(m_pContext); +    if (pCollection)
+    {
+	res = pCollection->QueryInterface(IID_IHXComponentDescriptorsCollection, (void \
**)&m_pComponentsCollection); +    }
 
 exit:
 
@@ -178,24 +186,81 @@
     return res;
 }
 
+HX_RESULT
+CHXAUNegotiator::AddAdviseSink(IHXUpgradeNegotiatorAdviseSink* pSink)
+{
+    HX_RELEASE(m_pSink);
+    if (pSink)
+    {
+	pSink->AddRef();
+	m_pSink = pSink;
+    }
+
+    return HXR_OK;
+}
+
+HX_RESULT
+CHXAUNegotiator::RemoveAdviseSink(IHXUpgradeNegotiatorAdviseSink* pSink)
+{
+    HX_RELEASE(m_pSink);
+    return HXR_OK;
+}
+
 //  IHXHttpResponse methods
 STDMETHODIMP
 CHXAUNegotiator::OnHeaders(IHXValues* pHeaders)
 {
+    const char* pName = NULL;
+    IHXBuffer* pValue = NULL;
+    CHXString strContentLength = "Content-Length";
+
+    // figure out AU response size from header and setup response buffer
+    HX_RESULT retVal = pHeaders->GetFirstPropertyCString(pName, pValue);
+    while (retVal == HXR_OK)
+    {
+        if (strContentLength.CompareNoCase(pName) == 0)
+        {
+            int nResponseLength = atoi((const char*)pValue->GetBuffer());
+	    CreateBufferCCF(*m_spResponseBuffer.AsInOutParam(), m_spCCF.Ptr());
+	    m_spResponseBuffer->SetSize(nResponseLength);
+	    break;
+        }
+        HX_RELEASE(pValue);
+        retVal = pHeaders->GetNextPropertyCString(pName, pValue);
+    }
+    HX_RELEASE(pValue);
+
     return HXR_OK;
 }
 
 STDMETHODIMP
 CHXAUNegotiator::OnDataReceived(IHXBuffer* pBuffer)
 {
-    HX_RESULT   res = HXR_OK;
- 
-    return res;
+    // seve AU response data
+    UINT32      ulSize = 0;
+    UCHAR*	pData = NULL;
+
+    if (pBuffer)
+    {
+        ulSize = pBuffer->GetSize();
+        pData = pBuffer->GetBuffer();
+    }
+
+    if (ulSize && pData)
+    {
+	memcpy(m_spResponseBuffer->GetBuffer() + m_nCurrentBufferPosition, pData, ulSize);
+	m_nCurrentBufferPosition += ulSize;
+    }
+
+    return HXR_OK;
 }
 
 STDMETHODIMP
 CHXAUNegotiator::OnGetDone(HXBOOL bSuccess)
 {
+    // process response
+    HandleServerResponse(bSuccess);
+
     return HXR_OK;
 }
     
@@ -228,25 +293,29 @@
 }
 
 HX_RESULT 
-CHXAUNegotiator::Negotiate(void)
+CHXAUNegotiator::Negotiate(IHXValues* pRequestOptions, IHXUpgradeCollection* \
pUpgradeCollection)  {
     HX_RESULT   res = HXR_FAIL;
 
-    res = PrepareAURequest();
-    if (FAILED(res))
+    if (m_bInitialized && pRequestOptions)
     {
-        return res;
+	res = PrepareAURequest(pRequestOptions, pUpgradeCollection);
+    }
+
+    if (SUCCEEDED(res))
+    {
+	SetServerURL(pRequestOptions);
     }
 
     m_spHTTP->SetBufferSize(4096);
 
-    res = m_spHTTP2->Post(AUSERV_URL, m_spAURequest->GetSize());
+    res = m_spHTTP2->Post((const char*)m_strServerURL, m_spAURequest->GetSize());
 
     return res;
 }
 
 HX_RESULT
-CHXAUNegotiator::PrepareAURequest(void)
+CHXAUNegotiator::PrepareAURequest(IHXValues* pRequestOptions, IHXUpgradeCollection* \
pUpgradeCollection)  {
     HX_RESULT   res = HXR_OK;
     UINT32      nSizePos = 0;
@@ -257,17 +326,19 @@
         return res;
     }
 
-    // write UPGP header
+    UINT32 ulUpgradeType;
+    pRequestOptions->GetPropertyULONG32(REQ_REUQEST_TYPE, ulUpgradeType);
+    UINT16 u16UpgradeType = (ulUpgradeType == eUT_Required) ? \
UPGP_REQ_MISSING_PLUGIN : UPGP_REQ_AUTOMATIC; +
+    /***** write UPGP header *****/
     spOutStream->WriteString(UPGP_PROTOCOL_NAME);
     spOutStream->WriteString(UPGP_PROTOCOL_VERSION);
-    spOutStream->WriteUINT16(UPGP_REQ_AUTOMATIC);
+    spOutStream->WriteUINT16(u16UpgradeType);
 
-    // write the system description bloc.
+    /***** write the system description bloc *****/
     spOutStream->WriteUINT16(UPGP_DATA_REQ_SYSTEM_DESC);
-    
-    nSizePos = spOutStream->GetOffset();  // save current position
-    spOutStream->WriteUINT16(0);          // reserve spot for block size
-
+    nSizePos = spOutStream->GetOffset();
+    spOutStream->WriteUINT16(0);
 #if defined(_WIN32)
     spOutStream->WriteString("Win32");
 #elif defined(_MACINTOSH)
@@ -281,7 +352,6 @@
 #else
     spOutStream->WriteString("Unk");
 #endif
-
     // OS name/ver
     HXVERSIONINFO VersionInfo;
     HXGetWinVer( &VersionInfo );
@@ -300,53 +370,49 @@
     {
 	spOutStream->WriteString("Unk");
     }
-
     // System Language ID
     spOutStream->WriteUINT32(0);
-
     // Bandwidth
-    spOutStream->WriteUINT32(0);
-
+    UINT32 nBandwidth = 0;
+    pRequestOptions->GetPropertyULONG32(REQ_BANDWIDTH, nBandwidth);
+    spOutStream->WriteUINT32(nBandwidth);
     // UID
     spOutStream->WriteString("");
-
     // Last AU check
-    spOutStream->WriteUINT32(0);
-
-    // Write block size
+    UINT32 nLastAUCheckInHours = 0;
+    pRequestOptions->GetPropertyULONG32(REQ_LAST_UPGRADE_CHECK, \
nLastAUCheckInHours); +    spOutStream->WriteUINT32(nLastAUCheckInHours);
     spOutStream->WriteUINT16At(nSizePos, \
(UINT16)(spOutStream->GetOffset()-nSizePos-sizeof(UINT16)));  
-    // AU Contacting Configuration Block
+    /***** write AU Contacting Configuration Block *****/
     spOutStream->WriteUINT16(UPGP_DATA_AU_CONFIGURATION);
-    nSizePos = spOutStream->GetOffset();   // save current position
-    spOutStream->WriteUINT16(0);  // reserve spot for block size
-
+    nSizePos = spOutStream->GetOffset();
+    spOutStream->WriteUINT16(0);
     spOutStream->WriteUINT16(1);
     spOutStream->WriteUINT16(0);
-
-    // now we can write block size
     spOutStream->WriteUINT16At(nSizePos, (UINT16)(spOutStream->GetOffset() - \
nSizePos - sizeof(UINT16)));  
-    // Product location block
+    /***** write Product location block *****/
     spOutStream->WriteUINT16(UPGP_DATA_LOCATION3);
-    nSizePos = spOutStream->GetOffset();   // save current position
-    spOutStream->WriteUINT16(0);  // reserve spot for block size
-
+    nSizePos = spOutStream->GetOffset();
+    spOutStream->WriteUINT16(0);
     // CountryID
     spOutStream->WriteString("");
     // RegionData
     spOutStream->WriteString("");
-
-    // now we can write block size
     spOutStream->WriteUINT16At(nSizePos, \
(UINT16)(spOutStream->GetOffset()-nSizePos-sizeof(UINT16)));  
-    // Product Info
+    /***** write Product Info block *****/
     spOutStream->WriteUINT16(UPGP_DATA_INST_PRODUCT_EX2); 
-    nSizePos = spOutStream->GetOffset();   // save current position
-    spOutStream->WriteUINT16(0);  // reserve spot for block size
-
-    spOutStream->WriteString("RealPlayer"); 
-    spOutStream->WriteString("6.0.0.0");
+    nSizePos = spOutStream->GetOffset();
+    spOutStream->WriteUINT16(0);
+    SPIHXBuffer spBuffer;
+    // product name
+    pRequestOptions->GetPropertyCString(REQ_PRODUCT_NAME, \
*(spBuffer.AsInOutParam())); +    spOutStream->WriteString((const \
char*)spBuffer->GetBuffer()); +    // product version
+    pRequestOptions->GetPropertyCString(REQ_PRODUCT_VERSION, \
*(spBuffer.AsInOutParam())); +    spOutStream->WriteString((const \
char*)spBuffer->GetBuffer());  spOutStream->WriteString("FREE");
     // Language
     spOutStream->WriteString("");
@@ -357,43 +423,505 @@
     // Origination Code
     spOutStream->WriteString("");
     spOutStream->WriteUCHAR(1);
-    
     spOutStream->WriteUINT16At(nSizePos, (UINT16)(spOutStream->GetOffset() - \
nSizePos - sizeof(UINT16)));  
-    // End Block
+    /***** write requested plugins block *****/
+    UINT32 nCount = 0;
+    nCount = pUpgradeCollection->GetCount();
+    if (nCount > 0)
+    {
+	UINT16 n16Count = (UINT16)nCount;
+	spOutStream->WriteUINT16(UPGP_DATA_REQ_PLUGINS);
+	nSizePos = spOutStream->GetOffset();
+	spOutStream->WriteUINT16(0);
+	// plugin count
+	spOutStream->WriteUINT16(n16Count);
+	// plugin names
+	HXUpgradeType eType;
+	SPIHXBuffer spNameBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	UINT32 majorVersion = 0;
+	UINT32 minorVersion = 0;
+	for(UINT16 nIndex = 0; nIndex < n16Count; nIndex++)
+	{
+	    pUpgradeCollection->GetAt(nIndex, eType, spNameBuffer.Ptr(), majorVersion, \
minorVersion); +	    spOutStream->WriteString((const \
char*)spNameBuffer->GetBuffer()); +	}
+	spOutStream->WriteUINT16At(nSizePos, (UINT16)(spOutStream->GetOffset() - nSizePos - \
sizeof(UINT16))); +    }
+
+    /***** write End Block *****/
     spOutStream->WriteUINT16(UPGP_DATA_END);
     spOutStream->WriteUINT16(0);
 
-    // MD5
-    SPIHXBuffer spEncryption;
-    CreateBufferCCF(*spEncryption.AsInOutParam(), m_spCCF.Ptr());
-    spEncryption->Set((UCHAR*)AUSERV_PASSWD, strlen(AUSERV_PASSWD));
-
-    SPIHXBuffer spAURequest;
+    /***** message signature *****/
     CreateBufferCCF(*m_spAURequest.AsInOutParam(), m_spCCF.Ptr());
     m_spAURequest->SetSize(spOutStream->GetLength() + 32);
     memcpy(m_spAURequest->GetBuffer(), spOutStream->GetBuffer(), \
                spOutStream->GetLength());
-
-    UCHAR binaryChecksum[16];
+    // key
+    SPIHXBuffer spEncryption;
+    CreateBufferCCF(*spEncryption.AsInOutParam(), m_spCCF.Ptr());
+    spEncryption->Set((UCHAR*)RN_AUSERV_PASSWD, strlen(RN_AUSERV_PASSWD));
+    // MD5 digest
+    UCHAR binaryChecksum[MD5_DIGEST_SIZE];
     md5_state_t md5Context;
     md5_init(&md5Context);
+    // request message
     md5_append(&md5Context, (const UCHAR*)spOutStream->GetBuffer(), \
spOutStream->GetLength()); +    // AU protocol key
     md5_append(&md5Context, (const UCHAR*)spEncryption->GetBuffer(), \
spEncryption->GetSize());  md5_finish(binaryChecksum, &md5Context);
-
+    // append encoded signature to request
     UCHAR* pText = m_spAURequest->GetBuffer() + spOutStream->GetLength();
     static const char hex[]="0123456789abcdef";
-    for(int i = 0; i < 16; i++)
+    for(int i = 0; i < MD5_DIGEST_SIZE; i++)
+    {
+	pText[i+i] = hex[binaryChecksum[i] >> 4];
+	pText[i+i+1] = hex[binaryChecksum[i] & 0x0f];
+    }
+
+    return res;
+}
+
+HX_RESULT
+CHXAUNegotiator::SetServerURL(IHXValues* pRequest)
+{
+    HX_RESULT res = HXR_OK;
+
+    m_strServerURL = RN_AUSERV_URL;
+
+    // alternative AU server
+    SPIHXBuffer spBuffer;
+    res = pRequest->GetPropertyCString(REQ_UPGRADE_SERVER, \
*(spBuffer.AsInOutParam())); +    if (SUCCEEDED(res))
+    {
+	m_strServerURL = (const char*)spBuffer->GetBuffer();
+    }
+
+    // product name version
+    res = pRequest->GetPropertyCString(REQ_PRODUCT_NAME, \
*(spBuffer.AsInOutParam())); +    if (SUCCEEDED(res))
+    {
+	m_strServerURL = m_strServerURL + (const char*)spBuffer->GetBuffer() + '/';
+	res = pRequest->GetPropertyCString(REQ_PRODUCT_VERSION, \
*(spBuffer.AsInOutParam())); +    }
+
+    // product version
+    if (SUCCEEDED(res))
+    {
+	m_strServerURL = m_strServerURL + (const char*)spBuffer->GetBuffer() + '/';
+    }
+
+    // platform
+    if (SUCCEEDED(res))
+    {
+#if defined(_WIN32)
+	m_strServerURL += "win32/";
+#elif defined(_MAC_UNIX)
+	m_strServerURL += "MacOSX/";
+	// todo: other platforms
+#endif
+    }
+
+    return res;
+}
+
+HX_RESULT
+CHXAUNegotiator::HandleServerResponse(HXBOOL bSuccess)
+{
+    HX_RESULT res = HXR_OK;
+
+    if (!bSuccess)
+    {
+	// HttpPost failed, blame the net
+	res = HXR_NET_CONNECT;
+    }
+
+    // check signature
+    if (SUCCEEDED(res))
+    {
+	res = ValidateUpgradeResponse();
+    }
+
+    // parse response data
+    if (SUCCEEDED(res))
+    {
+	res = ParseAUResponse();
+    }
+
+    if (m_nHeaderStatus == UPGP_STAT_OK)
+    {
+	// write LastAUCheck to pref
+	time_t tNow;
+	time(&tNow);
+	CHXString LastAUCheckStr;
+
+	LastAUCheckStr.Format("%d", tNow);
+	if (!LastAUCheckStr.IsEmpty())
+	{
+	    WritePrefCSTRING(m_pContext, "LastAUCheck", LastAUCheckStr);
+	}
+    }
+    
+    if (m_nHeaderStatus != UPGP_STAT_OK)
+    {
+	// convert error code
+	switch (m_nHeaderStatus)
+	{
+	case UPGP_SERVER_ERROR:
+	case UPGP_SERVER_UNAVAILABLE:
+	case UPGP_CLIENT_UNSUPPORTED:
+	case UPGP_CLIENT_UNKNOWN:
+	    res = HXR_BAD_SERVER;
+	    break;
+	case UPGP_REQ_ERROR:
+	case UPGP_INVALID_SERIAL:
+	case UPGP_BLACKLISTED:
+	    res = HXR_FAIL;
+	    break;
+	}
+    }
+
+    // callbacks via sink
+    if (m_pSink)
+    {
+	// first send components descriptors
+	if (SUCCEEDED(res) && m_pComponentsCollection->GetCount() > 0)
+	{
+	    m_pSink->OnAvailableComponents(m_pComponentsCollection);
+	}
+
+	// then signal AU negotiation done
+	if (SUCCEEDED(res))
+	{
+	    m_pSink->OnNegotiatorStatus(NEGOTIATOR_DONE);
+	}
+
+	// report error
+	if (res != HXR_OK)
+	{
+	    m_pSink->OnNegotiatorError(res);
+	}
+    }
+
+    return res;
+}
+
+HX_RESULT
+CHXAUNegotiator::ValidateUpgradeResponse(void)
+{
+    HX_RESULT res = HXR_OK;
+
+    UINT32 ulSize = m_spResponseBuffer->GetSize();
+    UCHAR* pData = m_spResponseBuffer->GetBuffer();
+    UINT32 nSizeOfActualData = ulSize - TEXT_CHECKSUM_SIZE;
+
+    SPIHXBuffer spEncryption;
+    CreateBufferCCF(*spEncryption.AsInOutParam(), m_spCCF.Ptr());
+    spEncryption->Set((UCHAR*)RN_AUSERV_PASSWD, strlen(RN_AUSERV_PASSWD));
+
+    // MD5
+    UCHAR binaryChecksum[MD5_DIGEST_SIZE];
+    md5_state_t md5Context;
+    md5_init(&md5Context);
+    md5_append(&md5Context, (const UCHAR*)pData, nSizeOfActualData);
+    md5_append(&md5Context, (const UCHAR*)spEncryption->GetBuffer(), \
spEncryption->GetSize()); +    md5_finish(binaryChecksum, &md5Context);
+
+    UCHAR pText[TEXT_CHECKSUM_SIZE];
+    static const char hex[]="0123456789abcdef";
+    for(int i = 0; i < MD5_DIGEST_SIZE; i++)
     {
 	pText[i+i] = hex[binaryChecksum[i] >> 4];
 	pText[i+i+1] = hex[binaryChecksum[i] & 0x0f];
     }
 
+    // validate
+    if (strncmp((const char*)(pData + nSizeOfActualData),
+	(const char*)pText, TEXT_CHECKSUM_SIZE) != 0)
+    {
+	res =  HXR_UNEXPECTED_MSG;
+    }
+
+    return res;
+}
+
+HX_RESULT
+CHXAUNegotiator::ParseAUResponse(void)
+{
+    HX_RESULT res = HXR_OK;
+
+    m_hasComponent = FALSE;
+    UINT32 ulSize = m_spResponseBuffer->GetSize();
+    UCHAR* pData = m_spResponseBuffer->GetBuffer();
+    UINT32 nSizeOfActualData = ulSize - TEXT_CHECKSUM_SIZE;
+
+    SPIHXObjInStream spInStream = SPIHXObjInStream(m_spCCF.Ptr(), \
CLSID_IHXObjInStream, &res); +
+    // setup reader
+    if (SUCCEEDED(res))
+    {
+	spInStream->Initialize(pData, nSizeOfActualData);
+    }
+
+    UINT16 nBlockSize=0;
+    UINT16 nType = 0;
+    CHXString tmpStr;
+    UINT16 uTmp16;
+    HXBOOL bDone = FALSE;
+
+    // check header
+    if (SUCCEEDED(res))
+    {
+	CHXString strProtocolName, strProtocolVersion;
+	res = HXR_INVALID_PROTOCOL;
+	
+	if (spInStream->ReadString(strProtocolName)&&
+	    spInStream->ReadString(strProtocolVersion) &&
+	    spInStream->ReadUINT16(nType) &&
+	    strProtocolName == UPGP_PROTOCOL_NAME &&
+	    nType == UPGP_RESP_UPGRADE &&
+	    // first block type
+	    spInStream->ReadUINT16(nType))
+
+	{
+	    res = HXR_OK;
+	}
+    }
+
+    // go over all message blocks
+    while (SUCCEEDED(res) && nType != UPGP_DATA_END && !spInStream->IsEndOfData() && \
!bDone) +    {
+	// block size
+	if(!spInStream->ReadUINT16( nBlockSize ))
+	{
+	    res = HXR_INVALID_PROTOCOL;
+	    break;
+	}
+
+	UINT32 nOldPosition = spInStream->GetOffset();
+
+	switch(nType)
+	{
+	case UPGP_DATA_RESP_HEADER:
+	    // response header block
+	    if(!spInStream->ReadUINT16(m_nDaysBeforeNextCheck) ||
+		!spInStream->ReadString(tmpStr) ||
+		!spInStream->ReadString(tmpStr) ||
+		!spInStream->ReadUINT16(uTmp16) ||
+		!spInStream->ReadUINT32(m_nHeaderStatus))
+	    {
+		res = HXR_INVALID_PROTOCOL;
+	    }
+	    if(m_nDaysBeforeNextCheck > _MAX_INTERVAL)
+	    {
+		res = HXR_INVALID_PROTOCOL;
+	    }
+	    break;
+	case UPGP_DATA_AVAIL_COMPONENT:
+	    // available component block
+    	    if (!spInStream->ReadString(m_szCmpName) ||
+		!spInStream->ReadString(m_szCmpVersion) ||
+		!spInStream->ReadString(m_szCmpDisplayName) ||
+		!spInStream->ReadString(m_szCmpUpgradeURL) ||
+		!spInStream->ReadString(m_szCmpBackupURL) ||
+		!spInStream->ReadString(m_szCmpHelpURL) ||
+		!spInStream->ReadString(m_szCmpDescription) ||
+		!spInStream->ReadUINT32(m_ulCmpDiskSize) ||
+		!spInStream->ReadUINT32(m_ulCmpDownloadSize) ||
+		!spInStream->ReadUINT16(m_ulCmpShowFlag) ||
+		!spInStream->ReadUINT16(m_ulCmpState))
+	    {
+		res = HXR_INVALID_PROTOCOL;
+	    }
+	    else
+	    {
+		AddAvailableComponentsToCollection();
+	    }
+	    break;
+	case UPGP_DATA_UPSELL_COMPONENT: // fall through, don't care in this version
+	case UPGP_DATA_MESSAGE_RESP:
+	case UPGP_DATA_RESP_PRODUCT:
+	case UPGP_DATA_RESP_CLASS:
+	case UPGP_DATA_HTML_UI:
+	    break;
+	}
+
+	// advance to the next block
+	if (spInStream->Seek(nOldPosition + nBlockSize) != HXR_OK ||
+	    !spInStream->ReadUINT16(nType))
+	{
+	    res = HXR_INVALID_PROTOCOL;
+	}
+    }
+
+    return res;
+}
+
+HX_RESULT
+CHXAUNegotiator::AddAvailableComponentsToCollection(void)
+{
+    HX_RESULT res = HXR_OK;
+
+    IHXComponentDescriptor* pComponent = NULL;
+    res = m_pComponentsCollection->Create(pComponent);
+
+    if (SUCCEEDED(res) && !m_szCmpName.IsEmpty())
+    {
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)m_szCmpName), \
m_szCmpName.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_NAME, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res) && !m_szCmpName.IsEmpty())
+    {
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)m_szCmpName), \
m_szCmpName.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_NAME, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res) && !m_szCmpVersion.IsEmpty())
+    {
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)m_szCmpVersion), \
m_szCmpVersion.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_VERSION, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res) && !m_szCmpDisplayName.IsEmpty())
+    {
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)m_szCmpDisplayName), \
m_szCmpDisplayName.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_DISPNAME, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res) && !m_szCmpUpgradeURL.IsEmpty())
+    {
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)m_szCmpUpgradeURL), \
m_szCmpUpgradeURL.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_UPGRDURL, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res) && !m_szCmpBackupURL.IsEmpty())
+    {
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)m_szCmpBackupURL), \
m_szCmpBackupURL.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_BACKUPURL, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res) && !m_szCmpHelpURL.IsEmpty())
+    {
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)m_szCmpHelpURL), \
m_szCmpHelpURL.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_HELPURL, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res) && !m_szCmpDescription.IsEmpty())
+    {
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)m_szCmpDescription), \
m_szCmpDescription.GetLength()+1); +	    \
pComponent->SetProperty(UPGRD_CMP_DESCRIPTION, spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res))
+    {
+	CHXString strVal;
+	strVal.Format("%d", m_ulCmpDiskSize);
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)strVal), \
strVal.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_SPACE, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res))
+    {
+	CHXString strVal;
+	strVal.Format("%d", m_ulCmpDiskSize);
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)strVal), \
strVal.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_SPACE, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res))
+    {
+	CHXString strVal;
+	strVal.Format("%d", m_ulCmpDownloadSize);
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)strVal), \
strVal.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_DOWNLOADSIZE, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res))
+    {
+	CHXString strVal = m_ulCmpShowFlag ? "true" : "false";
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)strVal), \
strVal.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_SHOWFLAG, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res))
+    {
+	CHXString strVal;
+	strVal.Format("%d", m_ulCmpState);
+	SPIHXBuffer spBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+	if (spBuffer.IsValid())
+	{
+	    spBuffer->Set((const UCHAR*)const_cast<char*>((const char*)strVal), \
strVal.GetLength()+1); +	    pComponent->SetProperty(UPGRD_CMP_STATE, \
spBuffer.Ptr()); +	}
+    }
+
+    if (SUCCEEDED(res))
+    {
+	res = m_pComponentsCollection->Add(pComponent);
+    }
+
     return res;
 }
 
 void
 CHXAUNegotiator::Close(void)
 {
-    return;
+    HX_RELEASE(m_pComponentsCollection);
+    HX_RELEASE(m_pSink);
+
+    if (m_spHTTP)
+    {
+	m_spHTTP->Terminate();
+    }
+
+    HX_RELEASE(m_pContext);
 }

--- NEW FILE: chxauinstaller.cpp ---
/* ***** BEGIN LICENSE BLOCK *****
 *
 * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
 *
 * The contents of this file, and the files included with this file,
 * are subject to the current version of the RealNetworks Public
 * Source License (the "RPSL") available at
 * http://www.helixcommunity.org/content/rpsl unless you have licensed
 * the file under the current version of the RealNetworks Community
 * Source License (the "RCSL") available at
 * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
 * will apply. You may also obtain the license terms directly from
 * RealNetworks.  You may not use this file except in compliance with
 * the RPSL or, if you have a valid RCSL with RealNetworks applicable
 * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
 * the rights, obligations and limitations governing use of the
 * contents of the file.
 *
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL") in which case the provisions of the GPL are applicable
 * instead of those above. If you wish to allow use of your version of
 * this file only under the terms of the GPL, and not to allow others
 * to use your version of this file under the terms of either the RPSL
 * or RCSL, indicate your decision by deleting the provisions above
 * and replace them with the notice and other provisions required by
 * the GPL. If you do not delete the provisions above, a recipient may
 * use your version of this file under the terms of any one of the
 * RPSL, the RCSL or the GPL.
 *
 * This file is part of the Helix DNA Technology. RealNetworks is the
 * developer of the Original Code and owns the copyrights in the
 * portions it created.
 *
 * This file, and the files included with this file, is distributed
 * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
 * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
 * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
 * ENJOYMENT OR NON-INFRINGEMENT.
 *
 * Technology Compatibility Kit Test Suite(s) Location:
 *    http://www.helixcommunity.org/content/tck
 *
 * Contributor(s):
 *
 * ***** END LICENSE BLOCK ***** */

#include "hxcom.h"


#include "hxtypes.h"
#include "hxstring.h"
#include "hxcomm.h"
#include "chxauinstaller.h"

CHXAUInstaller::CHXAUInstaller()
                : m_lRefCount(0)
                , m_pContext(NULL)
                , m_pSink(NULL)
{
}

CHXAUInstaller::~CHXAUInstaller()
{
    Close();
}


STDMETHODIMP_(ULONG32) 
CHXAUInstaller::AddRef()
{
    return InterlockedIncrement(&m_lRefCount);
}

STDMETHODIMP_(ULONG32) 
CHXAUInstaller::Release()
{
    if (InterlockedDecrement(&m_lRefCount) > 0)
    {
        return m_lRefCount;
    }

    delete this;
    return 0;
}

STDMETHODIMP 
CHXAUInstaller::QueryInterface(REFIID riid, void** ppvObj)
{
    QInterfaceList qiList[] =
        {
            { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)this },
        };

    HX_RESULT res = ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);    

    return res;
}

void
CHXAUInstaller::Close(void)
{
    HX_RELEASE(m_pSink);
    HX_RELEASE(m_pContext);
}

HX_RESULT
CHXAUInstaller::Init(IUnknown* pContext)
{
    if (!pContext)
    {
	return HXR_FAIL;
    }

    HX_RESULT   res = HXR_OK;

    pContext->AddRef();
    m_pContext = pContext;

    m_spCCF = m_pContext;
    m_spScheduler = m_pContext;

    return HXR_OK;
}

HX_RESULT
CHXAUInstaller::AddAdviseSink(IHXUpgradeSetupAdviseSink* pSink)
{
    HX_RELEASE(m_pSink);
    if (pSink)
    {
	pSink->AddRef();
	m_pSink = pSink;
    }

    return HXR_OK;
}

HX_RESULT
CHXAUInstaller::RemoveAdviseSink(IHXUpgradeSetupAdviseSink* pSink)
{
    HX_RELEASE(m_pSink);
    return HXR_OK;
}

HX_RESULT 
CHXAUInstaller::StartInstallPackage(const char* pPackagePath)
{
    HX_RESULT res = HXR_OK;

    m_strPackagePath = pPackagePath;

    // check type
    m_ePackageType = GetPackageType(m_strPackagePath);

    if (m_ePackageType != AUPKG_UNK)
    {
	m_status = SETUP_INSTALLING;
	m_nPercentDone = 0;
	if (m_pSink)
	{
	    m_pSink->OnInstallStatus(m_status, m_nPercentDone);
	}
    }

    // handle install
    switch (m_ePackageType)
    {
    case AUPKG_EXE:
	res = RunExeInstaller(m_strPackagePath);

	break;
    case AUPKG_XPI:
	res = InstallXPI(m_strPackagePath);

	break;
    case AUPKG_RUP:
	res = InstallXPI(m_strPackagePath);

	break;
    default:
	res = HXR_FAIL;
    }

    // call sink
    if (SUCCEEDED(res))
    {
	m_status = SETUP_INSTALLING;
	m_nPercentDone = 100;
	if (m_pSink)
	{
	    m_pSink->OnInstallStatus(m_status, m_nPercentDone);
	}
    }
    else if (m_pSink)
    {
	m_pSink->OnInstallError(res);
    }

    return res;
}

AUPKG_TYPE
CHXAUInstaller::GetPackageType(const char* pPackagePath)
{
    CHXString strPackagePath = pPackagePath;
    INT32 lLastDot = strPackagePath.ReverseFind('.');
    CHXString pkgExtension = strPackagePath.Right(strPackagePath.GetLength() - \
lLastDot - 1);  pkgExtension.MakeLower();

    if (strncmp(EXT_EXE, (const char*)pkgExtension, 3) == 0)
    {
	return AUPKG_EXE;
    }
    else if (strncmp(EXT_XPI, (const char*)pkgExtension, 3) == 0)
    {
	return AUPKG_XPI;
    }
    else if (strncmp(EXT_RUP, (const char*)pkgExtension, 3) == 0)
    {
	return AUPKG_RUP;
    }

    return AUPKG_UNK;
}

HX_RESULT
CHXAUInstaller::RunExeInstaller(const char* pPackagePath)
{
#if defined(_WIN32)
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );

    CHXString CommandOptionsStr = "";//" /S";
    CHXString pCommandStr = pPackagePath;

    pCommandStr += CommandOptionsStr;
    LPSTR pCommand = (LPSTR)(LPCTSTR)pCommandStr;

    // Start the child process. 
    if( !CreateProcess( NULL,   // No module name (use command line)
	pCommand,	// Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi )           // Pointer to PROCESS_INFORMATION structure
    ) 
    {
        return HXR_FAIL;
    }

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
#endif

    return HXR_OK;
}

HX_RESULT
CHXAUInstaller::UnpackRupPackage(const char* pPackagePath)
{
    // todo: merge unpack code here.
    return HXR_OK;
}

HX_RESULT
CHXAUInstaller::InstallXPI(const char* pPackagePath)
{
    // todo: implement xpi installer
    return HXR_OK;
}

Index: chxautoupgrade.cpp
===================================================================
RCS file: /cvsroot/client/autoupgdmgr/chxautoupgrade.cpp,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- chxautoupgrade.cpp	5 Oct 2007 00:35:47 -0000	1.3
+++ chxautoupgrade.cpp	29 Apr 2008 23:56:03 -0000	1.4
@@ -47,15 +47,16 @@
  * ***** END LICENSE BLOCK ***** */
 
 #include "hxcom.h"
-
-#include <stdlib.h>
 #include "hxtypes.h"
-#include "timeval.h"
 #include "hxstring.h"
 #include "hxslist.h"
 #include "hxcomm.h"
 #include "chxautoupgrade.h"
 #include "filespecutils.h"
+#include "hxcbobj.h"
+#include "hxprefutil.h"
+#include "hxupgrd.h"
+#include "ihxcomponentdescriptor.h"
 
 #ifdef _DEBUG
 #undef HX_THIS_FILE
@@ -65,13 +66,15 @@
 CHXAutoUpgrade::CHXAutoUpgrade()
             : m_lRefCount(0)
             , m_status(AU_UNKNOWN)
+            , m_nPercentDone(0)
             , m_pContext(NULL)
             , m_pAUNegotiator(NULL)
+            , m_pAUInstaller(NULL)
             , m_pSinkList(NULL)
-            , m_ulServerPort(80)
-            , m_pRequest(NULL)
-	    , m_bUseFixedInstaller(FALSE)
-	    , m_szCommandOptions("")
+	    , m_pTerminateNegotiatorCallback(NULL)
+	    , m_pTerminateDownloadCallback(NULL)
+	    , m_pInstallCallback(NULL)
+	    , m_pUpgradeCollection(NULL)
 {
 }
 
@@ -98,9 +101,44 @@
     return 0;
 }
 
+STDMETHODIMP 
+CHXAutoUpgrade::QueryInterface(REFIID riid, void** ppvObj)
+{
+    QInterfaceList qiList[] =
+        {
+            { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXAutoUpgrade*)this },
+            { GET_IIDHANDLE(IID_IHXAutoUpgrade), (IHXAutoUpgrade*)this },
+            { GET_IIDHANDLE(IID_IHXDownloadAdviseSink), (IHXDownloadAdviseSink*)this \
}, +            { GET_IIDHANDLE(IID_IHXUpgradeNegotiatorAdviseSink), \
(IHXUpgradeNegotiatorAdviseSink*)this }, +	    { \
GET_IIDHANDLE(IID_IHXUpgradeSetupAdviseSink), (IHXUpgradeSetupAdviseSink*)this }, +   \
}; +
+    HX_RESULT res = ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);    
+
+    return res;
+}
+
 STDMETHODIMP
 CHXAutoUpgrade::Close()
 {
+    if (m_pTerminateNegotiatorCallback)
+    {
+	if (m_pTerminateNegotiatorCallback->IsCallbackPending())
+	{
+	    m_pTerminateNegotiatorCallback->Cancel(m_spScheduler.Ptr());
+	}
+	HX_RELEASE(m_pTerminateNegotiatorCallback);
+    }
+
+    if (m_pTerminateDownloadCallback)
+    {
+	if (m_pTerminateDownloadCallback->IsCallbackPending())
+	{
+	    m_pTerminateDownloadCallback->Cancel(m_spScheduler.Ptr());
+	}
+	HX_RELEASE(m_pTerminateDownloadCallback);
+    }
+
     if (m_pSinkList)
     {
 	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
@@ -114,9 +152,9 @@
         HX_DELETE(m_pSinkList);
     }
 
-    if (m_pRequest)
+    if (m_spDownloadMgr)
     {
-	HX_RELEASE(m_pRequest);
+	m_spDownloadMgr->Close();
     }
 
     if (m_pAUNegotiator)
@@ -125,46 +163,95 @@
 	HX_RELEASE(m_pAUNegotiator);
     }
 
+    if (m_pAUInstaller)
+    {
+	m_pAUInstaller->Close();
+	HX_RELEASE(m_pAUInstaller);
+    }
+    
+    HX_RELEASE(m_pUpgradeCollection);
     HX_RELEASE(m_pContext);
+
     return HXR_OK;
 }
 
-STDMETHODIMP 
-CHXAutoUpgrade::QueryInterface(REFIID riid, void** ppvObj)
+STDMETHODIMP
+CHXAutoUpgrade::Prepare(HXUpgradeRequestInfo* pClientRequestInfo)
 {
-    QInterfaceList qiList[] =
-        {
-            { GET_IIDHANDLE(IID_IUnknown), (IUnknown*)(IHXAutoUpgrade*)this },
-            { GET_IIDHANDLE(IID_IHXAutoUpgrade), (IHXAutoUpgrade*)this },
-            { GET_IIDHANDLE(IID_IHXDownloadAdviseSink), (IHXDownloadAdviseSink*)this \
                },
-        };
+    if (!pClientRequestInfo || !(pClientRequestInfo->m_pUpgradeCollection))
+    {
+	return HXR_FAIL;
+    }
 
-    HX_RESULT res = ::QIFind(qiList, QILISTSIZE(qiList), riid, ppvObj);    
+    HX_RESULT res = HXR_OK;
 
-    return res;
-}
+    m_pUpgradeCollection = pClientRequestInfo->m_pUpgradeCollection;
+    m_pUpgradeCollection->AddRef();
 
-STDMETHODIMP
-CHXAutoUpgrade::Prepare(const char* pszServer,
-                        UINT32 ulPort,
-                        IHXValues* pRequest)
-{
-    // AU server
-    if (pszServer)
+    m_spRequestValues = SPIHXValues(m_spCCF.Ptr(), CLSID_IHXValues, &res);
+
+    // product name
+    SPIHXBuffer spProductNameBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+    if (SUCCEEDED(res) && spProductNameBuffer.IsValid() && \
pClientRequestInfo->m_pProductName)  {
-	m_szAUServer = pszServer;
+	UCHAR* pszProductName = (pClientRequestInfo->m_pProductName)->GetBuffer();
+	spProductNameBuffer->Set(pszProductName, strlen((const char*)pszProductName)+1);
+	m_spRequestValues->SetPropertyCString(REQ_PRODUCT_NAME, spProductNameBuffer.Ptr());
     }
 
-    m_ulServerPort = ulPort;
+    // product version
+    SPIHXBuffer spProductVersionBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+    if (SUCCEEDED(res) && spProductVersionBuffer.IsValid() && \
pClientRequestInfo->m_pProductVersion) +    {
+	UCHAR* pszProductVersion = (pClientRequestInfo->m_pProductVersion)->GetBuffer();
+	spProductVersionBuffer->Set(pszProductVersion, strlen((const \
char*)pszProductVersion)+1); \
+	m_spRequestValues->SetPropertyCString(REQ_PRODUCT_VERSION, \
spProductVersionBuffer.Ptr()); +    }
 
-    // AU request/options
-    if (pRequest)
+    // AU request type
+    if (SUCCEEDED(res))
     {
-	pRequest->AddRef();
-	m_pRequest = pRequest;
+	m_spRequestValues->SetPropertyULONG32(REQ_REUQEST_TYPE, \
(ULONG32)(pClientRequestInfo->m_ulUpgradeType)); +    }
+
+    // last AU check in hours
+    if (SUCCEEDED(res))
+    {
+	UINT32 nLastCheckInDays = GetLastAUCheckInDays();
+	m_spRequestValues->SetPropertyULONG32(REQ_LAST_UPGRADE_CHECK, \
(ULONG32)(nLastCheckInDays * 24)); +    }
+
+    // Bandwidth
+    if (SUCCEEDED(res))
+    {
+	ULONG32 nBandwidth = 0;
+	CHXString BandwidthStr;
+	res = ReadPrefCSTRING(m_pContext, REQ_BANDWIDTH, BandwidthStr);
+	if (SUCCEEDED(res))
+	{
+	    nBandwidth = atol((const char*)BandwidthStr);
+	}
+	m_spRequestValues->SetPropertyULONG32(REQ_BANDWIDTH, nBandwidth);
     }
 
+    // AU server URL
+    SPIHXBuffer spAUServerURLBuffer(m_spCCF.Ptr(), CLSID_IHXBuffer);
+    if (SUCCEEDED(res) && spAUServerURLBuffer.IsValid())
+    {
+	CHXString AUServerURLStr;
+	res = ReadPrefCSTRING(m_pContext, REQ_UPGRADE_SERVER, AUServerURLStr);
+	if (SUCCEEDED(res) && AUServerURLStr.GetLength() > 0)
+	{
+	    spAUServerURLBuffer->Set((const unsigned char*)const_cast<char*>((const \
char*)AUServerURLStr), AUServerURLStr.GetLength()+1); +	    \
m_spRequestValues->SetPropertyCString(REQ_UPGRADE_SERVER, spAUServerURLBuffer.Ptr()); \
+	} +
+	// server URL is optional
+	res = HXR_OK;
+    }
+    
     m_status = AU_PENDING;
+
     return HXR_OK;
 }
 
@@ -205,64 +292,105 @@
 CHXAutoUpgrade::Resume()
 {
     HX_RESULT   res = HXR_OK;
+    SPIHXBuffer spBuffer;
+    HXBOOL bCallOnComponent = FALSE;
 
-    if (AU_PENDING != m_status && AU_PAUSED != m_status)
+    switch (m_status)
     {
-        res = HXR_FAIL;
-    }
+    case AU_PENDING:
+	m_status = AU_REQUESTING;
+	m_nPercentDone = 0;
 
-    // get pkg URL from AU options
-    if (SUCCEEDED(res) && m_pRequest)
-    {
-	SPIHXBuffer spBuffer;
-	if (SUCCEEDED( m_pRequest->GetPropertyCString("InstallerURL", \
*(spBuffer.AsInOutParam())) )) +	m_pAUNegotiator = new CHXAUNegotiator();
+	if (m_pAUNegotiator)
 	{
-	    m_szDownloadURL = (const char*)spBuffer->GetBuffer();
-	    m_bUseFixedInstaller = TRUE;
+	    m_pAUNegotiator->AddRef();
+	    m_pAUNegotiator->Init(m_pContext);
+	    m_pAUNegotiator->AddAdviseSink((IHXUpgradeNegotiatorAdviseSink*)this);
+	    res = m_pAUNegotiator->Negotiate(m_spRequestValues.Ptr(), \
m_pUpgradeCollection); +	    m_pUpgradeCollection->RemoveAll();
 	}
-	if (SUCCEEDED( m_pRequest->GetPropertyCString("CommandOptions", \
*(spBuffer.AsInOutParam())) )) +	else
 	{
-	    m_szCommandOptions = (const char*)spBuffer->GetBuffer();
+	    res = HXR_FAIL;
 	}
-    }
 
-    // todo: get pkg URL from AU server
-    if (SUCCEEDED(res) && m_bUseFixedInstaller == FALSE)
-    {
-	HX_ASSERT(!m_pAUNegotiator);
+	break;
+    case AU_REQUESTING:
+	if (m_nPercentDone == 100)
+	{
+	    m_status = AU_DOWNLOADING;
+	    m_nPercentDone = 0;
 
-	m_pAUNegotiator = new CHXAUNegotiator();
-	m_pAUNegotiator->Init(m_pContext);
+	    if (!m_spDownloadMgr || m_szDownloadURL.IsEmpty())
+	    {
+		res = HXR_FAIL;
+	    }
 
-	res = m_pAUNegotiator->Negotiate();
-    }
+	    // local path
+	    if (SUCCEEDED(res))
+	    {
+		INT32 lLastSlash = m_szDownloadURL.ReverseFind('/');
+		CHXString pkgName = m_szDownloadURL.Right(m_szDownloadURL.GetLength() - lLastSlash \
- 1); +		CHXDirSpecifier dirSpec = CHXFileSpecUtils::GetSystemTempDirectory();
+		if (dirSpec.IsSet())
+		{
+		    m_szLocalPKGPath = dirSpec.GetPathName() + pkgName;
+		}
+	    }
 
-    // Local package path
-    if (SUCCEEDED(res))
-    {
-	INT32 lLastSlash = m_szDownloadURL.ReverseFind('/');
-	CHXString pkgName = m_szDownloadURL.Right(m_szDownloadURL.GetLength() - lLastSlash \
                - 1);
-	CHXDirSpecifier dirSpec = CHXFileSpecUtils::GetSystemTempDirectory();
-	if (dirSpec.IsSet())
+	    // kickoff downloading
+	    if (SUCCEEDED(res))
+	    {
+		res = HXR_FAIL;
+		SPIHXDownload spDownload;
+		m_spDownloadMgr->CreateDownload(*spDownload.AsInOutParam());
+		if (spDownload)
+		{
+		    spDownload->AddAdviseSink((IHXDownloadAdviseSink*)this);
+		    spDownload->DownloadToFile((const char*)m_szDownloadURL, (const \
char*)m_szLocalPKGPath); +		    m_spDownloadMgr->AddDownload(spDownload.Ptr());
+		    res = HXR_OK;
+		}
+	    }
+	}
+
+	break;
+    case AU_DOWNLOADING:
+	if (m_nPercentDone == 100)
 	{
-	    m_szLocalPKGPath = dirSpec.GetPathName() + pkgName;
+	    m_status = AU_INSTALLING;
+	    m_nPercentDone = 0;
+
+	    // installer should be on a different thread...
+	    if (!m_pInstallCallback->IsCallbackPending())
+	    {
+		m_pInstallCallback->ScheduleRelative(m_spScheduler.Ptr(), 0);
+	    }
 	}
-    }
-    
-    if (SUCCEEDED(res) && m_spDownloadMgr)
-    {
-        SPIHXDownload spDownload;
 
-        m_spDownloadMgr->CreateDownload(*spDownload.AsInOutParam());
-        if (spDownload)
-        {
-	    spDownload->AddAdviseSink((IHXDownloadAdviseSink*)this);
-            spDownload->DownloadToFile((const char*)m_szDownloadURL, (const \
                char*)m_szLocalPKGPath);
-            m_spDownloadMgr->AddDownload(spDownload.Ptr());
+	break;
+    default:
+	res = HXR_FAIL;
+	break;
+    }
 
-            m_status = AU_DOWNLOADING;
-            res = HXR_OK;
-        }
+    // inform client
+    if (m_pSinkList)
+    {
+	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
+	for (; ndx != m_pSinkList->End(); ++ndx)
+	{
+	    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
+	    if (SUCCEEDED(res))
+	    {
+		pSink->OnStatus(m_status, m_nPercentDone);
+	    }
+	    else
+	    {
+		pSink->OnError(res);
+	    }
+	}
     }
 
     return res;
@@ -293,49 +421,173 @@
     return HXR_NOTIMPL;
 }
 
+HX_RESULT 
+CHXAutoUpgrade::Init(IUnknown* pContext)
+{
+    if (!pContext)
+    {
+	return HXR_FAIL;
+    }
+
+    HX_RESULT res = HXR_OK;
+
+    m_pContext = pContext;
+    HX_ADDREF(m_pContext);
+    m_spCCF = m_pContext;
+    m_spScheduler = m_pContext;
+
+    res = m_pContext->QueryInterface(IID_IHXDownloadManager, \
(void**)m_spDownloadMgr.AsInOutParam()); +
+    if (SUCCEEDED(res) && !m_pTerminateNegotiatorCallback)
+    {        
+	m_pTerminateNegotiatorCallback = new CHXGenericCallback((void*) this, \
TerminateNegotiatorCallbackFunc); +	if (m_pTerminateNegotiatorCallback)
+	{
+	    m_pTerminateNegotiatorCallback->AddRef();
+	}
+    }
+
+    if (SUCCEEDED(res) && !m_pTerminateDownloadCallback)
+    {        
+	m_pTerminateDownloadCallback = new CHXGenericCallback((void*) this, \
TerminateDownloadCallbackFunc); +	if (m_pTerminateDownloadCallback)
+	{
+	    m_pTerminateDownloadCallback->AddRef();
+	}
+    }
+
+    if (SUCCEEDED(res) && !m_pInstallCallback)
+    {        
+	m_pInstallCallback = new CHXGenericCallback((void*) this, InstallCallbackFunc);
+	if (m_pInstallCallback)
+	{
+	    m_pInstallCallback->AddRef();
+	}
+    }
+
+    return res;
+}
+
+/*
+ *  IHXUpgradeNegotiatorAdviseSink 
+ */
 STDMETHODIMP
-CHXAutoUpgrade::OnDownloadStatus(DOWNLOAD_STATUS  status)
+CHXAutoUpgrade::OnAvailableComponents(IHXComponentDescriptorsCollection* \
pComponents)  {
     HX_RESULT res = HXR_OK;
 
-    switch(status)
+    // component download URL, assuming only one component for this version
+    SPIHXComponentDescriptor spComponentDescriptor;
+    if (pComponents && pComponents->GetCount() > 0)
     {
-    case DOWNLOAD_COMPLETED:
-	if (m_pSinkList)
+	res = pComponents->GetAt(0, *(spComponentDescriptor.AsInOutParam()));
+    }
+
+    if (SUCCEEDED(res) && spComponentDescriptor)
+    {
+	SPIHXBuffer spBuffer;
+	res = spComponentDescriptor->GetProperty(UPGRD_CMP_UPGRDURL, \
*(spBuffer.AsInOutParam())); +	if (SUCCEEDED(res))
 	{
-	    CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
-	    for (; ndx != m_pSinkList->End(); ++ndx)
-	    {
-		IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
-		// report AU_INSTALLING
-		pSink->OnStatus(AU_INSTALLING, 0);
-	    }
+	    m_szDownloadURL = (const char*)spBuffer->GetBuffer();
 	}
-	if (m_bUseFixedInstaller)
+    }
+
+    // call IHXAutoUpgradeAdviseSink
+    if (pComponents && m_pSinkList)
+    {
+	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
+	for (; ndx != m_pSinkList->End(); ++ndx)
 	{
-	    // run installer
-	    res = RunInstaller(m_szLocalPKGPath, m_szCommandOptions);
-	    if (m_pSinkList)
-	    {
-		CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
-		for (; ndx != m_pSinkList->End(); ++ndx)
-		{
-		    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
-		    // report AU_DONE
-		    pSink->OnStatus((res == HXR_OK) ? AU_DONE : AU_ERROR, 100);
-		}
-	    }
+	    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
+	    pSink->OnComponents(pComponents);
 	}
-	else
+    }
+
+    return HXR_OK;
+}
+
+STDMETHODIMP
+CHXAutoUpgrade::OnNegotiatorStatus(NEGOTIATOR_STATUS  status)
+{
+    m_status = AU_REQUESTING;
+    m_nPercentDone = (status == NEGOTIATOR_DONE) ? 100 : 0;
+
+    if (m_pSinkList)
+    {
+	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
+	for (; ndx != m_pSinkList->End(); ++ndx)
 	{
-	    // todo: implement and use CHXAUInstaller to verify and install the AU pkg
+	    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
+	    pSink->OnStatus(m_status, m_nPercentDone);
 	}
-	break;
-    default:
-	break;
     }
 
-    return res;
+    if (m_status == AU_REQUESTING && m_nPercentDone == 100)
+    {
+	if (!m_pTerminateNegotiatorCallback->IsCallbackPending())
+	{
+	    m_pTerminateNegotiatorCallback->ScheduleRelative(m_spScheduler.Ptr(), 5);
+	}
+    }
+
+    return HXR_OK;
+}
+
+
+STDMETHODIMP
+CHXAutoUpgrade::OnNegotiatorError(HX_RESULT  error)
+{
+    if (m_pSinkList)
+    {
+	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
+	for (; ndx != m_pSinkList->End(); ++ndx)
+	{
+	    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
+	    pSink->OnError(error);
+	}
+    }
+
+    if (!m_pTerminateNegotiatorCallback->IsCallbackPending())
+    {
+        m_pTerminateNegotiatorCallback->ScheduleRelative(m_spScheduler.Ptr(), 5);
+    }
+
+    return HXR_OK;
+}
+
+/*
+ *  IHXDownloadAdviseSink
+ */
+STDMETHODIMP
+CHXAutoUpgrade::OnDownloadStatus(DOWNLOAD_STATUS  status)
+{
+    if (m_pSinkList)
+    {
+	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
+	for (; ndx != m_pSinkList->End(); ++ndx)
+	{
+	    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
+	    if (status == DOWNLOAD_COMPLETED)
+	    {
+		m_status = AU_DOWNLOADING;
+		m_nPercentDone = 100;
+		pSink->OnStatus(m_status, m_nPercentDone);
+	    }
+	    else
+	    {
+		pSink->OnError(HXR_FAIL);
+	    }
+	}
+    }
+
+    // we are in the way.  schedule a callback to release download manager
+    if (!m_pTerminateDownloadCallback->IsCallbackPending())
+    {
+        m_pTerminateDownloadCallback->ScheduleRelative(m_spScheduler.Ptr(), 5);
+    }
+
+    return HXR_OK;
 }
 
 STDMETHODIMP
@@ -355,14 +607,18 @@
 	}
     }
 
+    // new PercentDone
+    m_status = AU_DOWNLOADING;
+    m_nPercentDone = ulTotalPercentDone;
+
+    // update client
     if (m_pSinkList)
     {
 	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
 	for (; ndx != m_pSinkList->End(); ++ndx)
 	{
 	    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
-	    // report AU_DOWNLOADING percentage
-	    pSink->OnStatus(AU_DOWNLOADING, ulTotalPercentDone);
+	    pSink->OnStatus(m_status, (m_nPercentDone == 100) ? 99 : m_nPercentDone);
 	}
     }
 
@@ -372,61 +628,150 @@
 STDMETHODIMP
 CHXAutoUpgrade::OnDownloadError(HX_RESULT  error)
 {
+    if (m_pSinkList)
+    {
+	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
+	for (; ndx != m_pSinkList->End(); ++ndx)
+	{
+	    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
+	    pSink->OnError(error);
+	}
+    }
+
+    if (!m_pTerminateDownloadCallback->IsCallbackPending())
+    {
+        m_pTerminateDownloadCallback->ScheduleRelative(m_spScheduler.Ptr(), 5);
+    }
+
     return HXR_OK;
 }
 
-HX_RESULT 
-CHXAutoUpgrade::Init(IUnknown* pContext)
+/*
+ *  IHXUpgradeSetupAdviseSink
+ */
+STDMETHODIMP
+CHXAutoUpgrade::OnInstallStatus(SETUP_STATUS  status, UINT32 nPercentDone)
 {
-    m_pContext = pContext;
-    HX_ADDREF(m_pContext);
+    m_status = (status == AU_UNPACKING) ? AU_UNPACKING : AU_INSTALLING;
+    m_nPercentDone = nPercentDone;
 
-    m_pContext->QueryInterface(IID_IHXDownloadManager, \
(void**)m_spDownloadMgr.AsInOutParam()); +    if (m_pSinkList)
+    {
+	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
+	for (; ndx != m_pSinkList->End(); ++ndx)
+	{
+	    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
+	    pSink->OnStatus(m_status, m_nPercentDone);
+	}
+    }
 
     return HXR_OK;
 }
 
-HX_RESULT
-CHXAutoUpgrade::RunInstaller(CHXString InstallerPath, CHXString CommandOptions)
+
+STDMETHODIMP
+CHXAutoUpgrade::OnInstallError(HX_RESULT  error)
 {
-#if defined(_WIN32)
-    STARTUPINFO si;
-    PROCESS_INFORMATION pi;
+    if (m_pSinkList)
+    {
+	CHXSimpleList::Iterator ndx = m_pSinkList->Begin();
+	for (; ndx != m_pSinkList->End(); ++ndx)
+	{
+	    IHXAutoUpgradeAdviseSink* pSink = (IHXAutoUpgradeAdviseSink*) (*ndx);
+	    pSink->OnError(error);
+	}
+    }
 
-    ZeroMemory( &si, sizeof(si) );
-    si.cb = sizeof(si);
-    ZeroMemory( &pi, sizeof(pi) );
+    return HXR_OK;
+}
 
-    CHXString pCommandStr = InstallerPath + CommandOptions;
-    LPSTR pCommand = (LPSTR)(LPCTSTR)pCommandStr;
+/*
+ *  callbacks
+ */
+void
+CHXAutoUpgrade::HandleTerminateDownload(void)
+{
+    if (m_spDownloadMgr)
+    {
+	m_spDownloadMgr->Close();
+	m_spDownloadMgr.Clear();
+    }
+}
 
-    // Start the child process. 
-    if( !CreateProcess( NULL,   // No module name (use command line)
-	pCommand,	// Command line
-        NULL,           // Process handle not inheritable
-        NULL,           // Thread handle not inheritable
-        FALSE,          // Set handle inheritance to FALSE
-        0,              // No creation flags
-        NULL,           // Use parent's environment block
-        NULL,           // Use parent's starting directory 
-        &si,            // Pointer to STARTUPINFO structure
-        &pi )           // Pointer to PROCESS_INFORMATION structure
-    ) 
+void
+CHXAutoUpgrade::TerminateDownloadCallbackFunc(void* pParam)
+{
+    if (pParam)
     {
-        return HXR_FAIL;
+        CHXAutoUpgrade* pObj = (CHXAutoUpgrade*) pParam;
+        pObj->HandleTerminateDownload();
     }
+}
 
-    // Wait until child process exits.
-    WaitForSingleObject( pi.hProcess, INFINITE );
+void
+CHXAutoUpgrade::HandleTerminateNegotiator(void)
+{
+    if (m_pAUNegotiator)
+    {
+	m_pAUNegotiator->Close();
+	HX_RELEASE(m_pAUNegotiator);
+    }
+}
 
-    // Close process and thread handles. 
-    CloseHandle( pi.hProcess );
-    CloseHandle( pi.hThread );
-#endif
+void
+CHXAutoUpgrade::TerminateNegotiatorCallbackFunc(void* pParam)
+{
+    if (pParam)
+    {
+        CHXAutoUpgrade* pObj = (CHXAutoUpgrade*) pParam;
+        pObj->HandleTerminateNegotiator();
+    }
+}
 
-    return HXR_OK;
+void
+CHXAutoUpgrade::InstallCallbackFunc(void* pParam)
+{
+    if (pParam)
+    {
+        CHXAutoUpgrade* pObj = (CHXAutoUpgrade*) pParam;
+        pObj->HandleInstallCallback();
+    }
 }
 
+void
+CHXAutoUpgrade::HandleInstallCallback(void)
+{
+    // kickoff setup
+    m_pAUInstaller = new CHXAUInstaller();
+
+    if (m_pAUInstaller)
+    {
+	m_pAUInstaller-AddRef();
+	m_pAUInstaller->Init(m_pContext);
+	m_pAUInstaller->AddAdviseSink((IHXUpgradeSetupAdviseSink*)this);
+	m_pAUInstaller->StartInstallPackage((const char*)m_szLocalPKGPath);
+    }
+}
+
+UINT32
+CHXAutoUpgrade::GetLastAUCheckInDays(void)
+{
+    HX_RESULT res = HXR_OK;
+    UINT32 nLastCheckInDays = 0xFFFFFFFF;
+    CHXString LastAUCheckStr;
+
+    res = ReadPrefCSTRING(m_pContext, "LastAUCheck", LastAUCheckStr);
+    if (SUCCEEDED(res))
+    {
+	time_t tLastCheck;
+	tLastCheck = atol((const char*)LastAUCheckStr);
+	time_t tNow;
+	time(&tNow);
+	nLastCheckInDays = (tNow - tLastCheck) / 86400;
+    }
+
+    return nLastCheckInDays;
+}
 
 IMPLEMENT_MANAGED_COMPONENT(CHXAutoUpgradeManager)
 
@@ -469,7 +814,7 @@
 	m_pAUList = new CHXSimpleList();
     }
 
-    if (pAU)
+    if (pAU && m_pAUList)
     {
 	pAU->AddRef();
 	m_pAUList->AddTail(pAU);
@@ -478,9 +823,11 @@
 	{
 	    pAU->Resume();
 	}
+
+	return HXR_OK;
     }
 
-    return HXR_OK;
+    return HXR_FAIL;
 }
 
 STDMETHODIMP

Index: autoupgdlib
===================================================================
RCS file: /cvsroot/client/autoupgdmgr/autoupgdlib,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- autoupgdlib	5 Oct 2007 00:35:47 -0000	1.3
+++ autoupgdlib	29 Apr 2008 23:56:03 -0000	1.4
@@ -67,7 +67,10 @@
 			  "protocol/http/pub")
 
 project.AddSources("chxautoupgrade.cpp",
-		   "chxaunegotiator.cpp")
+		   "chxaunegotiator.cpp",
+		   "chxcompcoll.cpp",
+		   "chxauinstaller.cpp")
+
 
 LibraryTarget("autoupgdlib")
 


_______________________________________________
Client-cvs mailing list
Client-cvs@helixcommunity.org
http://lists.helixcommunity.org/mailman/listinfo/client-cvs


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic