Logo Search packages:      
Sourcecode: valknut version File versions  Download package

dcupdatemanager.cpp

/***************************************************************************
                          dcupdatemanager.cpp  -  description
                             -------------------
    begin                : Sun May 2 2004
    copyright            : (C) 2004 by Mathias Küster
    email                : mathen@users.berlios.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#include <stdlib.h>

#include <qapplication.h>
#include <qobject.h>
#include <qfile.h>
#include <qpushbutton.h>
#include <qtextedit.h>
#include <qdatetime.h>

#include <dclib/dcos.h>
#include <dclib/chttp.h>
#include <dclib/core/ccallback.h>
#include <dclib/core/cbz.h>
#include <dclib/dcobject.h>
#include <dclib/core/cxml.h>
#include <dclib/core/cbytearray.h>

#include <dcconfig.h>
#include <dciconloader.h>

#include "dcupdatemanager.h"

#define UPDATE_URL      "http://-server-/update.xml"

DCUpdateManager * g_pUpdateManager = 0;

/** */
00045 DCUpdateManager::DCUpdateManager(QWidget* parent, const char *name, int wflags)
      : DCDialogUpdateManager(parent,name,wflags)
{
      // set default icon
      setIcon( g_pIconLoader->GetPixmap(eiINFO) );
      
      m_bRun    = FALSE;
      m_Timeout = 0;
      m_pHttp   = 0;
      m_bUpdate = FALSE;

      m_pUpdateListNew = 0;
      m_pUpdateListOld = 0;
      
      m_pMessageList = new CList<CObject>();
      
      InitDocument();
      
      g_pUpdateManager = this;
}

/** */
00067 DCUpdateManager::~DCUpdateManager()
{
      m_Timer.stop();

      g_pUpdateManager = NULL;
      
      m_UMThread.Lock();

      if ( m_pMessageList )
      {
            delete m_pMessageList;
            m_pMessageList = 0;
      }

      m_UMThread.UnLock();
}

/** */
00085 void DCUpdateManager::InitDocument()
{
      PushButton_UPDATE->setEnabled(FALSE);

      connect( PushButton_UPDATE, SIGNAL(clicked()), this, SLOT(slotUpdate()) );
      connect( PushButton_CHECKUPDATE, SIGNAL(clicked()), this, SLOT(slotCheckUpdate()) );
      
      connect( &m_Timer, SIGNAL(timeout()), this, SLOT(timerDone()) );
      m_Timer.start( 1000, TRUE );
}

/** */
00097 void DCUpdateManager::AppendLog( QString s )
{
      TextEdit_UPDATE->append( QTime::currentTime().toString("[hh:mm:ss]") + " " + s + "\n" );
}

/** callback function */
00103 int DCUpdateManager::DC_CallBack( CObject * Object )
{
      int err;

      m_UMThread.Lock();

      if ( Object != NULL )
      {
            if ( m_pMessageList != NULL )
            {
                  m_pMessageList->Add(Object);
                  err = 0;
            }
            else
            {
                  err = -1;
            }
      }
      else
      {
            err = -1;
      }

      m_UMThread.UnLock();

      return err;
}

/** */
00132 void DCUpdateManager::slotCheckUpdate()
{
      if ( (m_pUpdateListNew != 0) && (m_pUpdateListOld != 0) )
      {
            return;
      }

      PushButton_CHECKUPDATE->setEnabled(FALSE);
      m_Timeout = 0;
}

/** */
00144 void DCUpdateManager::slotUpdate()
{
      PushButton_UPDATE->setEnabled(FALSE);

      m_bUpdate = TRUE;
}

