From 09b9702d80aeb29444eeea7166165f114dee5f41 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Duraffort?= Date: Mon, 10 Dec 2007 23:12:45 +0000 Subject: [PATCH] Modify the update system : I will add more functionnality but this is the beginning --- include/vlc_update.h | 126 +-- modules/control/rc.c | 124 +-- modules/gui/qt4/dialogs/help.cpp | 153 +--- modules/gui/qt4/dialogs/help.hpp | 21 +- src/misc/update.c | 1341 ++++-------------------------- 5 files changed, 230 insertions(+), 1535 deletions(-) diff --git a/include/vlc_update.h b/include/vlc_update.h index f2588ebdfa..f36e4059e5 100644 --- a/include/vlc_update.h +++ b/include/vlc_update.h @@ -36,45 +36,11 @@ * @{ */ -#define UPDATE_FILE_TYPE_ALL (~0) -#define UPDATE_FILE_TYPE_NONE 0 - -#define UPDATE_FILE_TYPE_UNDEF 1 -#define UPDATE_FILE_TYPE_INFO 2 -#define UPDATE_FILE_TYPE_SOURCE 4 -#define UPDATE_FILE_TYPE_BINARY 8 -#define UPDATE_FILE_TYPE_PLUGIN 16 - -#define UPDATE_RELEASE_STATUS_ALL (~0) -#define UPDATE_RELEASE_STATUS_NONE 0 - -#define UPDATE_RELEASE_STATUS_OLDER 1 -#define UPDATE_RELEASE_STATUS_EQUAL 2 -#define UPDATE_RELEASE_STATUS_NEWER 4 - -#define UPDATE_RELEASE_TYPE_STABLE 1 -#define UPDATE_RELEASE_TYPE_TESTING 2 -#define UPDATE_RELEASE_TYPE_UNSTABLE 4 - -#define UPDATE_FAIL 0 -#define UPDATE_SUCCESS 1 -#define UPDATE_NEXT 0 -#define UPDATE_PREV 2 -#define UPDATE_MIRROR 4 -#define UPDATE_RELEASE 8 -#define UPDATE_FILE 16 -#define UPDATE_RESET 32 - -/** - * Describes an update file - */ -struct update_file_t +enum { - int i_type; ///< File type - char* psz_md5; ///< MD5 hash - long int l_size; ///< File size in bytes - char* psz_url; ///< Relative (to a mirror) or absolute url - char* psz_description; ///< Plain text description + UpdateReleaseStatusOlder, + UpdateReleaseStatusEqual, + UpdateReleaseStatusNewer }; /** @@ -82,32 +48,13 @@ struct update_file_t */ struct update_release_t { - char* psz_major; ///< Version major string - char* psz_minor; ///< Version minor string - char* psz_revision; ///< Version revision string - char* psz_extra; ///< Version extra string - - char* psz_svn_revision; ///< SVN revision - - int i_type; ///< Release type - - int i_status; ///< Release status compared to current VLC version - - struct update_file_t* p_files; ///< Files list - int i_files; ///< Number of files in the files list -}; - -/** - * Describes a mirror - */ -struct update_mirror_t -{ - char *psz_name; ///< Mirror name - char *psz_location; ///< Mirror geographical location - char *psz_type; ///< Mirror type (FTP, HTTP, ...) - - char *psz_base_url; ///< Mirror base url - + int i_major; ///< Version major + int i_minor; ///< Version minor + int i_revision; ///< Version revision + char* psz_svnrev; ///< SVN revision + char* psz_extra; ///< Version extra + char* psz_url; ///< Download URL + char* psz_desc; ///< Release description }; /** @@ -116,60 +63,17 @@ struct update_mirror_t struct update_t { libvlc_int_t *p_libvlc; - vlc_mutex_t lock; - - struct update_release_t *p_releases; ///< Releases (version) list - int i_releases; ///< Number of releases - vlc_bool_t b_releases; ///< True if we have a releases list - - struct update_mirror_t *p_mirrors; ///< Mirrors list - int i_mirrors; ///< Number of mirrors - vlc_bool_t b_mirrors; ///< True if we have a mirrors list + struct update_release_t release; ///< Release (version) }; -/** - * The update iterator structure. Usefull to browse the update object seamlessly - */ -struct update_iterator_t -{ - update_t *p_u; ///< Pointer to VLC update object - - int i_r; ///< Position in the releases list - int i_f; ///< Position in the release's files list - int i_m; ///< Position in the mirrors list - - int i_t; ///< File type bitmask - int i_rs; ///< Release status bitmask - int i_rt; ///< Release type bitmask - - struct update_file_t file; ///< Local copy of the current file's information - struct - { - char *psz_version; ///< Version string - char *psz_svn_revision; ///< SVN revision - int i_status; ///< Status - int i_type; ///< Type - } release; ///< Local 'copy' of the current release's information - struct - { - char *psz_name; ///< Name - char *psz_location; ///< Geographical location - char *psz_type; ///< Type (HTTP, FTP, ...) - } mirror; ///< Local 'copy' of the current mirror's information -}; #define update_New( a ) __update_New( VLC_OBJECT( a ) ) VLC_EXPORT( update_t *, __update_New, ( vlc_object_t * ) ); -VLC_EXPORT( void, update_Delete, (update_t * ) ); -VLC_EXPORT( void, update_Check, ( update_t *, vlc_bool_t ) ); - -VLC_EXPORT( update_iterator_t *, update_iterator_New, ( update_t * ) ); -VLC_EXPORT( void, update_iterator_Delete, ( update_iterator_t * ) ); -VLC_EXPORT( unsigned int, update_iterator_Action, ( update_iterator_t *, int ) ); -VLC_EXPORT( unsigned int, update_iterator_ChooseMirrorAndFile, ( update_iterator_t *, int, int, int ) ); -VLC_EXPORT( void, update_download, ( update_iterator_t *, const char * ) ); +VLC_EXPORT( void, update_Delete, ( update_t * ) ); +VLC_EXPORT( void, update_Check, ( update_t * ) ); +VLC_EXPORT( int, update_CompareReleaseToCurrent, ( update_t * ) ); /** * @} diff --git a/modules/control/rc.c b/modules/control/rc.c index 1bb743bd73..3f9133dd48 100644 --- a/modules/control/rc.c +++ b/modules/control/rc.c @@ -96,7 +96,7 @@ static int AudioConfig ( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); static int Menu ( vlc_object_t *, char const *, vlc_value_t, vlc_value_t, void * ); -static void checkUpdates( intf_thread_t *p_intf, char *psz_arg ); +static void checkUpdates( intf_thread_t *p_intf ); /* Status Callbacks */ static int TimeOffsetChanged( vlc_object_t *, char const *, @@ -752,7 +752,7 @@ static void Run( intf_thread_t *p_intf ) } else if( !strcmp( psz_cmd, "check-updates" ) ) { - checkUpdates( p_intf, psz_arg ); + checkUpdates( p_intf ); } else if( !strcmp( psz_cmd, "key" ) || !strcmp( psz_cmd, "hotkey" ) ) { @@ -2105,116 +2105,20 @@ static input_item_t *parse_MRL( intf_thread_t *p_intf, char *psz_mrl ) /***************************************************************************** * checkUpdates : check for updates ****************************************************************************/ -static void checkUpdates( intf_thread_t *p_intf, char *psz_arg ) +static void checkUpdates( intf_thread_t *p_intf ) { - update_iterator_t *p_uit; update_t *p_u = update_New( p_intf ); if( p_u == NULL ) return; - p_uit = update_iterator_New( p_u ); - if( p_uit ) - { - int s = 0, t = 0; - - if( strstr( psz_arg, "newer" ) ) - s |= UPDATE_RELEASE_STATUS_NEWER; - if( strstr( psz_arg, "equal" ) ) - s |= UPDATE_RELEASE_STATUS_EQUAL; - if( strstr( psz_arg, "older" ) ) - s |= UPDATE_RELEASE_STATUS_OLDER; - if( s ) p_uit->i_rs = s; - else p_uit->i_rs = UPDATE_RELEASE_STATUS_NEWER; - - if( strstr( psz_arg, "undef" ) ) - t |= UPDATE_FILE_TYPE_UNDEF; - if( strstr( psz_arg, "info" ) ) - t |= UPDATE_FILE_TYPE_INFO; - if( strstr( psz_arg, "source" ) ) - t |= UPDATE_FILE_TYPE_SOURCE; - if( strstr( psz_arg, "binary" ) ) - t |= UPDATE_FILE_TYPE_BINARY; - if( strstr( psz_arg, "plugin" ) ) - t |= UPDATE_FILE_TYPE_PLUGIN; - if( t ) p_uit->i_t = t; - - update_Check( p_u, VLC_FALSE ); - update_iterator_Action( p_uit, UPDATE_MIRROR ); - msg_rc( "\nUsing mirror: %s (%s) [%s]", - p_uit->mirror.psz_name, - p_uit->mirror.psz_location, - p_uit->mirror.psz_type ); - while( (s = update_iterator_Action( p_uit, UPDATE_FILE )) != UPDATE_FAIL ) - { - char *psz_tmp; - if( s & UPDATE_RELEASE ) - { - switch( p_uit->release.i_status ) - { - case UPDATE_RELEASE_STATUS_OLDER: - psz_tmp = strdup( "older" ); - break; - case UPDATE_RELEASE_STATUS_EQUAL: - psz_tmp = strdup( "equal" ); - break; - case UPDATE_RELEASE_STATUS_NEWER: - psz_tmp = strdup( "newer" ); - break; - default: - psz_tmp = strdup( "?!?" ); - break; - } - msg_rc( "\n+----[ VLC %s %s (%s) ] ", - p_uit->release.psz_version, - p_uit->release.psz_svn_revision, - psz_tmp ); - free( psz_tmp ); - } - switch( p_uit->file.i_type ) - { - case UPDATE_FILE_TYPE_UNDEF: - psz_tmp = strdup( "undef" ); - break; - case UPDATE_FILE_TYPE_INFO: - psz_tmp = strdup( "info" ); - break; - case UPDATE_FILE_TYPE_SOURCE: - psz_tmp = strdup( "source" ); - break; - case UPDATE_FILE_TYPE_BINARY: - psz_tmp = strdup( "binary" ); - break; - case UPDATE_FILE_TYPE_PLUGIN: - psz_tmp = strdup( "plugin" ); - break; - default: - psz_tmp = strdup( "?!?" ); - break; - } - msg_rc( "| %s (%s)", p_uit->file.psz_description, psz_tmp ); - free( psz_tmp ); - if( p_uit->file.l_size ) - { - if( p_uit->file.l_size > 1024 * 1024 * 1024 ) - asprintf( &psz_tmp, "(%ld GB)", - p_uit->file.l_size / (1024*1024*1024) ); - if( p_uit->file.l_size > 1024 * 1024 ) - asprintf( &psz_tmp, "(%ld MB)", - p_uit->file.l_size / (1024*1024) ); - else if( p_uit->file.l_size > 1024 ) - asprintf( &psz_tmp, "(%ld kB)", - p_uit->file.l_size / 1024 ); - else - asprintf( &psz_tmp, "(%ld B)", p_uit->file.l_size ); - } - else - { - psz_tmp = strdup( "" ); - } - msg_rc( "| %s %s", p_uit->file.psz_url, psz_tmp ); - msg_rc( "+----" ); - free( psz_tmp ); - } - msg_rc( "" ); - update_iterator_Delete( p_uit ); - } + + update_Check( p_u ); + msg_rc( "\nChecking for updates" ); + + if( update_CompareReleaseToCurrent( p_u ) == UpdateReleaseStatusNewer ) + msg_rc( "\n+----[ VLC %i.%i.%i%s ] ", p_u->release.i_major, + p_u->release.i_minor, + p_u->release.i_revision, + p_u->release.psz_extra ); + else + msg_rc( "\n+----Last version" ); update_Delete( p_u ); } diff --git a/modules/gui/qt4/dialogs/help.cpp b/modules/gui/qt4/dialogs/help.cpp index 72fd52316c..409dbafce3 100644 --- a/modules/gui/qt4/dialogs/help.cpp +++ b/modules/gui/qt4/dialogs/help.cpp @@ -35,15 +35,12 @@ #include #include #include -#include -#include #include -#include HelpDialog *HelpDialog::instance = NULL; -HelpDialog::HelpDialog( intf_thread_t *_p_intf) : QVLCFrame( _p_intf ) +HelpDialog::HelpDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf ) { setWindowTitle( qtr( "Help" ) ); resize( 600, 560 ); @@ -98,20 +95,20 @@ AboutDialog::AboutDialog( intf_thread_t *_p_intf) : QVLCFrame( _p_intf ) QLabel *infoLabel = new QLabel( "VLC media player " PACKAGE_VERSION "\n\n" "(c) 1996-2007 - the VideoLAN Team\n\n" + qtr( "VLC media player is a free media player, made by the " - "VideoLAN Team.\nIt is a standalone multimedia player, " - "encoder and streamer, that can read from many supports " - "(files, CDs, DVDs, networks, capture cards...) and that " - "works on many platforms.\n\n" ) + "VideoLAN Team.\nIt is a standalone multimedia player, " + "encoder and streamer, that can read from many supports " + "(files, CDs, DVDs, networks, capture cards...) and that " + "works on many platforms.\n\n" ) + qtr( "You are using the new Qt4 Interface.\n" ) + qtr( "Compiled by " ) + qfu( VLC_CompileBy() )+ "@" + qfu( VLC_CompileDomain() ) + ".\n" - + "Compiler: " + qfu( VLC_Compiler() ) +".\n" + + "Compiler: " + qfu( VLC_Compiler() ) + ".\n" + qtr( "Based on SVN revision: " ) + qfu( VLC_Changeset() ) + ".\n\n" + qtr( "This program comes with NO WARRANTY, to the extent " "permitted by the law; read the distribution tab.\n\n" ) + "The VideoLAN team \n" - "http://www.videolan.org/\n") ; + "http://www.videolan.org/\n" ); infoLabel->setWordWrap( infoLabel ); QLabel *iconVLC2 = new QLabel; @@ -129,7 +126,7 @@ AboutDialog::AboutDialog( intf_thread_t *_p_intf) : QVLCFrame( _p_intf ) QWidget *thanksWidget = new QWidget( this ); QVBoxLayout *thanksLayout = new QVBoxLayout( thanksWidget ); - QLabel *thanksLabel = new QLabel( qtr("We would like to thank the whole " + QLabel *thanksLabel = new QLabel( qtr( "We would like to thank the whole " "community, the testers, our users and the following people " "(and the missing ones...) for their collaboration to " "provide the best software." ) ); @@ -165,45 +162,32 @@ void AboutDialog::close() UpdateDialog *UpdateDialog::instance = NULL; -UpdateDialog::UpdateDialog( intf_thread_t *_p_intf) : QVLCFrame( _p_intf ) +UpdateDialog::UpdateDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf ) { setWindowTitle( qtr( "Update" ) ); - resize( 230, 180 ); + resize( 320, 120 ); QGridLayout *layout = new QGridLayout( this ); + updateBrowser = new QTextBrowser( this ); + updateBrowser->setOpenExternalLinks( true ); + updateBrowser->setHtml( qtr( " \ +
Push the update button to get the updates
" ) ); + QPushButton *closeButton = new QPushButton( qtr( "&Close" ) ); - updateButton = new QPushButton( qtr( "&Update List" ) ); + QPushButton *updateButton = new QPushButton( qtr( "&Update List" ) ); updateButton->setDefault( true ); - QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal); + QDialogButtonBox *buttonBox = new QDialogButtonBox( Qt::Horizontal ); buttonBox->addButton( updateButton, QDialogButtonBox::ActionRole ); buttonBox->addButton( closeButton, QDialogButtonBox::AcceptRole ); - QGroupBox *checkGroup = new QGroupBox( qtr( "Select Package" ) ); - QGridLayout *checkLayout = new QGridLayout( checkGroup ); - checkInfo = new QCheckBox( qtr( "Information" ) ); - checkSource = new QCheckBox( qtr( "Sources" ) ); - checkBinary = new QCheckBox( qtr( "Binary" ) ); - checkPlugin = new QCheckBox( qtr( "Plugin" ) ); - - checkInfo->setDisabled( true ); - checkSource->setDisabled( true ); - checkBinary->setDisabled( true ); - checkPlugin->setDisabled( true ); - - checkLayout->addWidget( checkInfo, 0, 0 ); - checkLayout->addWidget( checkSource, 1, 0 ); - checkLayout->addWidget( checkBinary, 2, 0 ); - checkLayout->addWidget( checkPlugin, 3, 0 ); - - layout->addWidget( checkGroup, 0, 0 ); + layout->addWidget( updateBrowser, 0, 0 ); layout->addWidget( buttonBox, 1, 0 ); BUTTONACT( updateButton, updateOrUpload() ); BUTTONACT( closeButton, close() ); p_update = update_New( _p_intf ); - b_updated = false; } UpdateDialog::~UpdateDialog() @@ -218,101 +202,18 @@ void UpdateDialog::close() void UpdateDialog::updateOrUpload() { - if( !p_update ) return; - if( !b_updated ) + update_Check( p_update ); + + if( update_CompareReleaseToCurrent( p_update ) == UpdateReleaseStatusNewer ) { - update_Check( p_update, VLC_FALSE ); - update_iterator_t *p_updateit = update_iterator_New( p_update ); - bool b_download = false; - if( p_updateit ) - { - p_updateit->i_rs = UPDATE_RELEASE_STATUS_NEWER; - p_updateit->i_t = UPDATE_FILE_TYPE_ALL; - update_iterator_Action( p_updateit, UPDATE_MIRROR ); - while( update_iterator_Action( p_updateit, UPDATE_FILE ) != UPDATE_FAIL ) - { - switch( p_updateit->file.i_type ) - { - case UPDATE_FILE_TYPE_INFO: - checkInfo->setText( qtr( "Information" ) + " (" + qfu( p_updateit->release.psz_version ) + ")" ); - checkInfo->setDisabled( false ); - checkInfo->setCheckState( Qt::Checked ); - b_download = true; - break; - case UPDATE_FILE_TYPE_SOURCE: - checkSource->setText( qtr( "Source" ) + " (" + qfu( p_updateit->release.psz_version ) + ")" ); - checkSource->setDisabled( false ); - checkSource->setCheckState( Qt::Checked ); - b_download = true; - break; - case UPDATE_FILE_TYPE_BINARY: - checkBinary->setText( qtr( "Binary" ) + " (" + qfu( p_updateit->release.psz_version ) + ")" ); - checkBinary->setDisabled( false ); - checkBinary->setCheckState( Qt::Checked ); - b_download = true; - break; - case UPDATE_FILE_TYPE_PLUGIN: - checkPlugin->setText( qtr( "Plugin" ) + " (" + qfu( p_updateit->release.psz_version ) + ")"); - checkPlugin->setDisabled( false ); - checkPlugin->setCheckState( Qt::Checked ); - b_download = true; - break; - default: - break; - } - } - } - if( b_download ) - { - updateButton->setText(qtr( "Download" ) ); - b_updated = true; - } - update_iterator_Delete( p_updateit ); + updateBrowser->setHtml( qtr( " \ +

" ) + qtu( (QString)p_update->release.psz_desc ) + + qtr( "

You can download the latest version of VLC release.psz_url ) + qtr( "\">here
" ) ); } else { - update_iterator_t *p_updateit = update_iterator_New( p_update ); - bool b_download = false; - if( p_updateit ) - { - QString saveDir = QFileDialog::getExistingDirectory( this, qtr( "Choose a directory..." ), - qfu( p_intf->p_libvlc->psz_homedir ) ); - - p_updateit->i_rs = UPDATE_RELEASE_STATUS_NEWER; - p_updateit->i_t = UPDATE_FILE_TYPE_ALL; - update_iterator_Action( p_updateit, UPDATE_MIRROR ); - - while( update_iterator_Action( p_updateit, UPDATE_FILE ) != UPDATE_FAIL ) - { - b_download = false; - switch( p_updateit->file.i_type ) - { - case UPDATE_FILE_TYPE_INFO: - if( checkInfo->isChecked() ) - b_download = true; - break; - case UPDATE_FILE_TYPE_SOURCE: - if( checkSource->isChecked() ) - b_download = true; - break; - case UPDATE_FILE_TYPE_BINARY: - if( checkBinary->isChecked() ) - b_download = true; - break; - case UPDATE_FILE_TYPE_PLUGIN: - if( checkPlugin->isChecked() ) - b_download = true; - break; - default: - break; - } - if( b_download ) - { - QString strFileName = p_updateit->file.psz_url; - strFileName.remove( 0, strFileName.lastIndexOf( "/" ) + 1 ); - update_download( p_updateit, qtu( ( saveDir + strFileName ) ) ); - } - } - } + updateBrowser->setHtml( " \ +
You have the latest version of VLC.
" ); } } diff --git a/modules/gui/qt4/dialogs/help.hpp b/modules/gui/qt4/dialogs/help.hpp index e8bf68ffe0..9a8df3cafa 100644 --- a/modules/gui/qt4/dialogs/help.hpp +++ b/modules/gui/qt4/dialogs/help.hpp @@ -29,7 +29,7 @@ #include "util/qvlcframe.hpp" class QPushButton; -class QCheckBox; +class QTextBrowser; class HelpDialog : public QVLCFrame { @@ -44,7 +44,7 @@ public: virtual ~HelpDialog(); private: - HelpDialog( intf_thread_t *); + HelpDialog( intf_thread_t * ); static HelpDialog *instance; public slots: void close(); @@ -58,13 +58,13 @@ public: static AboutDialog * getInstance( intf_thread_t *p_intf ) { if( !instance) - instance = new AboutDialog( p_intf); + instance = new AboutDialog( p_intf ); return instance; } virtual ~AboutDialog(); private: - AboutDialog( intf_thread_t *); + AboutDialog( intf_thread_t * ); static AboutDialog *instance; public slots: void close(); @@ -77,22 +77,17 @@ class UpdateDialog : public QVLCFrame public: static UpdateDialog * getInstance( intf_thread_t *p_intf ) { - if( !instance) - instance = new UpdateDialog( p_intf); + if( !instance ) + instance = new UpdateDialog( p_intf ); return instance; } virtual ~UpdateDialog(); private: - UpdateDialog( intf_thread_t *); + UpdateDialog( intf_thread_t * ); static UpdateDialog *instance; - QPushButton *updateButton; - QCheckBox *checkInfo; - QCheckBox *checkSource; - QCheckBox *checkBinary; - QCheckBox *checkPlugin; update_t *p_update; - bool b_updated; + QTextBrowser *updateBrowser; private slots: void close(); void updateOrUpload(); diff --git a/src/misc/update.c b/src/misc/update.c index 37d6f806e5..8a17e2a8c0 100644 --- a/src/misc/update.c +++ b/src/misc/update.c @@ -21,11 +21,6 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. *****************************************************************************/ -/* TODO - * --> check release types. - * --> make sure that the version comparision method is ok. - */ - /** * \file * This file contains functions related to VLC and plugins update management @@ -45,65 +40,44 @@ #include #include -#include #include #include -#include /***************************************************************************** * Misc defines *****************************************************************************/ -/* All release notes and source packages should match on "*" - * Only binary installers are OS specific ( we only provide these - * for Win32, Mac OS X, WincCE, beos(?) ) */ +//#define UPDATE_VLC_STATUS_URL "http://zen.via.ecp.fr/~ivoire/videolan/update" + #if defined( UNDER_CE ) -# define UPDATE_VLC_OS "*" -# define UPDATE_VLC_ARCH "*" +# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-ce" #elif defined( WIN32 ) -# define UPDATE_VLC_OS "windows" -# define UPDATE_VLC_ARCH "i386" +# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-win-x86" #elif defined( __APPLE__ ) # define UPDATE_VLC_OS "macosx" # if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ ) -# define UPDATE_VLC_ARCH "ppc" +# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-ppc" # else -# define UPDATE_VLC_ARCH "x86" +# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-x86" # endif #elif defined( SYS_BEOS ) -# define UPDATE_VLC_OS "beos" -# define UPDATE_VLC_ARCH "i386" +# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-beos-x86" #else -# define UPDATE_VLC_OS "*" -# define UPDATE_VLC_ARCH "*" +# define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status" #endif -#define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status.xml" -#define UPDATE_VLC_MIRRORS_URL "http://update.videolan.org/mirrors.xml" - #define STRDUP( a ) ( a ? strdup( a ) : NULL ) + /***************************************************************************** * Local Prototypes *****************************************************************************/ +static void EmptyRelease( update_t *p_update ); +static void GetUpdateFile( update_t *p_update ); +static int cmp( int i1, int i2 ); +static int CompareReleases( const struct update_release_t *p1, + const struct update_release_t *p2 ); -static void FreeMirrorsList( update_t * ); -static void FreeReleasesList( update_t * ); -static void GetMirrorsList( update_t *, vlc_bool_t ); -static void GetFilesList( update_t *, vlc_bool_t ); - -static int CompareReleases( const struct update_release_t *, - const struct update_release_t * ); -static int CompareReleaseToCurrent( const struct update_release_t * ); - -static unsigned int update_iterator_Reset( update_iterator_t * ); -static unsigned int update_iterator_NextFile( update_iterator_t * ); -static unsigned int update_iterator_PrevFile( update_iterator_t * ); -static unsigned int update_iterator_NextMirror( update_iterator_t * ); -static unsigned int update_iterator_PrevMirror( update_iterator_t * ); - -static void update_iterator_GetData( update_iterator_t * ); -static void update_iterator_ClearData( update_iterator_t * ); /***************************************************************************** * Update_t functions @@ -128,22 +102,12 @@ update_t *__update_New( vlc_object_t *p_this ) p_update->p_libvlc = p_this->p_libvlc; - p_update->p_releases = NULL; - p_update->i_releases = 0; - p_update->b_releases = VLC_FALSE; + p_update->release.psz_svnrev = NULL; + p_update->release.psz_extra = NULL; + p_update->release.psz_url = NULL; + p_update->release.psz_desc = NULL; - p_update->p_mirrors = NULL; - p_update->i_mirrors = 0; - p_update->b_mirrors = VLC_FALSE; - -#if 1 - msg_Err( p_this, "Auto-update currently disabled." ); - vlc_mutex_destroy( &p_update->lock ); - free( p_update ); - return NULL; -#else - return p_update -#endif + return p_update; } /** @@ -157,284 +121,90 @@ void update_Delete( update_t *p_update ) assert( p_update ); vlc_mutex_destroy( &p_update->lock ); - FreeMirrorsList( p_update ); - FreeReleasesList( p_update ); - free( p_update ); -} -/** - * Empty the mirrors list - * *p_update should be locked before using this function - * - * \param p_update pointer to the update struct - * \return nothing - */ -static void FreeMirrorsList( update_t *p_update ) -{ - int i; + if( p_update->release.psz_svnrev ) + { + free( p_update->release.psz_svnrev ); + p_update->release.psz_svnrev = NULL; + } - for( i = 0; i < p_update->i_mirrors; i++ ) + if( p_update->release.psz_extra ) { - free( p_update->p_mirrors[i].psz_name ); - free( p_update->p_mirrors[i].psz_location ); - free( p_update->p_mirrors[i].psz_type ); - free( p_update->p_mirrors[i].psz_base_url ); + free( p_update->release.psz_extra ); + p_update->release.psz_extra = NULL; } - FREENULL( p_update->p_mirrors ); - p_update->i_mirrors = 0; - p_update->b_mirrors = VLC_FALSE; -} -/** - * Empty the releases list - * *p_update should be locked before calling this function - * - * \param p_update pointer to the update struct - * \return nothing - */ -static void FreeReleasesList( update_t *p_update ) -{ - int i; + if( p_update->release.psz_url ) + { + free( p_update->release.psz_url ); + p_update->release.psz_url = NULL; + } - for( i = 0; i < p_update->i_releases; i++ ) + if( p_update->release.psz_desc ) { - int j; - struct update_release_t *p_release = (p_update->p_releases + i); - for( j = 0; j < p_release->i_files; j++ ) - { - free( p_release->p_files[j].psz_md5 ); - free( p_release->p_files[j].psz_url ); - free( p_release->p_files[j].psz_description ); - } - free( p_release->psz_major ); - free( p_release->psz_minor ); - free( p_release->psz_revision ); - free( p_release->psz_extra ); - free( p_release->psz_svn_revision ); - free( p_release->p_files ); + free( p_update->release.psz_desc ); + p_update->release.psz_desc = NULL; } - FREENULL( p_update->p_releases ); - p_update->i_releases = 0; - p_update->b_releases = VLC_FALSE; + + free( p_update ); } /** - * Get the mirrors list XML file and parse it - * *p_update has to be unlocked when calling this function + * Empty the release struct * - * \param p_update pointer to the update struct - * \param b_force set to VLC_TRUE if you want to force the mirrors list update + * \param p_update update_t* pointer * \return nothing */ -static void GetMirrorsList( update_t *p_update, vlc_bool_t b_force ) +static void EmptyRelease( update_t *p_update ) { - stream_t *p_stream = NULL; - - xml_t *p_xml = NULL; - xml_reader_t *p_xml_reader = NULL; - char *psz_eltname = NULL; - //char *psz_eltvalue = NULL; - char *psz_name = NULL; - char *psz_value = NULL; - struct update_mirror_t tmp_mirror; - - vlc_mutex_lock( &p_update->lock ); - - memset( &tmp_mirror, 0, sizeof(struct update_mirror_t)); - - if( p_update->b_mirrors && b_force == VLC_FALSE ) - { - vlc_mutex_unlock( &p_update->lock ); - return; - } - - p_xml = xml_Create( p_update->p_libvlc ); - if( !p_xml ) - { - msg_Err( p_update->p_libvlc, "Failed to open XML parser" ); - goto error; - } + p_update->release.i_major = 0; + p_update->release.i_minor = 0; + p_update->release.i_revision = 0; - p_stream = stream_UrlNew( p_update->p_libvlc, UPDATE_VLC_MIRRORS_URL ); - if( !p_stream ) + if( p_update->release.psz_svnrev ) { - msg_Err( p_update->p_libvlc, "Failed to open %s for reading", - UPDATE_VLC_MIRRORS_URL ); - goto error; + free( p_update->release.psz_svnrev ); + p_update->release.psz_svnrev = NULL; } - p_xml_reader = xml_ReaderCreate( p_xml, p_stream ); - - if( !p_xml_reader ) + if( p_update->release.psz_extra ) { - msg_Err( p_update->p_libvlc, "Failed to open %s for parsing", - UPDATE_VLC_MIRRORS_URL ); - goto error; + free( p_update->release.psz_extra ); + p_update->release.psz_extra = NULL; } - if( p_update->p_mirrors ) + if( p_update->release.psz_url ) { - FreeMirrorsList( p_update ); + free( p_update->release.psz_url ); + p_update->release.psz_url = NULL; } - while( xml_ReaderRead( p_xml_reader ) == 1 ) + if( p_update->release.psz_desc ) { - switch( xml_ReaderNodeType( p_xml_reader ) ) - { - case -1: - msg_Err( p_update->p_libvlc, "Error while parsing %s", - UPDATE_VLC_MIRRORS_URL ); - goto error; - - case XML_READER_STARTELEM: - psz_eltname = xml_ReaderName( p_xml_reader ); - if( !psz_eltname ) - { - msg_Err( p_update->p_libvlc, "Error while parsing %s", - UPDATE_VLC_MIRRORS_URL ); - goto error; - } - - while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) - { - psz_name = xml_ReaderName( p_xml_reader ); - psz_value = xml_ReaderValue( p_xml_reader ); - - if( !psz_name || !psz_value ) - { - msg_Err( p_update->p_libvlc, "Error while parsing %s", - UPDATE_VLC_MIRRORS_URL ); - goto error; - } - - if( !strcmp( psz_eltname, "mirror" ) ) - { - if( !strcmp( psz_name, "name" ) ) - tmp_mirror.psz_name = STRDUP( psz_value ); - else if( !strcmp( psz_name, "location" ) ) - tmp_mirror.psz_location = STRDUP( psz_value ); - } - else if( !strcmp( psz_eltname, "url" ) ) - { - if( !strcmp( psz_name, "type" ) ) - tmp_mirror.psz_type = STRDUP( psz_value ); - else if( !strcmp( psz_name, "base" ) ) - tmp_mirror.psz_base_url = STRDUP( psz_value ); - } - FREENULL( psz_name ); - FREENULL( psz_value ); - } - if( !strcmp( psz_eltname, "url" ) ) - { - /* append to mirrors list */ - p_update->p_mirrors = - (struct update_mirror_t *)realloc( p_update->p_mirrors, - (++(p_update->i_mirrors)) - *sizeof( struct update_mirror_t ) ); - p_update->p_mirrors[ p_update->i_mirrors - 1 ] = - tmp_mirror; - tmp_mirror.psz_name = STRDUP( tmp_mirror.psz_name ); - tmp_mirror.psz_location = STRDUP( tmp_mirror.psz_location ); - tmp_mirror.psz_type = NULL; - tmp_mirror.psz_base_url = NULL; - } - FREENULL( psz_eltname ); - break; - - case XML_READER_ENDELEM: - psz_eltname = xml_ReaderName( p_xml_reader ); - if( !psz_eltname ) - { - msg_Err( p_update->p_libvlc, "Error while parsing %s", - UPDATE_VLC_MIRRORS_URL ); - goto error; - } - - if( !strcmp( psz_eltname, "mirror" ) ) - { - FREENULL( tmp_mirror.psz_name ); - FREENULL( tmp_mirror.psz_location ); - } - - FREENULL( psz_eltname ); - break; - - /*case XML_READER_TEXT: - psz_eltvalue = xml_ReaderValue( p_xml_reader ); - FREENULL( psz_eltvalue ); - break;*/ - } - } - - p_update->b_mirrors = VLC_TRUE; - - error: - vlc_mutex_unlock( &p_update->lock ); - - free( psz_eltname ); - //free( psz_eltvalue ); - free( psz_name ); - free( psz_value ); - - free( tmp_mirror.psz_name ); - free( tmp_mirror.psz_location ); - free( tmp_mirror.psz_type ); - free( tmp_mirror.psz_base_url ); - - if( p_xml_reader && p_xml ) - xml_ReaderDelete( p_xml, p_xml_reader ); - if( p_stream ) - stream_Delete( p_stream ); - if( p_xml ) - xml_Delete( p_xml ); + free( p_update->release.psz_desc ); + p_update->release.psz_desc = NULL; + } } /** - * Get the files list XML file and parse it + * Get the update file and parse it * *p_update has to be unlocked when calling this function * * \param p_update pointer to update struct - * \param b_force set to VLC_TRUE if you want to force the files list update * \return nothing */ -static void GetFilesList( update_t *p_update, vlc_bool_t b_force ) +static void GetUpdateFile( update_t *p_update ) { stream_t *p_stream = NULL; - - xml_t *p_xml = NULL; - xml_reader_t *p_xml_reader = NULL; - - char *psz_eltname = NULL; - char *psz_eltvalue = NULL; - char *psz_name = NULL; - char *psz_value = NULL; - - struct update_release_t *p_release = NULL; - struct update_release_t tmp_release; - struct update_file_t tmp_file; - - vlc_bool_t b_os = VLC_FALSE, b_arch = VLC_FALSE; - - memset( &tmp_release, 0, sizeof(struct update_release_t) ); - memset( &tmp_file, 0, sizeof(struct update_file_t) ); - - tmp_release.i_type = UPDATE_RELEASE_TYPE_STABLE; + int i_major = 0; + int i_minor = 0; + int i_revision = 0; + char *psz_extra = NULL; + char *psz_svnrev = NULL; + char *psz_line = NULL; vlc_mutex_lock( &p_update->lock ); - if( p_update->b_releases && b_force == VLC_FALSE ) - { - vlc_mutex_unlock( &p_update->lock ); - return; - } - - p_xml = xml_Create( p_update->p_libvlc ); - if( !p_xml ) - { - msg_Err( p_update->p_libvlc, "Failed to open XML parser" ); - goto error; - } - p_stream = stream_UrlNew( p_update->p_libvlc, UPDATE_VLC_STATUS_URL ); if( !p_stream ) { @@ -443,950 +213,171 @@ static void GetFilesList( update_t *p_update, vlc_bool_t b_force ) goto error; } - p_xml_reader = xml_ReaderCreate( p_xml, p_stream ); - - if( !p_xml_reader ) + /* Try to read three lines */ + if( !( psz_line = stream_ReadLine( p_stream ) ) ) { - msg_Err( p_update->p_libvlc, "Failed to open %s for parsing", + msg_Err( p_update->p_libvlc, "Update file %s is corrupted : missing version", UPDATE_VLC_STATUS_URL ); goto error; } - if( p_update->p_releases ) + /* first line : version number */ + if( sscanf( psz_line, "%i.%i.%i%as %as", &i_major, &i_minor, &i_revision, &psz_extra, &psz_svnrev ) ) { - FreeReleasesList( p_update ); - } - - while( xml_ReaderRead( p_xml_reader ) == 1 ) - { - switch( xml_ReaderNodeType( p_xml_reader ) ) - { - case -1: - msg_Err( p_update->p_libvlc, "Error while parsing %s", - UPDATE_VLC_STATUS_URL ); - goto error; - - case XML_READER_STARTELEM: - psz_eltname = xml_ReaderName( p_xml_reader ); - if( !psz_eltname ) - { - msg_Err( p_update->p_libvlc, "Error while parsing %s", - UPDATE_VLC_STATUS_URL ); - goto error; - } - - while( xml_ReaderNextAttr( p_xml_reader ) == VLC_SUCCESS ) - { - psz_name = xml_ReaderName( p_xml_reader ); - psz_value = xml_ReaderValue( p_xml_reader ); + p_update->release.i_major = i_major; + p_update->release.i_minor = i_minor; + p_update->release.i_revision = i_revision; - if( !psz_name || !psz_value ) - { - msg_Err( p_update->p_libvlc, "Error while parsing %s", - UPDATE_VLC_STATUS_URL ); - goto error; - } + if( psz_svnrev ) + p_update->release.psz_svnrev = psz_svnrev; + else + p_update->release.psz_svnrev = STRDUP( "" ); - if( b_os && b_arch ) - { - if( strcmp( psz_eltname, "version" ) == 0 ) - { - if( !strcmp( psz_name, "major" ) ) - tmp_release.psz_major = STRDUP( psz_value ); - else if( !strcmp( psz_name, "minor" ) ) - tmp_release.psz_minor = STRDUP( psz_value ); - else if( !strcmp( psz_name, "revision" ) ) - tmp_release.psz_revision = STRDUP( psz_value ); - else if( !strcmp( psz_name, "extra" ) ) - tmp_release.psz_extra = STRDUP( psz_value ); - else if( !strcmp( psz_name, "svn" ) ) - tmp_release.psz_svn_revision = - STRDUP( psz_value ); - else if( !strcmp( psz_name, "version" ) ) - { - if( !strcmp( psz_value, "unstable" ) ) - tmp_release.i_type = - UPDATE_RELEASE_TYPE_UNSTABLE; - else if( !strcmp( psz_value, "testing" ) ) - tmp_release.i_type = - UPDATE_RELEASE_TYPE_TESTING; - else - tmp_release.i_type = - UPDATE_RELEASE_TYPE_STABLE; - } - } - else if( !strcmp( psz_eltname, "file" ) ) - { - if( !strcmp( psz_name, "type" ) ) - { - if( !strcmp( psz_value, "info" ) ) - tmp_file.i_type = UPDATE_FILE_TYPE_INFO; - else if( !strcmp( psz_value, "source" ) ) - tmp_file.i_type = UPDATE_FILE_TYPE_SOURCE; - else if( !strcmp( psz_value, "binary" ) ) - tmp_file.i_type = UPDATE_FILE_TYPE_BINARY; - else if( !strcmp( psz_value, "plugin" ) ) - tmp_file.i_type = UPDATE_FILE_TYPE_PLUGIN; - else - tmp_file.i_type = UPDATE_FILE_TYPE_UNDEF; - } - else if( !strcmp( psz_name, "md5" ) ) - tmp_file.psz_md5 = STRDUP( psz_value ); - else if( !strcmp( psz_name, "size" ) ) - tmp_file.l_size = atol( psz_value ); - else if( !strcmp( psz_name, "url" ) ) - tmp_file.psz_url = STRDUP( psz_value ); - } - } - if( !strcmp( psz_name, "name" ) - && ( !strcmp( psz_value, UPDATE_VLC_OS ) - || !strcmp( psz_value, "*" ) ) - && !strcmp( psz_eltname, "os" ) ) - { - b_os = VLC_TRUE; - } - if( b_os && !strcmp( psz_name, "name" ) - && ( !strcmp( psz_value, UPDATE_VLC_ARCH ) - || !strcmp( psz_value, "*" ) ) - && !strcmp( psz_eltname, "arch" ) ) - { - b_arch = VLC_TRUE; - } - FREENULL( psz_name ); - FREENULL( psz_value ); - } - if( ( b_os && b_arch && strcmp( psz_eltname, "arch" ) ) ) - { - if( !strcmp( psz_eltname, "version" ) ) - { - int i; - /* look for a previous occurrence of this release */ - for( i = 0; i < p_update->i_releases; i++ ) - { - p_release = p_update->p_releases + i; - if( CompareReleases( p_release, &tmp_release ) - == UPDATE_RELEASE_STATUS_EQUAL ) - { - break; - } - } - /* if this is the first time that we see this release, - * append it to the list of releases */ - if( i == p_update->i_releases ) - { - tmp_release.i_status = - CompareReleaseToCurrent( &tmp_release ); - p_update->p_releases = - (struct update_release_t *)realloc( p_update->p_releases, - (++(p_update->i_releases))*sizeof( struct update_release_t ) ); - p_update->p_releases[ p_update->i_releases - 1 ] = - tmp_release; - p_release = - p_update->p_releases + p_update->i_releases - 1; - tmp_release.psz_major = NULL; - tmp_release.psz_minor = NULL; - tmp_release.psz_revision = NULL; - tmp_release.psz_extra = NULL; - tmp_release.psz_svn_revision = NULL; - tmp_release.i_type = UPDATE_RELEASE_TYPE_STABLE; - tmp_release.i_status = 0; - tmp_release.p_files = NULL; - tmp_release.i_files = 0; - } - else - { - FREENULL( tmp_release.psz_major ); - FREENULL( tmp_release.psz_minor ); - FREENULL( tmp_release.psz_revision ); - FREENULL( tmp_release.psz_extra ); - FREENULL( tmp_release.psz_svn_revision ); - tmp_release.i_type = UPDATE_RELEASE_TYPE_STABLE; - FREENULL( tmp_release.p_files ); - tmp_release.i_files = 0; - } - } - else if( !strcmp( psz_eltname, "file" ) ) - { - /* append file to p_release's file list */ - if( p_release == NULL ) - { - goto error; - } - p_release->p_files = - (struct update_file_t *)realloc( p_release->p_files, - (++(p_release->i_files))*sizeof( struct update_file_t ) ); - p_release->p_files[ p_release->i_files - 1 ] = tmp_file; - tmp_file.i_type = UPDATE_FILE_TYPE_UNDEF; - tmp_file.psz_md5 = NULL; - tmp_file.l_size = 0; - tmp_file.psz_url = NULL; - tmp_file.psz_description = NULL; - } - } - FREENULL( psz_eltname ); - break; + if( psz_extra ) + p_update->release.psz_extra = psz_extra; + else + p_update->release.psz_extra = STRDUP( "" ); + } + else + { + msg_Err( p_update->p_libvlc, "Update version false formated" ); + free( psz_line ); + goto error; + } - case XML_READER_ENDELEM: - psz_eltname = xml_ReaderName( p_xml_reader ); - if( !psz_eltname ) - { - msg_Err( p_update->p_libvlc, "Error while parsing %s", - UPDATE_VLC_STATUS_URL ); - goto error; - } + /* Second line : URL */ + if( !( psz_line = stream_ReadLine( p_stream ) ) ) + { + msg_Err( p_update->p_libvlc, "Update file %s is corrupted : URL missing", + UPDATE_VLC_STATUS_URL ); + goto error; + } + p_update->release.psz_url = psz_line; - if( !strcmp( psz_eltname, "os" ) ) - b_os = VLC_FALSE; - else if( !strcmp( psz_eltname, "arch" ) ) - b_arch = VLC_FALSE; - FREENULL( psz_eltname ); - break; - case XML_READER_TEXT: - psz_eltvalue = xml_ReaderValue( p_xml_reader ); - if( p_release && p_release->i_files ) - p_release->p_files[ p_release->i_files - 1 ] - .psz_description = STRDUP( psz_eltvalue ); - FREENULL( psz_eltvalue ); - break; - } + /* Third line : description */ + if( !( psz_line = stream_ReadLine( p_stream ) ) ) + { + msg_Err( p_update->p_libvlc, "Update file %s is corrupted : description missing", + UPDATE_VLC_STATUS_URL ); + goto error; } - - p_update->b_releases = VLC_TRUE; + p_update->release.psz_desc = psz_line; error: vlc_mutex_unlock( &p_update->lock ); - free( psz_eltname ); - free( psz_eltvalue ); - free( psz_name ); - free( psz_value ); - - free( tmp_release.psz_major ); - free( tmp_release.psz_minor ); - free( tmp_release.psz_revision ); - free( tmp_release.psz_extra ); - free( tmp_release.psz_svn_revision ); - - free( tmp_file.psz_md5 ); - free( tmp_file.psz_url ); - free( tmp_file.psz_description ); - - if( p_xml_reader && p_xml ) - xml_ReaderDelete( p_xml, p_xml_reader ); if( p_stream ) stream_Delete( p_stream ); - if( p_xml ) - xml_Delete( p_xml ); } /** * Check for updates * * \param p_update pointer to update struct - * \param b_force set to VLC_TRUE if you want to force the update * \returns nothing */ -void update_Check( update_t *p_update, vlc_bool_t b_force ) +void update_Check( update_t *p_update ) { assert( p_update ); - GetMirrorsList( p_update, b_force ); - GetFilesList( p_update, b_force ); -} - -/** - * Compare two release numbers - * The comparision algorith basically performs an alphabetical order (strcmp) - * comparision of each of the version number elements until it finds two - * different ones. This is the tricky function. - * - * \param p1 first release - * \param p2 second release - * \return like strcmp - */ -static int CompareReleases( const struct update_release_t *p1, - const struct update_release_t *p2 ) -{ - int d; - if( ( d = strcmp( p1->psz_major, p2->psz_major ) ) ) ; - else if( ( d = strcmp( p1->psz_minor, p2->psz_minor ) ) ) ; - else if( ( d = strcmp( p1->psz_revision, p2->psz_revision ) ) ) ; - else - { - d = strcmp( p1->psz_extra, p2->psz_extra ); - if( d<0 ) - { - /* FIXME: - * not num < NULL < num - * -test and -svn releases are thus always considered older than - * -'' or -0 releases, which is the best i could come up with */ - char *psz_end1; - char *psz_end2; - strtol( p1->psz_extra, &psz_end1, 10 ); - strtol( p2->psz_extra, &psz_end2, 10 ); - if( psz_end2 == p2->psz_extra - && ( psz_end1 != p1->psz_extra || *p1->psz_extra == '\0' ) ) - d = 1; - } - } - if( d < 0 ) - return UPDATE_RELEASE_STATUS_OLDER; - else if( d == 0 ) - return UPDATE_RELEASE_STATUS_EQUAL; - else - return UPDATE_RELEASE_STATUS_NEWER; -} - -/** - * Compare a given release's version number to the current VLC's one - * - * \param p a release - * \return >0 if newer, 0 if equal and <0 if older - */ -static int CompareReleaseToCurrent( const struct update_release_t *p ) -{ - struct update_release_t c; - int r; - - memset( &c, 0, sizeof(struct update_release_t) ); - c.psz_major = STRDUP( PACKAGE_VERSION_MAJOR ); - c.psz_minor = STRDUP( PACKAGE_VERSION_MINOR ); - c.psz_revision = STRDUP( PACKAGE_VERSION_REVISION ); - c.psz_extra = STRDUP( PACKAGE_VERSION_EXTRA ); - r = CompareReleases( p, &c ); - free( c.psz_major ); - free( c.psz_minor ); - free( c.psz_revision ); - free( c.psz_extra ); - return r; -} - -/***************************************************************************** - * Updatei_iterator_t functions - *****************************************************************************/ - -/** - * Create a new update iterator structure. This structure can then be used to - * describe a position and move through the update and mirror trees/lists. - * This will use an existing update struct or create a new one if none is - * found - * - * \param p_u the calling update_t - * \return a pointer to an update iterator - */ -update_iterator_t *update_iterator_New( update_t *p_u ) -{ - update_iterator_t *p_uit = NULL; - - assert( p_u ); - - p_uit = (update_iterator_t *)malloc( sizeof( update_iterator_t ) ); - if( p_uit == NULL ) return NULL; - - p_uit->p_u = p_u; - - p_uit->i_m = -1; - p_uit->i_r = -1; - p_uit->i_f = -1; - - p_uit->i_t = UPDATE_FILE_TYPE_ALL; - p_uit->i_rs = UPDATE_RELEASE_STATUS_ALL; - p_uit->i_rt = UPDATE_RELEASE_TYPE_STABLE; - - p_uit->file.i_type = UPDATE_FILE_TYPE_NONE; - p_uit->file.psz_md5 = NULL; - p_uit->file.psz_url = NULL; - p_uit->file.l_size = 0; - p_uit->file.psz_description = NULL; - - p_uit->release.psz_version = NULL; - p_uit->release.psz_svn_revision = NULL; - p_uit->release.i_type = UPDATE_RELEASE_TYPE_UNSTABLE; - p_uit->release.i_status = UPDATE_RELEASE_STATUS_NONE; - - p_uit->mirror.psz_name = NULL; - p_uit->mirror.psz_location = NULL; - p_uit->mirror.psz_type = NULL; - - return p_uit; -} - -/** - * Delete an update iterator structure (duh!) - * - * \param p_uit pointer to an update iterator - * \return nothing - */ -void update_iterator_Delete( update_iterator_t *p_uit ) -{ - assert( p_uit ); - - update_iterator_ClearData( p_uit ); - free( p_uit ); -} - -/** - * Reset an update_iterator_t structure - * - * \param p_uit pointer to an update iterator - * \return UPDATE_FAIL upon error, UPDATE_SUCCESS otherwise - */ -unsigned int update_iterator_Reset( update_iterator_t *p_uit ) -{ - assert( p_uit ); - - p_uit->i_r = -1; - p_uit->i_f = -1; - p_uit->i_m = -1; + EmptyRelease( p_update ); - update_iterator_ClearData( p_uit ); - return UPDATE_SUCCESS; + GetUpdateFile( p_update ); } /** - * Finds the next file in the update tree that matches status and type - * requirements set in the update_iterator + * Compare two integers * - * \param p_uit update iterator - * \return UPDATE_FAIL if we can't find the next file, UPDATE_SUCCESS|UPDATE_FILE if we stay in the same release, UPDATE_SUCCESS|UPDATE_RELEASE|UPDATE_FILE if we change the release index - */ -static unsigned int update_iterator_NextFile( update_iterator_t *p_uit ) -{ - int r,f=-1,old_r; - - assert( p_uit ); - old_r=p_uit->i_r; - - /* if the update iterator was already in a "no match" state, start over */ - if( p_uit->i_r == -1 ) p_uit->i_r = 0; - //if( p_uit->i_f == -1 ) p_uit->i_f = 0; - - vlc_mutex_lock( &p_uit->p_u->lock ); - - for( r = p_uit->i_r; r < p_uit->p_u->i_releases; r++ ) - { - if( !( p_uit->p_u->p_releases[r].i_status & p_uit->i_rs ) ) continue; - for( f = ( r == p_uit->i_r ? p_uit->i_f + 1 : 0 ); - f < p_uit->p_u->p_releases[r].i_files; f++ ) - { - if( p_uit->p_u->p_releases[r].p_files[f].i_type & p_uit->i_t ) - { - goto done;/* "double break" */ - } - } - } - done: - p_uit->i_r = r; - p_uit->i_f = f; - - r = p_uit->p_u->i_releases; - - if( old_r == p_uit->i_r ) - { - update_iterator_GetData( p_uit ); - vlc_mutex_unlock( &p_uit->p_u->lock ); - return UPDATE_SUCCESS|UPDATE_FILE; - } - else if( p_uit->i_r == r ) - { - p_uit->i_r = -1; - p_uit->i_f = -1; - update_iterator_GetData( p_uit ); - vlc_mutex_unlock( &p_uit->p_u->lock ); - return UPDATE_FAIL; - } - else - { - update_iterator_GetData( p_uit ); - vlc_mutex_unlock( &p_uit->p_u->lock ); - return UPDATE_SUCCESS|UPDATE_RELEASE|UPDATE_FILE; - } -} - -/** - * Finds the previous file in the update tree that matches status and type - * requirements set in the update_iterator - * - * \param p_uit update iterator - * \return UPDATE_FAIL if we can't find the previous file, UPDATE_SUCCESS|UPDATE_FILE if we stay in the same release, UPDATE_SUCCESS|UPDATE_RELEASE|UPDATE_FILE if we change the release index + * \param p1 first integer + * \param p2 second integer + * \return like strcmp */ -//TODO: test -static unsigned int update_iterator_PrevFile( update_iterator_t *p_uit ) +static int cmp( int i1, int i2 ) { - int r,f=-1,old_r; - - if( !p_uit ) return UPDATE_FAIL; - - old_r=p_uit->i_r; - - /* if the update iterator was already in a "no match" state, start over - * (begin at the end of the list) */ - if( p_uit->i_r == -1 ) p_uit->i_r = p_uit->p_u->i_releases - 1; - p_uit->i_f = p_uit->p_u->p_releases[p_uit->i_r].i_files + 1; - - vlc_mutex_lock( &p_uit->p_u->lock ); - - for( r = p_uit->i_r; r >= 0; r-- ) - { - if( !( p_uit->p_u->p_releases[r].i_status & p_uit->i_rs ) ) continue; - for( f =( r==p_uit->i_r ? p_uit->i_f - 1 : p_uit->p_u->p_releases[r].i_files ); - f >= 0; f-- ) - { - if( p_uit->p_u->p_releases[r].p_files[f].i_type & p_uit->i_t ) - { - goto done;/* "double break" */ - } - } - } - done: - p_uit->i_r = r; - p_uit->i_f = f; - - r = p_uit->p_u->i_releases; - - if( old_r == p_uit->i_r ) - { - update_iterator_GetData( p_uit ); - vlc_mutex_unlock( &p_uit->p_u->lock ); - return UPDATE_SUCCESS|UPDATE_FILE; - } - else if( p_uit->i_r == -1 ) - { - p_uit->i_r = -1; - p_uit->i_f = -1; - update_iterator_GetData( p_uit ); - vlc_mutex_unlock( &p_uit->p_u->lock ); - return UPDATE_FAIL; - } + if( i1 < i2 ) + return -1; + else if(i1 == i2) + return 0; else - { - update_iterator_GetData( p_uit ); - vlc_mutex_unlock( &p_uit->p_u->lock ); - return UPDATE_SUCCESS|UPDATE_RELEASE|UPDATE_FILE; - } -} - -/** - * Finds the next mirror in the update tree - * - * \param update iterator - * \return UPDATE_FAIL if we can't find the next mirror, UPDATE_SUCCESS|UPDATE_MIRROR otherwise - */ -static unsigned int update_iterator_NextMirror( update_iterator_t *p_uit ) -{ - if( !p_uit ) return UPDATE_FAIL; - vlc_mutex_lock( &p_uit->p_u->lock ); - p_uit->i_m++; - if( p_uit->i_m >= p_uit->p_u->i_mirrors ) p_uit->i_m = -1; - update_iterator_GetData( p_uit ); - vlc_mutex_unlock( &p_uit->p_u->lock ); - return p_uit->i_m == -1 ? UPDATE_FAIL : UPDATE_SUCCESS|UPDATE_MIRROR; -} - -/** - * Finds the previous mirror in the update tree - * - * \param update iterator - * \return UPDATE_FAIL if we can't find a previous mirror, UPDATE_SUCCESS|UPDATE_MIRROR otherwise - */ -static unsigned int update_iterator_PrevMirror( update_iterator_t *p_uit ) -{ - if( !p_uit ) return UPDATE_FAIL; - vlc_mutex_lock( &p_uit->p_u->lock ); - p_uit->i_m--; - update_iterator_GetData( p_uit ); - vlc_mutex_unlock( &p_uit->p_u->lock ); - return p_uit->i_m == -1 ? UPDATE_FAIL : UPDATE_SUCCESS|UPDATE_MIRROR; + return 1; } /** - * Change the update iterator's position in the file and mirrors tree - * If position is negative, don't change it + * Compare two release numbers * - * \param i_m position in mirrors list - * \param i_r position in releases list - * \param i_f position in release's files list - * \return UPDATE_FAIL when changing position fails or position wasn't changed, a combination of UPDATE_MIRROR, UPDATE_RELEASE and UPDATE_FILE otherwise + * \param p1 first release + * \param p2 second release + * \return UpdateReleaseStatus(Older|Equal|Newer) */ -unsigned int update_iterator_ChooseMirrorAndFile( update_iterator_t *p_uit, - int i_m, int i_r, int i_f ) +static int CompareReleases( const struct update_release_t *p1, + const struct update_release_t *p2 ) { - unsigned int i_val = 0; - - if( !p_uit ) return 0; - vlc_mutex_lock( &p_uit->p_u->lock ); - - if( i_m >= 0 ) - { - if( i_m < p_uit->p_u->i_mirrors ) - { - if( i_m != p_uit->i_m ) - i_val |= UPDATE_MIRROR; - p_uit->i_m = i_m; - } - else i_m = -1; - } - - if( i_r >= 0 ) - { - if( i_r < p_uit->p_u->i_releases ) - { - if( i_r != p_uit->i_r ) - i_val |= UPDATE_FILE; - p_uit->i_r = i_r; - } - else i_r = -1; - } - - if( i_f >= 0 ) - { - if( i_r >= 0 && i_r < p_uit->p_u->i_releases - && i_f < p_uit->p_u->p_releases[p_uit->i_r].i_files ) - { - if( i_f != p_uit->i_f ) - i_val |= UPDATE_FILE; - p_uit->i_f = i_f; - } - else i_f = -1; - } - - update_iterator_GetData( p_uit ); - vlc_mutex_unlock( &p_uit->p_u->lock ); - - if( ( i_m < 0 || p_uit->i_m >= 0 ) - && ( i_r < 0 || p_uit->i_r >= 0 ) - && ( i_f < 0 || p_uit->i_f >= 0 ) ) - { - /* Everything worked */ - return UPDATE_SUCCESS|i_val; - } + int d; + if( ( d = cmp( p1->i_major, p2->i_major ) ) ) ; + else if( ( d = cmp( p1->i_minor, p2->i_minor ) ) ) ; + else if( ( d = cmp( p1->i_revision, p2->i_revision ) ) ) ; else { - /* Something failed */ - return UPDATE_FAIL; - } -} - -/** - * Fills the iterator data (file, release and mirror structs) - * The update struct should be locked before calling this function. - * - * \param p_uit update iterator - * \return nothing - */ -static void update_iterator_GetData( update_iterator_t *p_uit ) -{ - struct update_release_t *p_r = NULL; - struct update_file_t *p_f = NULL; - struct update_mirror_t *p_m = NULL; - - update_iterator_ClearData( p_uit ); - - if( p_uit->i_m >= 0 ) - { - p_m = p_uit->p_u->p_mirrors + p_uit->i_m; - p_uit->mirror.psz_name = STRDUP( p_m->psz_name ); - p_uit->mirror.psz_location = STRDUP( p_m->psz_location ); - p_uit->mirror.psz_type = STRDUP( p_m->psz_type ); - } - - if( p_uit->i_r >= 0 ) - { - p_r = p_uit->p_u->p_releases + p_uit->i_r; - asprintf( &p_uit->release.psz_version, "%s.%s.%s-%s", - p_r->psz_major, - p_r->psz_minor, - p_r->psz_revision, - p_r->psz_extra ); - p_uit->release.psz_svn_revision = STRDUP( p_r->psz_svn_revision ); - p_uit->release.i_type = p_r->i_type; - p_uit->release.i_status = p_r->i_status; - if( p_uit->i_f >= 0 ) + if( p1->psz_extra[0] == '-' ) { - p_f = p_r->p_files + p_uit->i_f; - p_uit->file.i_type = p_f->i_type; - p_uit->file.psz_md5 = STRDUP( p_f->psz_md5 ); - p_uit->file.l_size = p_f->l_size; - p_uit->file.psz_description = STRDUP( p_f->psz_description); - if( p_f->psz_url[0] == '/' ) - { - if( p_m ) - { - asprintf( &p_uit->file.psz_url, "%s%s", - p_m->psz_base_url, p_f->psz_url ); - } - } + if( p2->psz_extra[0] == '-' ) + d = strcmp( p1->psz_extra, p2->psz_extra ); else - { - p_uit->file.psz_url = STRDUP( p_f->psz_url ); - } - } - } -} - -/** - * Clears the iterator data (file, release and mirror structs) - * - * \param p_uit update iterator - * \return nothing - */ -static void update_iterator_ClearData( update_iterator_t *p_uit ) -{ - p_uit->file.i_type = UPDATE_FILE_TYPE_NONE; - FREENULL( p_uit->file.psz_md5 ); - p_uit->file.l_size = 0; - FREENULL( p_uit->file.psz_description ); - FREENULL( p_uit->file.psz_url ); - FREENULL( p_uit->release.psz_version ); - FREENULL( p_uit->release.psz_svn_revision ); - p_uit->release.i_type = UPDATE_RELEASE_TYPE_UNSTABLE; - p_uit->release.i_status = UPDATE_RELEASE_STATUS_NONE; - FREENULL( p_uit->mirror.psz_name ); - FREENULL( p_uit->mirror.psz_location ); - FREENULL( p_uit->mirror.psz_type ); -} - -/** - * Perform an action on the update iterator - * Only the first matching action is performed. - * - * \param p_uit update iterator - * \param i_action update action bitmask. can be a combination of UPDATE_NEXT, UPDATE_PREV, UPDATE_MIRROR, UPDATE_RELEASE, UPDATE_FILE, UPDATE_RESET - * \return UPDATE_FAIL if action fails, UPDATE_SUCCESS|(combination of UPDATE_MIRROR, UPDATE_RELEASE and UPDATE_FILE if these changed) otherwise - */ -unsigned int update_iterator_Action( update_iterator_t *p_uit, int i_action ) -{ - if( i_action & UPDATE_RESET ) - { - return update_iterator_Reset( p_uit ); - } - else - if( i_action & UPDATE_MIRROR ) - { - if( i_action & UPDATE_PREV ) - { - return update_iterator_PrevMirror( p_uit ); - } - else - { - return update_iterator_NextMirror( p_uit ); - } - } - /*else if( i_action & UPDATE_RELEASE ) - { - if( i_action & UPDATE_PREV ) - { - return update_iterator_PrevRelease( p_uit ); - } - else - { - return update_iterator_NextRelease( p_uit ); - } - }*/ - else if( i_action & UPDATE_FILE ) - { - if( i_action & UPDATE_PREV ) - { - return update_iterator_PrevFile( p_uit ); + d = 1; } else { - return update_iterator_NextFile( p_uit ); + if( p2->psz_extra[0] == '-' ) + d = -1; + else + d = strcmp(p1->psz_extra, p2->psz_extra ); } + if( d == 0 ) + d = strcmp( p1->psz_svnrev, p2->psz_svnrev ); } - else - { - return UPDATE_SUCCESS; - } -} - -/** - * Object to launch download thread in a different object - */ -typedef struct { - VLC_COMMON_MEMBERS - char *psz_dest; //< Download destination - struct update_file_t src; //< Download source - char *psz_status; //< Download status displayed in progress dialog -} download_thread_t; -void update_download_for_real( download_thread_t *p_this ); - -/** - * Download the file selected by the update iterator. This function will - * launch the download in a new thread (downloads can be long) - * - * \param p_uit update iterator - * \param psz_dest destination file path - * \return nothing - */ -void update_download( update_iterator_t *p_uit, const char *psz_dest ) -{ - download_thread_t *p_dt = - vlc_object_create( p_uit->p_u->p_libvlc, sizeof( download_thread_t ) ); - - p_dt->psz_dest = strdup( psz_dest ); - p_dt->src.i_type = p_uit->file.i_type; - p_dt->src.l_size = p_uit->file.l_size; - p_dt->src.psz_md5 = STRDUP( p_uit->file.psz_md5 ); - p_dt->src.psz_url = STRDUP( p_uit->file.psz_url ); - p_dt->src.psz_description = STRDUP( p_uit->file.psz_description ); - asprintf( &p_dt->psz_status, "%s - %s (%s)\nSource: %s\nDestination: %s", - p_uit->file.psz_description, p_uit->release.psz_version, - p_uit->release.psz_svn_revision, p_uit->file.psz_url, - psz_dest); - - vlc_thread_create( p_dt, "download thread", update_download_for_real, - VLC_THREAD_PRIORITY_LOW, VLC_FALSE ); -} - -/** - * Convert a long int size in bytes to a string - * - * \param l_size the size in bytes - * \return the size as a string - */ -static char *size_str( long int l_size ) -{ - char *psz_tmp; - if( l_size>> 30 ) - asprintf( &psz_tmp, "%.1f GB", (float)l_size/(1<<30) ); - if( l_size >> 20 ) - asprintf( &psz_tmp, "%.1f MB", (float)l_size/(1<<20) ); - else if( l_size >> 10 ) - asprintf( &psz_tmp, "%.1f kB", (float)l_size/(1<<10) ); + if( d < 0 ) + return UpdateReleaseStatusOlder; + else if( d == 0 ) + return UpdateReleaseStatusEqual; else - asprintf( &psz_tmp, "%ld B", l_size ); - return psz_tmp; + return UpdateReleaseStatusNewer; } /** - * The true download function. + * Compare a given release's version number to the current VLC's one * - * \param p_this the download_thread_t object - * \return nothing + * \param p a release + * \return UpdateReleaseStatus(Older|Equal|Newer) */ -void update_download_for_real( download_thread_t *p_this ) +int update_CompareReleaseToCurrent( update_t *p_update ) { - char *psz_dest = p_this->psz_dest; - char *psz_src = p_this->src.psz_url; - stream_t *p_stream; - libvlc_int_t *p_libvlc = p_this->p_libvlc; - - FILE *p_file = NULL; - void *p_buffer; - - char *psz_status; - - int i_progress; - long int l_size, l_done = 0; - - vlc_thread_ready( p_this ); - - asprintf( &psz_status, "%s\nDownloading... 0.0/? %.1f%% done", - p_this->psz_status, 0.0 ); - i_progress = intf_UserProgress( p_libvlc, "Downloading...", - psz_status, 0.0, 0 ); + assert( p_update ); - p_stream = stream_UrlNew( p_libvlc, psz_src ); - if( !p_stream ) - { - msg_Err( p_libvlc, "Failed to open %s for reading", psz_src ); - intf_UserFatal( p_libvlc, VLC_TRUE, "Download Error", - "VLC failed to open %s for reading.", psz_src ); - intf_UserHide( p_libvlc, i_progress ); - } - else - { - l_size = stream_Size(p_stream); - if( l_size != p_this->src.l_size ) - { - stream_Delete( p_stream ); - free( psz_status ); - msg_Err( p_this, "%s hasn't a correct size (%li instead of %li)." - " Cancelling download.", - p_this->src.psz_description, - l_size, - p_this->src.l_size ); - goto end; - } - p_file = utf8_fopen( psz_dest, "w" ); - if( !p_file ) - { - msg_Err( p_libvlc, "Failed to open %s for writing", psz_dest ); - intf_UserFatal( p_libvlc, VLC_TRUE, "Download Error", - "VLC failed to open %s for writing.", psz_dest ); - intf_UserHide( p_libvlc, i_progress ); - } + struct update_release_t c; + int i_major = 0; + int i_minor = 0; + int i_revision = 0; + char *psz_extra; + int i_result = UpdateReleaseStatusOlder; + + /* get the current version number */ + if( sscanf( PACKAGE_VERSION, "%i.%i.%i%as", &i_major, &i_minor, &i_revision, &psz_extra ) ) + { + c.i_major = i_major; + c.i_minor = i_minor; + c.i_revision = i_revision; + if( psz_extra ) + c.psz_extra = psz_extra; else - { - int i_read; - char *psz_s1; char *psz_s2; - struct md5_s md5_s; + c.psz_extra = STRDUP( "" ); + c.psz_svnrev = STRDUP( VLC_Changeset() ); - p_buffer = (void *)malloc( 1<<10 ); - if( p_buffer ) - { - if( p_this->src.i_type & ( UPDATE_FILE_TYPE_SOURCE | UPDATE_FILE_TYPE_BINARY | UPDATE_FILE_TYPE_PLUGIN ) ) - InitMD5( &md5_s ); - while( ( i_read = stream_Read( p_stream, p_buffer, 1<<10 ) ) ) - { - float f_progress; + i_result = CompareReleases( &p_update->release, &c ); - fwrite( p_buffer, i_read, 1, p_file ); - if( p_this->src.i_type & ( UPDATE_FILE_TYPE_SOURCE | UPDATE_FILE_TYPE_BINARY | UPDATE_FILE_TYPE_PLUGIN ) ) - AddMD5( &md5_s, p_buffer, (size_t) i_read ); - - l_done += i_read; - free( psz_status ); - f_progress = 100.0*(float)l_done/(float)l_size; - psz_s1 = size_str( l_done ); - psz_s2 = size_str( l_size ); - asprintf( &psz_status, "%s\nDownloading... %s/%s (%.1f%%) done", - p_this->psz_status, psz_s1, psz_s2, f_progress ); - free( psz_s1 ); - free( psz_s2 ); - - intf_ProgressUpdate( p_libvlc, i_progress, - psz_status, f_progress, 0 ); - } - free( p_buffer ); - } - fclose( p_file ); - stream_Delete( p_stream ); - - if( l_done == p_this->src.l_size && - p_this->src.i_type & ( UPDATE_FILE_TYPE_SOURCE | - UPDATE_FILE_TYPE_BINARY | UPDATE_FILE_TYPE_PLUGIN ) ) - { - EndMD5( &md5_s ); - char *psz_md5 = psz_md5_hash( &md5_s ); - if( !p_this->src.psz_md5 || !psz_md5 || - strncmp( psz_md5, p_this->src.psz_md5, 32 ) ) - { - msg_Err( p_this, _("%s has an incorrect checksum, download failed or mirror is compromised.\n Please run an antivirus on %s, and report if that file is trojaned.\n If not, please try later."), - p_this->src.psz_description, psz_dest ); - } - free( psz_md5 ); - } - - free( psz_status ); - psz_s2 = size_str( l_size ); - asprintf( &psz_status, "%s\nDone %s (100.00%%)", - p_this->psz_status, psz_s2 ); - free( psz_s2 ); - intf_ProgressUpdate( p_libvlc, i_progress, psz_status, 100.0, 0 ); - free( psz_status ); - } + free( c.psz_extra ); + free( c.psz_svnrev ); } - -end: - free( p_this->psz_dest ); - free( p_this->src.psz_url ); - free( p_this->src.psz_description ); - free( p_this->src.psz_md5 ); - free( p_this->psz_status ); - - vlc_object_destroy( p_this ); + return i_result; } -- 2.39.2