/** */
00152 void DCUpdateManager::timerDone()
{
      CByteArray in;
      CObject * Object;
      CDCMessage *DCMsg;
      int i;

      if ( m_bRun == FALSE )
      {
            if ( m_pHttp )
            {
                  if ( m_sUrl == UPDATE_URL )
                  {
                        // get content
                        if ( (m_pHttp->GetHttpError() == 200) && (m_pHttp->GetData(&in) == TRUE) )
                        {
                              CheckConfig(&in);
                              
                              if ( (m_pUpdateListNew != 0) && (m_pUpdateListOld != 0) )
                              {
                                    PushButton_UPDATE->setEnabled(TRUE);
                              }
                        }
                        
                        PushButton_CHECKUPDATE->setEnabled(TRUE);
                  }
                  else
                  {
                        DCUpdateEntry * uo=0,* un = 0;
                        
                        while((un=m_pUpdateListNew->Next(un))!=0)
                        {
                              if ( un->m_sUrl == m_sUrl )
                              {
                                    break;
                              }
                        }
                        
                        if ( un )
                        {
                              // get content
                              if ( (m_pHttp->GetHttpError() == 200) && (m_pHttp->GetData(&in) == TRUE) )
                              {
                                    // save centent
                                    if ( SaveContent( un, &in ) == TRUE )
                                    {
                                          uo = 0;
                                          while((uo=m_pUpdateListOld->Next(uo))!=0)
                                          {
                                                if ( un->m_sName == uo->m_sName )
                                                {
                                                      m_pUpdateListOld->Del(uo);
                                                      m_pUpdateListNew->Remove(un);
                                                      m_pUpdateListOld->Add(un);
                                                      break;
                                                }
                                          }
                                    
                                          if ( uo == 0 )
                                          {
                                                // new entry
                                                m_pUpdateListNew->Remove(un);
                                                m_pUpdateListOld->Add(un);
                                          }
                                          
                                          SaveConfig(m_pUpdateListOld);
                                    }

                              }
                              else
                              {
                                    // remove old entry
                                    m_pUpdateListNew->Del(un);
                                    
                                    AppendLog( tr("Download failed") );
                              }
                        }

                        // fnished
                        if ( m_pUpdateListNew->Count() == 0 )
                        {
                              delete m_pUpdateListNew;
                              m_pUpdateListNew = 0;
                              
                              // save update config
                              SaveConfig(m_pUpdateListOld);
                              
                              delete m_pUpdateListOld;
                              m_pUpdateListOld = 0;
                              
                              m_bUpdate = FALSE;
                              
                              AppendLog( tr("Update finished") );
                        }
                  }
                  
                  delete m_pHttp;
                  m_sUrl    = "";
                  m_pHttp   = 0;
                  m_Timeout = time(0);
            }
            
            if ( (m_pUpdateListNew != 0) && (m_pUpdateListOld != 0) )
            {
                  if ( m_bUpdate == TRUE )
                  {
                        if ( m_pUpdateListNew->Next(0) )
                        {
                              m_bRun = GetUrl( m_pUpdateListNew->Next(0)->m_sUrl );
                        }

                        if ( m_bRun )
                        {
                              AppendLog( tr("Download content ") + m_pUpdateListNew->Next(0)->m_sName.Data() );
                        }
                        else
                        {
                              AppendLog( tr("Download content failed") );
                        }
                  }
            }
            else if ( ((m_Timeout == 0) || ((time(0)-m_Timeout) > 60*60)) )
            {
                  m_bRun = GetUrl(UPDATE_URL);
                  
                  if ( m_bRun )
                  {
                        PushButton_CHECKUPDATE->setEnabled(FALSE);
                        AppendLog( tr("Download update.xml") );
                  }
                  else
                  {
                        PushButton_CHECKUPDATE->setEnabled(TRUE);
                        AppendLog( tr("Download update.xml failed") );
                  }
            }
      }
      
      for(i=0;i<50;i++)
      {
            if ( m_UMThread.TryLock() == FALSE )
            {
                  break;
            }

            if ( m_pMessageList != 0 )
            {
                  Object = m_pMessageList->Next(0);

                  if ( Object != 0 )
                  {
                        m_pMessageList->Remove(Object);
                  }
            }
            else
            {
                  Object = 0;
            }

            m_UMThread.UnLock();

            if ( Object == 0 )
            {
                  break;
            }

            DCMsg = (CDCMessage*) Object;

            switch ( DCMsg->m_eType )
            {
                  case DC_MESSAGE_TRANSFER:
                  {
                        // CMessageTransfer *msg = (CMessageTransfer*)Object;

                        break;
                  }

                  default:
                  {
                        break;
                  }
            }

            if ( Object )
            {
                  delete Object;
            }
      }

      m_Timer.start( 1000, TRUE );
}

/** http callback function */
00345 int DCUpdateManager::HttpCallBack( CObject *, CObject * object )
{
      switch(((CDCMessage*)object)->m_eType)
      {
            case DC_MESSAGE_CONNECTION_STATE:
            {
                  CMessageConnectionState *msg = (CMessageConnectionState*)object;

                  if ( msg->m_eState == estDISCONNECTED )
                  {
                        if ( (m_pHttp->GetHttpError() == 200) && (m_pHttp->GetData(0) == TRUE) )
                        {
                              printf("finished\n");
                              m_bRun = FALSE;
                        }
                        
                        // redirect
                        if ( m_pHttp->GetHttpError() == 302 )
                        {
                              m_pHttp->GetUrl(m_pHttp->GetLocation());
                        }
                        else
                        {
                              m_bRun = FALSE;
                        }
                  }

                  break;
            }

            case DC_MESSAGE_TRANSFER:
            {
                  if ( DC_CallBack(object) != -1 )
                  {
                        object = 0;
                  }

                  break;
            }

            default:
            {
                  break;
            }
      }

      if ( object )
      {
            delete object;
      }

      return 0;
}

/** */
00400 bool DCUpdateManager::GetUrl( CString url )
{
      bool res = FALSE;

      if ( m_pHttp )
      {
            delete m_pHttp;
      }
      
      m_pHttp = new CHttp();
      m_pHttp->SetCallBackFunction( new CCallback<DCUpdateManager>( this, &DCUpdateManager::HttpCallBack ) );
      m_sUrl = url;
                        
      if ( m_pHttp->GetUrl(m_sUrl) == 0 )
      {
            res = TRUE;
      }

      if ( !res )
      {
            // error
            delete m_pHttp;
            m_pHttp = 0;
            m_sUrl = "";
      }
      
      return res;
}

/** */
00430 CList<DCUpdateEntry> * DCUpdateManager::ParseConfig( CByteArray * in )
{
      CXml * xml;
      xmlNodePtr n1,n2;
      CList<DCUpdateEntry> * list;

      // sanity check
      if ( !in )
      {
            return 0;
      }
      
      list = new CList<DCUpdateEntry>();
      
      xml = new CXml();
      
      if ( xml->ParseMemory( (const char*)in->Data(), in->Size() ) == TRUE )
      {
            for(n1=xml->doc()->children;n1!=0;n1=n1->next)
            {
                  if ( xml->name(n1) == "update" )
                  {
                        for(n2=n1->xmlChildrenNode;n2!=0;n2=n2->next)
                        {
                              if ( xml->name(n2) == "entry" )
                              {
                                    DCUpdateEntry * entry;
                                    
                                    entry = new DCUpdateEntry();
                                    
                                    //printf("entry found %s\n",xml->prop(n2,"name").Data());

                                    entry->m_sName    = xml->prop(n2,"name");
                                    entry->m_sVersion = xml->prop(n2,"version");
                                    entry->m_nTime    = xml->prop(n2,"date").asULL();
                                    entry->m_sUrl     = xml->prop(n2,"url");
                                    entry->m_sComp    = xml->prop(n2,"comp");
                                    
                                    list->Add(entry);
                              }
                        }
                  }
            }
      }
      
      delete xml;

      // remove a empty list
      if ( list->Count() == 0 )
      {
            delete list;
            list = 0;
      }
      
      return list;
}

/** */
00488 CList<DCUpdateEntry> * DCUpdateManager::LoadConfig()
{
      CList<DCUpdateEntry> * list = 0;
      
      // load old list
      QFile f((g_pConfig->GetConfigPath()+DIRSEPARATOR+"update.xml").Data());
                                    
      if ( f.open(IO_ReadOnly) )
      {
            if ( f.size() > 0 )
            {
                  CByteArray ba;
                  ba.SetSize(f.size());
                                                
                  if ( f.readBlock( (char*)ba.Data(), f.size()) == f.size() )
                  {
                        list = ParseConfig(&ba);
                  }
            }
            
            f.close();
      }

      return list;
}

/** */
00515 void DCUpdateManager::SaveConfig( CList<DCUpdateEntry> * list )
{
      CXml * xml;
      xmlDocPtr doc;
      xmlNodePtr node;
      CString s;
      DCUpdateEntry * ue = 0;
      
      xml = new CXml();

      doc = xmlNewDoc((const xmlChar*)"1.0");

      doc->children = xmlNewDocNode(doc,0,(const xmlChar*)"update",0);

      while( (ue=list->Next(ue)) != 0 )
      {
            node = xmlNewChild( doc->children, 0, (const xmlChar*)"entry", 0 );
            xml->xmlNewStringProp(node,"name",ue->m_sName);
            xml->xmlNewStringProp(node,"version",ue->m_sVersion);
            xml->xmlNewStringProp(node,"date",CString().setNum(ue->m_nTime));
            xml->xmlNewStringProp(node,"url",ue->m_sUrl);
            xml->xmlNewStringProp(node,"comp",ue->m_sComp);
      }

      s = g_pConfig->GetConfigPath()+DIRSEPARATOR+"update.xml";

      if ( xmlSaveFormatFile(s.Data(),doc,1) == -1 )
      {
      }

      xmlFreeDoc(doc);

      delete xml;
}

/** */
00551 void DCUpdateManager::CheckConfig( CByteArray * in )
{
      DCUpdateEntry * uo=0,* un = 0;

      // parse content
      CList<DCUpdateEntry> * listnew = ParseConfig(in);
      CList<DCUpdateEntry> * listold = 0;
                              
      if ( !listnew )
      {
            printf("error parse content\n");
            
            return;
      }
      
      listold = LoadConfig();
                                    
      if ( listold )
      {
            // compare date and remove old entry
            while((un=listnew->Next(un))!=0)
            {
                  uo = 0;
                  while((uo=listold->Next(uo))!=0)
                  {
                        if ( (un->m_sName == uo->m_sName) &&
                             (un->m_nTime <= uo->m_nTime) )
                        {
                              listnew->Del(un);
                              un=0;
                              break;
                        }
                        
                        // check compression and remove bz2 if it not supported
#ifndef HAVE_LIBBZ2
                        if ( un->m_sComp == "bz2" )
                        {
                              AppendLog( tr("Update available but no bz2 support for ") + un->m_sName.Data() );
                              listnew->Del(un);
                              un=0;
                              break;
                        }
#endif
                  }
            }
      }
      else
      {
            listold = new CList<DCUpdateEntry>();
      }

      // update view
      un = 0;
      while((un=listnew->Next(un))!=0)
      {
            AppendLog( tr("Update available for ") + un->m_sName.Data() );
      }
      
      AppendLog( CString().setNum(listnew->Count()).Data() + tr(" update(s) available") );
                                    
      if ( listnew->Count() == 0 )
      {
            // no new updates
            delete listnew;
            delete listold;
            listnew = 0;
            listold = 0;
      }
                                    
      m_pUpdateListNew = listnew;
      m_pUpdateListOld = listold;
}

/** */
00625 bool DCUpdateManager::SaveContent( DCUpdateEntry * entry, CByteArray * in )
{
      QString s;
      bool res = FALSE;
      CByteArray ba;
      
      s = (g_pConfig->GetConfigPath()+DIRSEPARATOR).Data();
      
      if ( entry->m_sName == "translator" )
      {
            s += "dctranslator.cfg";
      }
      else if ( entry->m_sName == "emoticons xml" )
      {
            s += "emoticons.xml";
      }
      else if ( entry->m_sName == "emoticons xpm" )
      {
            s += "emoticons.xpm";
      }
      else
      {
            printf("unknown content\n");
            return res;
      }
      
      ba.SetSize(0);
      
      // decompress data
      if ( entry->m_sComp == "bz2" )
      {
            CBZ bz;

            if ( bz.Decompress( in, &ba ) == FALSE )
            {
                  ba.SetSize(0);
            }
      }
      else
      {
            ba.Append(in->Data(),in->Size());
      }
      
      if ( ba.Size() == 0 )
      {
            return res;
      }
      
      QFile f(s);
      
      if ( f.open(IO_WriteOnly|IO_Truncate) )
      {
            if ( f.writeBlock( (char*)ba.Data(), ba.Size()) == ba.Size() )
            {
                  res = TRUE;
            }
      
            f.close();
      }
      
      // load new files
      if ( res == TRUE )
      {
            if ( entry->m_sName == "translator" )
            {
            }
            else if ( entry->m_sName == "emoticons xml" )
            {
                  g_pConfig->InitMimeSourceFactory();
            }
            else if ( entry->m_sName == "emoticons xpm" )
            {
                  g_pConfig->InitMimeSourceFactory();
            }
      }
      
      return res;
}

Generated by  Doxygen 1.6.0   Back to index