Disable update checking per default, re-enable with --enable-update-check
authorRafaël Carré <funman@videolan.org>
Fri, 14 Dec 2007 17:53:27 +0000 (17:53 +0000)
committerRafaël Carré <funman@videolan.org>
Fri, 14 Dec 2007 17:53:27 +0000 (17:53 +0000)
Add OpenPGP code, still unused as there is no download of binaries at the moment

We will need to define (and write) the files (and their location) we will use in the update system:

    * We will use a file per arch, which will be signed
    * ALL VideoLAN gpg public keys will be stored on http://download.videolan.org/pub/keys/XXXXXXXXXXXXXXXX.asc where XXXXXXXXXXXXXXXX is the long id of the key
    * Every downloadable file will be signed with gpg --sign --detach --armor

18 files changed:
configure.ac
doc/release-howto.txt
include/vlc_update.h
modules/control/rc.c
modules/gui/macosx/intf.h
modules/gui/macosx/intf.m
modules/gui/macosx/update.h
modules/gui/macosx/update.m
modules/gui/qt4/dialogs/help.cpp
modules/gui/qt4/dialogs/help.hpp
modules/gui/qt4/dialogs_provider.cpp
modules/gui/qt4/dialogs_provider.hpp
modules/gui/qt4/menus.cpp
modules/gui/wxwidgets/dialogs.cpp
modules/gui/wxwidgets/dialogs/updatevlc.cpp
modules/gui/wxwidgets/dialogs/updatevlc.hpp
modules/gui/wxwidgets/interface.cpp
src/misc/update.c

index c514ea8..5bdd942 100644 (file)
@@ -5589,6 +5589,20 @@ then
 fi
 AM_CONDITIONAL([HAVE_LIBGCRYPT], [test "${have_libgcrypt}" = "yes"])
 
+dnl
+dnl update checking system
+dnl
+AC_ARG_ENABLE(update-check,
+  [  --enable-update-check   update checking system (default disabled)])
+if test "${enable_update_check}" = "yes"
+then
+  if test "${have_libgcrypt}" != "yes"
+  then
+    AC_MSG_ERROR([libgcrypt is required for update checking system])
+  fi
+  VLC_ADD_LIBS([libvlc], [-lgcrypt])
+  AC_DEFINE([UPDATE_CHECK], [1], [Define if you want to use the VLC update mechanism])
+fi
 
 dnl
 dnl  Endianness check, AC_C_BIGENDIAN doesn't work if we are cross-compiling
index e683576..ce8bea4 100644 (file)
@@ -15,6 +15,7 @@
      · read all the commits and add important things to the NEWS file
      · update the milestones info on https://trac.videolan.org/vlc
    - Add a note about the matching contrib package in INSTALL.win32
+   - Make sure that the gpg key embedded in include/vlc_update.h is the last one
 
  * Commit
 
 
  * BeOS Packages
     Information on building: http://developers.videolan.org/vlc/beos-compile.html
+    Configure with --enable-update-check
     Build in the "buildbeos" chroot on altair.
     # add the .zip files to /opt/ftp/pub/videolan/testing/vlc-X.X.X/beos/
+   generate md5 hashes and gpg signature of these files
 
  * Win32 Packages
-    make the packages using the nightly builds configure/options/...
+    make the packages using the nightly builds configure/options/... , don't forget --enable-update-check
     don't forget to test the installer and uninstaller (the first 0.8.4 uninstaller was broken ...
     kind of suxxs)
     add the .zip and .exe files to /opt/ftp/pub/videolan/testing/vlc-X.X.X/win32/
    generate md5 hashes and gpg signature of these files
 
  * OS X packages
-    At the moment, only FK can do them (so they can be compatible with OS X 10.2)
-    Later: on the G5
+   configure with --enable-update-check
    generate md5 hashes and gpg signature of these files
 
  * Commit changes ... it never works the first time
index f36e405..cfac788 100644 (file)
@@ -1,10 +1,11 @@
 /*****************************************************************************
  * vlc_update.h: VLC update and plugins download
  *****************************************************************************
- * Copyright (C) 2005 the VideoLAN team
+ * Copyright © 2005-2007 the VideoLAN team
  * $Id$
  *
  * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
+ *          Rafaël Carré <funman@videolanorg>
  *
  * 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
   #error You are not libvlc or one of its plugins. You cannot include this file
 #endif
 
+#ifdef UPDATE_CHECK
+
 #ifndef _VLC_UPDATE_H
 #define _VLC_UPDATE_H
 
 #include <vlc/vlc.h>
 
+#include <vlc_stream.h>     /* key & signature downloading */
+#include <vlc_strings.h>    /* b64 decoding */
+#include <vlc_charset.h>    /* utf8_fopen() */
+#include <gcrypt.h>         /* cryptography and digest algorithms */
+
 /**
  * \defgroup update Update
  *
  * @{
  */
 
+enum    /* Public key algorithms */
+{
+    /* we will only use DSA public keys */
+    PUBLIC_KEY_ALGO_DSA = 0x11
+};
+
+enum    /* Digest algorithms */
+{
+    /* and DSA use SHA-1 digest */
+    DIGEST_ALGO_SHA1    = 0x02
+};
+
+enum    /* Packet types */
+{
+    SIGNATURE_PACKET    = 0x02,
+    PUBLIC_KEY_PACKET   = 0x06,
+    USER_ID_PACKET      = 0x0d
+};
+
+enum    /* Signature types */
+{
+    BINARY_SIGNATURE        = 0x00,
+    TEXT_SIGNATURE          = 0x01,
+
+    /* Public keys signatures */
+    GENERIC_KEY_SIGNATURE   = 0x10, /* No assumption of verification */
+    PERSONA_KEY_SIGNATURE   = 0x11, /* No verification has been made */
+    CASUAL_KEY_SIGNATURE    = 0x12, /* Some casual verification */
+    POSITIVE_KEY_SIGNATURE  = 0x13  /* Substantial verification */
+};
+
+
+enum    /* Signature subpacket types */
+{
+    ISSUER_SUBPACKET    = 0x10
+};
+
+
+
+struct public_key_packet_t
+{ /* a public key packet (DSA/SHA-1) is 418 bytes */
+
+    uint8_t version;      /* we use only version 4 */
+    uint8_t timestamp[4]; /* creation time of the key */
+    uint8_t algo;         /* we only use DSA */
+    /* the multi precision integers, with their 2 bytes length header */
+    uint8_t p[2+128];
+    uint8_t q[2+20];
+    uint8_t g[2+128];
+    uint8_t y[2+128];
+};
+
+/* used for public key signatures */
+struct signature_packet_v4_t
+{ /* hashed_data or unhashed_data can be empty, so the signature packet is
+   * theorically at least 54 bytes long, but always more than that. */
+
+    uint8_t version;
+    uint8_t type;
+    uint8_t public_key_algo;
+    uint8_t digest_algo;
+    uint8_t hashed_data_len[2];
+    uint8_t *hashed_data;
+    uint8_t unhashed_data_len[2];
+    uint8_t *unhashed_data;
+    uint8_t hash_verification[2];
+
+    /* The part below is made of consecutive MPIs, their number and size being
+     * public-key-algorithm dependant.
+     * But since we use DSA signatures only, we fix it. */
+    uint8_t r[2+20];
+    uint8_t s[2+20];
+};
+
+/* Used for binary document signatures (to be compatible with older software)
+ * DSA/SHA-1 is always 65 bytes */
+struct signature_packet_v3_t
+{
+    uint8_t header[2];
+    uint8_t version;            /* 3 */
+    uint8_t hashed_data_len;    /* MUST be 5 */
+    uint8_t type;
+    uint8_t timestamp[4];       /* 4 bytes scalar number */
+    uint8_t issuer_longid[8];  /* The key which signed the document */
+    uint8_t public_key_algo;    /* we only know about DSA */
+    uint8_t digest_algo;        /* and his little sister SHA-1 */
+    uint8_t hash_verification[2];/* the 2 1st bytes of the SHA-1 hash */
+
+    /* The part below is made of consecutive MPIs, their number and size being
+     * public-key-algorithm dependant.
+     * But since we use DSA signatures only, we fix it. */
+    uint8_t r[2+20];
+    uint8_t s[2+20];
+};
+
+typedef struct public_key_packet_t public_key_packet_t;
+typedef struct signature_packet_v4_t signature_packet_v4_t;
+typedef struct signature_packet_v3_t signature_packet_v3_t;
+
+struct public_key_t
+{
+    uint8_t longid[8];       /* Long id */
+    uint8_t *psz_username;    /* USER ID */
+
+    public_key_packet_t key;       /* Public key packet */
+
+    signature_packet_v4_t sig;     /* Signature packet, by the embedded key */
+};
+
+typedef struct public_key_t public_key_t;
+
+/* We trust this public key, and by extension, also keys signed by it. */
+
+//#define OLD 1 //Define OLD to use Videolan Key 2006, to test public key download
+
+static uint8_t videolan_public_key_longid[8] = {
+#ifdef OLD
+  0xC3, 0x67, 0xD8, 0xB9, 0x81, 0xCA, 0xCA, 0x84
+#else
+  0x90, 0x28, 0x17, 0xE4, 0xAA, 0x5F, 0x4D, 0xE6 
+#endif
+};
+
+static uint8_t videolan_public_key[] = {
+#ifdef OLD
+"-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
+"Version: GnuPG v2.0.4 (FreeBSD)\n"
+"\n"
+"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\n"
+"=tVe2\n"
+"-----END PGP PUBLIC KEY BLOCK-----\n"
+#else
+"-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
+"Version: GnuPG v2.0.4 (FreeBSD)\n"
+"\n"
+"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\n"
+"=qrc1\n"
+"-----END PGP PUBLIC KEY BLOCK-----\n"
+#endif
+};
+
 enum
 {
     UpdateReleaseStatusOlder,
@@ -67,7 +277,6 @@ struct update_t
     struct update_release_t release;    ///< Release (version)
 };
 
-
 #define update_New( a ) __update_New( VLC_OBJECT( a ) )
 
 VLC_EXPORT( update_t *, __update_New, ( vlc_object_t * ) );
@@ -80,3 +289,5 @@ VLC_EXPORT( int, update_CompareReleaseToCurrent, ( update_t * ) );
  */
 
 #endif
+
+#endif
index 3f9133d..94c4858 100644 (file)
@@ -96,7 +96,9 @@ 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 * );
+#ifdef UPDATE_CHECK
 static void checkUpdates( intf_thread_t *p_intf );
+#endif
 
 /* Status Callbacks */
 static int TimeOffsetChanged( vlc_object_t *, char const *,
@@ -750,10 +752,12 @@ static void Run( intf_thread_t *p_intf )
 
             Help( p_intf, b_longhelp );
         }
+#ifdef UPDATE_CHECK
         else if( !strcmp( psz_cmd, "check-updates" ) )
         {
             checkUpdates( p_intf );
         }
+#endif
         else if( !strcmp( psz_cmd, "key" ) || !strcmp( psz_cmd, "hotkey" ) )
         {
             var_SetInteger( p_intf->p_libvlc, "key-pressed",
@@ -922,9 +926,11 @@ static void Help( intf_thread_t *p_intf, vlc_bool_t b_longhelp)
         msg_rc(_("| @name mosaic-cols #. . . . . . . . . . .number of cols"));
         msg_rc(_("| @name mosaic-order id(,id)* . . . . order of pictures "));
         msg_rc(_("| @name mosaic-keep-aspect-ratio {0,1} . . .aspect ratio"));
+#ifdef UPDATE_CHECK
         msg_rc(  "| ");
         msg_rc(_("| check-updates [newer] [equal] [older]\n"
                  "|               [undef] [info] [source] [binary] [plugin]"));
+#endif
         msg_rc(  "| ");
     }
     msg_rc(_("| help . . . . . . . . . . . . . . . this help message"));
@@ -1634,7 +1640,7 @@ static int VideoConfig( vlc_object_t *p_this, char const *psz_cmd,
     intf_thread_t *p_intf = (intf_thread_t*)p_this;
     input_thread_t *p_input = NULL;
     vout_thread_t * p_vout;
-    const char * psz_variable;
+    const char * psz_variable = NULL;
     int i_error;
 
     p_input = vlc_object_find( p_this, VLC_OBJECT_INPUT, FIND_ANYWHERE );
@@ -2105,6 +2111,7 @@ static input_item_t *parse_MRL( intf_thread_t *p_intf, char *psz_mrl )
 /*****************************************************************************
  * checkUpdates : check for updates
  ****************************************************************************/
+#ifdef UPDATE_CHECK
 static void checkUpdates( intf_thread_t *p_intf )
 {
     update_t *p_u = update_New( p_intf );
@@ -2122,3 +2129,4 @@ static void checkUpdates( intf_thread_t *p_intf )
         msg_rc( "\n+----Last version" );
     update_Delete( p_u );
 }
+#endif
index b28b4f2..7e75880 100644 (file)
@@ -101,7 +101,9 @@ struct intf_sys_t
     id o_embedded_list;         /* VLCEmbeddedList*/
     id o_interaction_list;      /* VLCInteractionList*/
     id o_sfilters;              /* VLCsFilters    */
+#ifdef UPDATE_CHECK
     id o_update;                /* VLCUpdate      */
+#endif
     id o_eyetv;                 /* VLCEyeTVController */
     BOOL nib_main_loaded;       /* main nibfile */
     BOOL nib_open_loaded;       /* open nibfile */
index 2d11e15..1e17a48 100644 (file)
@@ -393,7 +393,9 @@ static VLCMain *_o_sharedMainInstance = nil;
     o_embedded_list = [[VLCEmbeddedList alloc] init];
     o_interaction_list = [[VLCInteractionList alloc] init];
     o_sfilters = nil;
+#ifdef UPDATE_CHECK
     //FIXME o_update = [[VLCUpdate alloc] init];
+#endif
 
     i_lastShownVolume = -1;
 
@@ -785,6 +787,7 @@ static VLCMain *_o_sharedMainInstance = nil;
 
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
 {
+#ifdef UPDATE_CHECK
     /* Check for update silently on startup */
     if ( !nib_update_loaded )
         nib_update_loaded = [NSBundle loadNibNamed:@"Update" owner:self];
@@ -792,7 +795,8 @@ static VLCMain *_o_sharedMainInstance = nil;
     // FIXME
     //if([o_update shouldCheckForUpdate])
     //    [NSThread detachNewThreadSelector:@selector(checkForUpdate) toTarget:o_update withObject:NULL];
+#endif
+
     /* Handle sleep notification */
     [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self selector:@selector(computerWillSleep:)
            name:NSWorkspaceWillSleepNotification object:nil];
@@ -1909,6 +1913,7 @@ static VLCMain *_o_sharedMainInstance = nil;
     [o_prefs showPrefs];
 }
 
+#ifdef UPDATE_CHECK
 - (IBAction)checkForUpdate:(id)sender
 {/* FIXME
     if( !nib_update_loaded )
@@ -1916,6 +1921,7 @@ static VLCMain *_o_sharedMainInstance = nil;
 
     [o_update showUpdateWindow];
 */}
+#endif
 
 - (IBAction)viewHelp:(id)sender
 {
index a0b2585..52dc641 100644 (file)
@@ -21,6 +21,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
+#ifdef UPDATE_CHECK
 #import <Cocoa/Cocoa.h>
 #import <vlc_update.h>
 
@@ -55,3 +56,4 @@
 + (VLCUpdate *)sharedInstance;
 
 @end
+#endif
index 04fc574..bc8052f 100644 (file)
@@ -27,6 +27,7 @@
  * ../wxwidgets/dialogs/updatevlc.cpp, written by Antoine Cellerier.
  *****************************************************************************/
 
+#ifdef UPDATE_CHECK
 
 /*****************************************************************************
  * Preamble
@@ -351,3 +352,5 @@ static VLCUpdate *_o_sharedInstance = nil;
 }
 
 @end
+
+#endif
index 409dbaf..4488626 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
+#include <vlc/vlc.h>
+
 #include "dialogs/help.hpp"
 #include <vlc_about.h>
+
+#ifdef UPDATE_CHECK
 #include <vlc_update.h>
+#endif
 
 #include "dialogs_provider.hpp"
 
@@ -159,7 +164,7 @@ void AboutDialog::close()
     this->toggleVisible();
 }
 
-
+#ifdef UPDATE_CHECK
 UpdateDialog *UpdateDialog::instance = NULL;
 
 UpdateDialog::UpdateDialog( intf_thread_t *_p_intf ) : QVLCFrame( _p_intf )
@@ -217,3 +222,5 @@ void UpdateDialog::updateOrUpload()
                                  <body><center>You have the latest version of VLC.</center></body></html>" );
     }
 }
+
+#endif
index 9a8df3c..a8fdb1d 100644 (file)
@@ -24,7 +24,7 @@
 #ifndef _HELP_DIALOG_H_
 #define _HELP_DIALOG_H_
 
-#include <vlc_update.h>
+#include <vlc/vlc.h>
 
 #include "util/qvlcframe.hpp"
 
@@ -70,7 +70,7 @@ public slots:
     void close();
 };
 
-
+#ifdef UPDATE_CHECK
 class UpdateDialog : public QVLCFrame
 {
     Q_OBJECT;
@@ -92,6 +92,6 @@ private slots:
     void close();
     void updateOrUpload();
 };
-
+#endif
 
 #endif
index 9e02240..7d42561 100644 (file)
@@ -172,10 +172,12 @@ void DialogsProvider::helpDialog()
     HelpDialog::getInstance( p_intf )->toggleVisible();
 }
 
+#ifdef UPDATE_CHECK
 void DialogsProvider::updateDialog()
 {
     UpdateDialog::getInstance( p_intf )->toggleVisible();
 }
+#endif
 
 void DialogsProvider::aboutDialog()
 {
index f7d6989..2d3533b 100644 (file)
@@ -146,7 +146,9 @@ public slots:
     void messagesDialog();
     void vlmDialog();
     void helpDialog();
+#ifdef UPDATE_CHECK
     void updateDialog();
+#endif
     void aboutDialog();
     void gotoTimeDialog();
     void podcastConfigureDialog();
index b694ab1..0a171b5 100644 (file)
@@ -22,6 +22,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
+#include <vlc/vlc.h>
+
 #include <vlc_intf_strings.h>
 
 #include "main_interface.hpp"
@@ -457,7 +459,9 @@ QMenu *QVLCMenu::HelpMenu()
     QMenu *menu = new QMenu();
     addDPStaticEntry( menu, qtr( "Help..." ) , "",
         ":/pixmaps/menus_help_16px.png", SLOT( helpDialog() ), "F1" );
+#ifdef UPDATE_CHECK
     addDPStaticEntry( menu, qtr( "Update" ) , "", "", SLOT( updateDialog() ), "");
+#endif
     menu->addSeparator();
     addDPStaticEntry( menu, qtr( I_MENU_ABOUT ), "", "", SLOT( aboutDialog() ),
         "Ctrl+F1" );
index 12e9647..63f062a 100644 (file)
@@ -63,7 +63,9 @@ private:
     void Open( int i_access_method, int i_arg );
 
     /* Event handlers (these functions should _not_ be virtual) */
+#ifdef UPDATE_CHECK
     void OnUpdateVLC( wxCommandEvent& event );
+#endif
     //void OnVLM( wxCommandEvent& event );
     void OnInteraction( wxCommandEvent& event );
     void OnExit( wxCommandEvent& event );
@@ -108,7 +110,9 @@ public:
     wxFrame             *p_prefs_dialog;
     wxFrame             *p_bookmarks_dialog;
     wxFileDialog        *p_file_generic_dialog;
+#ifdef UPDATE_CHECK
     UpdateVLC           *p_updatevlc_dialog;
+#endif
     //VLMFrame            *p_vlm_dialog;
 };
 }
@@ -156,8 +160,10 @@ BEGIN_EVENT_TABLE(DialogsProvider, wxFrame)
 
     EVT_COMMAND(INTF_DIALOG_EXIT, wxEVT_DIALOG,
                 DialogsProvider::OnExitThread)
+#ifdef UPDATE_CHECK
     EVT_COMMAND(INTF_DIALOG_UPDATEVLC, wxEVT_DIALOG,
                 DialogsProvider::OnUpdateVLC)
+#endif
 #if 0
     EVT_COMMAND(INTF_DIALOG_VLM, wxEVT_DIALOG,
                 DialogsProvider::OnVLM)
@@ -549,6 +555,7 @@ void DialogsProvider::OnExitThread( wxCommandEvent& WXUNUSED(event) )
     wxTheApp->ExitMainLoop();
 }
 
+#ifdef UPDATE_CHECK
 void DialogsProvider::OnUpdateVLC( wxCommandEvent& WXUNUSED(event) )
 {
     /* Show/hide the file info window */
@@ -560,6 +567,7 @@ void DialogsProvider::OnUpdateVLC( wxCommandEvent& WXUNUSED(event) )
         p_updatevlc_dialog->Show( !p_updatevlc_dialog->IsShown() );
     }
 }
+#endif
 
 #if 0
 void DialogsProvider::OnVLM( wxCommandEvent& WXUNUSED(event) )
index b4e0f6d..88eb5e0 100644 (file)
@@ -21,6 +21,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
+#ifdef UPDATE_CHECK
+
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
@@ -120,3 +122,4 @@ void UpdateVLC::OnCheckForUpdate( wxCommandEvent& event )
     SetSizerAndFit( main_sizer );
     Layout();
 }
+#endif
index 29cf974..53cba16 100644 (file)
@@ -21,6 +21,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
+#ifdef UPDATE_CHECK
+
 #ifndef _WXVLC_UPDATEVLC_H_
 #define _WXVLC_UPDATEVLC_H_
 
@@ -54,3 +56,5 @@ namespace wxvlc
 };
 
 #endif
+
+#endif
index 58ed75c..fa73e27 100644 (file)
@@ -300,7 +300,9 @@ enum
     About_Event = wxID_ABOUT,
     OnWebLink_Event,
     OnWebHelp_Event,
+#ifdef UPDATE_CHECK
     UpdateVLC_Event,
+#endif
     //VLM_Event,
 
     Iconize_Event,
@@ -314,7 +316,9 @@ BEGIN_EVENT_TABLE(Interface, wxFrame)
     EVT_MENU(About_Event, Interface::OnAbout)
     EVT_MENU(OnWebLink_Event, Interface::OnWebLink)
     EVT_MENU(OnWebHelp_Event, Interface::OnWebHelp)
+#ifdef UPDATE_CHECK
     EVT_MENU(UpdateVLC_Event, Interface::OnShowDialog)
+#endif
     //EVT_MENU(VLM_Event, Interface::OnShowDialog)
 
     EVT_MENU(Playlist_Event, Interface::OnShowDialog)
@@ -617,8 +621,10 @@ void Interface::CreateOurMenuBar()
     help_menu->Append( OnWebHelp_Event, wxU(_("Online Help")) );
     help_menu->AppendSeparator();
     help_menu->Append( About_Event, wxU(_("About...")) );
+#ifdef UPDATE_CHECK
     help_menu->AppendSeparator();
     help_menu->Append( UpdateVLC_Event, wxU(_("Check for Updates...")) );
+#endif
 
     /* Append the freshly created menus to the menu bar... */
     wxMenuBar *menubar = new wxMenuBar();
@@ -1024,9 +1030,11 @@ void Interface::OnShowDialog( wxCommandEvent& event )
         case Bookmarks_Event:
             i_id = INTF_DIALOG_BOOKMARKS;
             break;
+#ifdef UPDATE_CHECK
         case UpdateVLC_Event:
             i_id = INTF_DIALOG_UPDATEVLC;
             break;
+#endif
 #if 0
         case VLM_Event:
             i_id = INTF_DIALOG_VLM;
index 2ba4773..14a930b 100644 (file)
  *   This file contains functions related to VLC and plugins update management
  */
 
+/*
+ * TODO:  * pgp verification of the update file
+          * binary download, and pgp verification
+ */
+
 /*****************************************************************************
  * Preamble
  *****************************************************************************/
 
 #include <vlc/vlc.h>
 
+#ifdef UPDATE_CHECK
+
 #include <ctype.h>                                              /* tolower() */
 #include <assert.h>
 
@@ -76,6 +83,658 @@ static int extracmp( char *psz_1, char *psz_2 );
 static int CompareReleases( const struct update_release_t *p1,
                             const struct update_release_t *p2 );
 
+/*****************************************************************************
+ * OpenPGP functions
+ *****************************************************************************/
+
+#define packet_type( c ) ( ( c & 0x3c ) >> 2 )      /* 0x3C = 00111100 */
+#define packet_header_len( c ) ( ( c & 0x03 ) + 1 ) /* number of bytes in a packet header */
+
+static inline int scalar_number( uint8_t *p, int header_len )
+{
+    if( header_len == 1 )
+        return( p[0] );
+    else if( header_len == 2 )
+        return( (p[0] << 8) + p[1] );
+    else if( header_len == 4 )
+        return( (p[0] << 24) + (p[1] << 16) + (p[2] << 8) + p[3] );
+    else
+        abort();
+}
+
+/* number of data bytes in a MPI */
+#define mpi_len( mpi ) ( ( scalar_number( mpi, 2 ) + 7 ) / 8 )
+
+/* 
+ * fill a public_key_packet_t structure from public key packet data
+ * verify that it is a version 4 public key packet, using DSA
+ */
+static int parse_public_key_packet( public_key_packet_t *p_key, uint8_t *p_buf,
+                                    size_t i_packet_len )
+{
+    if( i_packet_len != 418 )
+        return VLC_EGENERIC;
+
+    p_key->version   = *p_buf++;
+    if( p_key->version != 4 )
+        return VLC_EGENERIC;
+
+    /* warn when timestamp is > date ? */
+    memcpy( p_key->timestamp, p_buf, 4 ); p_buf += 4;
+
+    p_key->algo      = *p_buf++;
+    if( p_key->algo != PUBLIC_KEY_ALGO_DSA )
+        return VLC_EGENERIC;
+
+    memcpy( p_key->p, p_buf, 2+128 ); p_buf += 2+128;
+    if( mpi_len( p_key->p ) != 128 )
+        return VLC_EGENERIC;
+
+    memcpy( p_key->q, p_buf, 2+20 );  p_buf += 2+20;
+    if( mpi_len( p_key->q ) != 20 )
+        return VLC_EGENERIC;
+
+    memcpy( p_key->g, p_buf, 2+128 ); p_buf += 2+128;
+    if( mpi_len( p_key->g ) != 128 )
+        return VLC_EGENERIC;
+
+    memcpy( p_key->y, p_buf, 2+128 ); p_buf += 2+128;
+    if( mpi_len( p_key->y ) != 128 )
+        return VLC_EGENERIC;
+
+    return VLC_SUCCESS;
+}
+
+/*
+ * fill a signature_packet_v4_t from signature packet data
+ * verify that it was used with a DSA public key, using SHA-1 digest
+ */
+static int parse_signature_v4_packet( signature_packet_v4_t *p_sig,
+                                      uint8_t *p_buf, size_t i_sig_len )
+{
+    if( i_sig_len < 54 )
+        return VLC_EGENERIC;
+
+    p_sig->version = *p_buf++;
+    if( p_sig->version != 4 )
+        return VLC_EGENERIC;
+
+    p_sig->type = *p_buf++;
+    if( p_sig->type < GENERIC_KEY_SIGNATURE ||
+        p_sig->type > POSITIVE_KEY_SIGNATURE )
+        return VLC_EGENERIC;
+
+    p_sig->public_key_algo = *p_buf++;
+    if( p_sig->public_key_algo != PUBLIC_KEY_ALGO_DSA )
+        return VLC_EGENERIC;
+
+    p_sig->digest_algo = *p_buf++;
+    if( p_sig->digest_algo != DIGEST_ALGO_SHA1 )
+        return VLC_EGENERIC;
+
+    memcpy( p_sig->hashed_data_len, p_buf, 2 ); p_buf += 2;
+
+    size_t i_pos = 6;
+    size_t i_hashed_data_len = scalar_number( p_sig->hashed_data_len, 2 );
+    i_pos += i_hashed_data_len;
+    if( i_pos > i_sig_len - 48 ) /* r & s are 44 bytes in total, 
+                              * + the unhashed data length (2 bytes)
+                              * + the hash verification (2 bytes) */
+        return VLC_EGENERIC;
+
+    p_sig->hashed_data = (uint8_t*) malloc( i_hashed_data_len );
+    if( !p_sig->hashed_data )
+        return VLC_ENOMEM;
+    memcpy( p_sig->hashed_data, p_buf, i_hashed_data_len );
+    p_buf += i_hashed_data_len;
+
+    memcpy( p_sig->unhashed_data_len, p_buf, 2 ); p_buf += 2;
+
+    size_t i_unhashed_data_len = scalar_number( p_sig->unhashed_data_len, 2 );
+    i_pos += 2 + i_unhashed_data_len;
+    if( i_pos != i_sig_len - 46 )
+    {
+        free( p_sig->hashed_data );
+        return VLC_EGENERIC;
+    }
+
+    p_sig->unhashed_data = (uint8_t*) malloc( i_unhashed_data_len );
+    if( !p_sig->unhashed_data )
+    {
+        free( p_sig->hashed_data );
+        return VLC_ENOMEM;
+    }
+    memcpy( p_sig->unhashed_data, p_buf, i_unhashed_data_len );
+    p_buf += i_unhashed_data_len;
+
+    memcpy( p_sig->hash_verification, p_buf, 2 ); p_buf += 2;
+
+    memcpy( p_sig->r, p_buf, 22 ); p_buf += 22;
+    if( mpi_len( p_sig->r ) != 20 )
+    {
+        free( p_sig->hashed_data );
+        free( p_sig->unhashed_data );
+        return VLC_EGENERIC;
+    }
+
+    memcpy( p_sig->s, p_buf, 22 );
+    if( mpi_len( p_sig->s ) != 20 )
+    {
+        free( p_sig->hashed_data );
+        free( p_sig->unhashed_data );
+        return VLC_EGENERIC;
+    }
+
+    return VLC_SUCCESS;
+}
+
+/*
+ * crc_octets() was lamely copied from rfc 2440
+ * Copyright (C) The Internet Society (1998).  All Rights Reserved.
+ */
+#define CRC24_INIT 0xB704CEL
+#define CRC24_POLY 0x1864CFBL
+
+static long crc_octets( uint8_t *octets, size_t len )
+{
+    long crc = CRC24_INIT;
+    int i;
+    while (len--)
+    {
+        crc ^= (*octets++) << 16;
+        for (i = 0; i < 8; i++)
+        {
+            crc <<= 1;
+            if (crc & 0x1000000)
+                crc ^= CRC24_POLY;
+        }
+    }
+    return crc & 0xFFFFFFL;
+}
+
+/*
+ * Transform an armored document in binary format
+ * Used on public keys and signatures
+ */
+static int pgp_unarmor( char *p_ibuf, size_t i_ibuf_len,
+                        uint8_t *p_obuf, size_t i_obuf_len )
+{
+    char *p_ipos = p_ibuf;
+    uint8_t *p_opos = p_obuf;
+    int i_end = 0;
+
+    int i_header_skipped = 0;
+
+    while( !i_end && p_ipos < p_ibuf + i_ibuf_len )
+    {
+        if( *p_ipos == '\r' || *p_ipos == '\n' )
+        {
+            p_ipos++;
+            continue;
+        }
+
+        size_t i_line_len = strcspn( p_ipos, "\r\n" );
+        if( i_line_len == 0 )
+            continue;
+
+        if( !i_header_skipped )
+        {
+            if( !strncmp( p_ipos, "-----BEGIN PGP", 14 ) )
+                i_header_skipped = 1;
+
+            p_ipos += i_line_len + 1;
+            continue;
+        }
+        
+        if( !strncmp( p_ipos, "Version:", 8 ) )
+        {
+            p_ipos += i_line_len + 1;
+            continue;
+        }
+
+        if( p_ipos[i_line_len - 1] == '=' )
+        {
+            i_end = 1;
+            p_ipos[i_line_len - 1] = '\0';
+        }
+        else
+            p_ipos[i_line_len] = '\0';
+
+        p_opos += vlc_b64_decode_binary_to_buffer(  p_opos,
+                                                    p_obuf - p_opos + i_obuf_len,
+                                                    p_ipos );
+
+        p_ipos += i_line_len + 1;
+    }
+
+    /* XXX: the CRC is OPTIONAL, really require it ? */
+    if( p_ipos + 5 > p_ibuf + i_ibuf_len || *p_ipos++ != '=' )
+        return 0;
+
+    uint8_t p_crc[3];
+    if( vlc_b64_decode_binary_to_buffer( p_crc, 3, p_ipos ) != 3 )
+        return 0;
+
+    long l_crc = crc_octets( p_obuf, p_opos - p_obuf );
+    long l_crc2 = ( 0 << 24 ) + ( p_crc[0] << 16 ) + ( p_crc[1] << 8 ) + p_crc[2];
+
+    return l_crc2 == l_crc ? p_opos - p_obuf : 0;
+}
+
+/*
+ * Download the signature associated to a document or a binary file.
+ * We're given the file's url, we just append ".asc" to it and download 
+ */
+static int download_signature(  vlc_object_t *p_this,
+                                signature_packet_v3_t *p_sig, char *psz_url )
+{
+    char *psz_sig = (char*) malloc( strlen( psz_url ) + 4 + 1 ); /* ".asc" + \0 */
+    if( !psz_sig )
+        return VLC_ENOMEM;
+
+    strcpy( psz_sig, psz_url );
+    strcat( psz_sig, ".asc" );
+
+    stream_t *p_stream = stream_UrlNew( p_this, psz_sig );
+    free( psz_sig );
+
+    if( !p_stream )
+        return VLC_ENOMEM;
+
+    int64_t i_size = stream_Size( p_stream );
+    if( i_size < 65 )
+    {
+        stream_Delete( p_stream );
+        return VLC_EGENERIC;
+    }
+    else if( i_size == 65 ) /* binary format signature */
+    {
+        int i_read = stream_Read( p_stream, p_sig, (int)i_size );
+        stream_Delete( p_stream );
+        if( i_read != i_size )
+            return VLC_EGENERIC;
+        else
+            return VLC_SUCCESS;
+    }
+
+    char *p_buf = (char*)malloc( i_size );
+    if( !p_buf )
+    {
+        stream_Delete( p_stream );
+        return VLC_ENOMEM;
+    }
+    
+    int i_read = stream_Read( p_stream, p_buf, (int)i_size );
+
+    stream_Delete( p_stream );
+
+    if( i_read != i_size )
+    {
+        free( p_buf );
+        return VLC_EGENERIC;
+    }
+    
+    int i_bytes = pgp_unarmor( p_buf, i_size, (uint8_t*)p_sig, 65 );
+    free( p_buf );
+
+    if( i_bytes != 65 )
+        return VLC_EGENERIC;
+    else
+        return VLC_SUCCESS;
+}
+
+/*
+ * Verify an OpenPGP signature made on some SHA-1 hash, with some DSA public key
+ */
+static int verify_signature( vlc_object_t *p_this, uint8_t *p_r, uint8_t *p_s,
+        public_key_packet_t *p_key, uint8_t *p_hash )
+{
+    /* the data to be verified (a SHA-1 hash) */
+    const char *hash_sexp_s = "(data(flags raw)(value %m))";
+    /* the public key */
+    const char *key_sexp_s = "(public-key(dsa(p %m)(q %m)(g %m)(y %m)))";
+    /* the signature */
+    const char *sig_sexp_s = "(sig-val(dsa(r %m )(s %m )))";
+
+    size_t erroff;
+    gcry_mpi_t p, q, g, y, r, s, hash;
+    p = q = g = y = r = s = hash = NULL;
+    gcry_sexp_t key_sexp, hash_sexp, sig_sexp;
+    key_sexp = hash_sexp = sig_sexp = NULL;
+
+    if( gcry_mpi_scan( &p, GCRYMPI_FMT_USG, p_key->p + 2, 128, NULL ) ||
+        gcry_mpi_scan( &q, GCRYMPI_FMT_USG, p_key->q + 2, 20, NULL ) ||
+        gcry_mpi_scan( &g, GCRYMPI_FMT_USG, p_key->g + 2, 128, NULL ) ||
+        gcry_mpi_scan( &y, GCRYMPI_FMT_USG, p_key->y + 2, 128, NULL ) ||
+        gcry_sexp_build( &key_sexp, &erroff, key_sexp_s, p, q, g, y ) )
+        goto problem;
+
+    if( gcry_mpi_scan( &r, GCRYMPI_FMT_USG, p_r + 2, 20, NULL ) ||
+        gcry_mpi_scan( &s, GCRYMPI_FMT_USG, p_s + 2, 20, NULL ) ||
+        gcry_sexp_build( &sig_sexp, &erroff, sig_sexp_s, r, s ) )
+        goto problem;
+
+    if( gcry_mpi_scan( &hash, GCRYMPI_FMT_USG, p_hash, 20, NULL ) ||
+        gcry_sexp_build( &hash_sexp, &erroff, hash_sexp_s, hash ) )
+        goto problem;
+
+    if( gcry_pk_verify( sig_sexp, hash_sexp, key_sexp ) )
+        goto problem;
+
+    return VLC_SUCCESS;
+
+problem:
+    if( p ) gcry_mpi_release( p );
+    if( q ) gcry_mpi_release( q );
+    if( g ) gcry_mpi_release( g );
+    if( y ) gcry_mpi_release( y );
+    if( r ) gcry_mpi_release( r );
+    if( s ) gcry_mpi_release( s );
+    if( hash ) gcry_mpi_release( hash );
+    if( key_sexp ) gcry_sexp_release( key_sexp );
+    if( sig_sexp ) gcry_sexp_release( sig_sexp );
+    if( hash_sexp ) gcry_sexp_release( hash_sexp );
+    return VLC_EGENERIC;
+}
+
+/*
+ * Return the long id (8 bytes) of the public key used to generate a signature
+ */
+static uint8_t *get_issuer_from_signature_v4( signature_packet_v4_t *p_sig )
+{
+    uint8_t *p = p_sig->unhashed_data;
+    uint8_t *max_pos = p + scalar_number( p_sig->unhashed_data_len, 2 );
+
+    while( p < max_pos )
+    {
+        int i_subpacket_len = *p < 192 ? *p++ :
+                *p < 255 ? ((*p++ - 192) << 8) + *p++ + 192 :
+                ((*++p) << 24) + (*++p << 16) + (*++p << 8) + *++p;
+
+        if( p >= max_pos - 1 )
+            return NULL;
+
+        if( *p == ISSUER_SUBPACKET )
+            return p+1;
+        else
+            p += i_subpacket_len;
+    }
+    return NULL;
+}
+
+/*
+ * fill a public_key_t with public key data, including:
+ *   * public key packet
+ *   * signature packet issued by key which long id is p_sig_issuer
+ *   * user id packet
+ */
+static int parse_public_key( const uint8_t *p_key_data, size_t i_key_len, public_key_t *p_key, const uint8_t *p_sig_issuer )
+{
+    uint8_t *pos = (uint8_t*) p_key_data;
+    uint8_t *max_pos = pos + i_key_len;
+
+    int i_status = 0;
+#define PUBLIC_KEY_FOUND    0x01
+#define USER_ID_FOUND       0x02
+#define SIGNATURE_FOUND     0X04
+
+    uint8_t *p_key_unarmored = NULL;
+
+    signature_packet_v4_t sig;
+
+    p_key->psz_username = NULL;
+    p_key->sig.hashed_data = p_key->sig.unhashed_data = NULL;
+
+    if( !( *pos & 0x80 ) )
+    {   /* first byte is ASCII, unarmoring */
+        p_key_unarmored = (uint8_t*)malloc( i_key_len );
+        if( !p_key_unarmored )
+            return VLC_ENOMEM;
+        int i_len = pgp_unarmor( (char*)p_key_data, i_key_len,
+                                 p_key_unarmored, i_key_len );
+
+        if( i_len == 0 )
+            goto error;
+
+        pos = p_key_unarmored;
+        max_pos = pos + i_len;
+    }
+
+    while( pos < max_pos )
+    {
+        if( !(*pos & 0x80) || *pos & 0x40 )
+            goto error;
+
+        int i_type = packet_type( *pos );
+
+        int i_header_len = packet_header_len( *pos++ );
+        if( pos + i_header_len > max_pos )
+            goto error;
+
+        int i_packet_len = scalar_number( pos, i_header_len );
+        pos += i_header_len;
+
+        if( pos + i_packet_len > max_pos )
+            goto error;
+
+        switch( i_type )
+        {
+            uint8_t *p_issuer;
+
+            case PUBLIC_KEY_PACKET:
+                i_status |= PUBLIC_KEY_FOUND;
+                if( parse_public_key_packet( &p_key->key, pos, i_packet_len ) != VLC_SUCCESS )
+                    goto error;
+                break;
+
+            case SIGNATURE_PACKET:
+                if( !p_sig_issuer || i_status & SIGNATURE_FOUND ||
+                    parse_signature_v4_packet( &sig, pos, i_packet_len ) != VLC_SUCCESS )
+                    break;
+                p_issuer = get_issuer_from_signature_v4( &sig );
+                if( memcmp( p_issuer, p_sig_issuer, 8 ) == 0 )
+                {
+                    memcpy( &p_key->sig, &sig, sizeof( signature_packet_v4_t ) );
+                    i_status |= SIGNATURE_FOUND;
+                }
+                else
+                {
+                    free( sig.hashed_data );
+                    free( sig.unhashed_data );
+                }
+                break;
+
+            case USER_ID_PACKET:
+                if( p_key->psz_username ) /* save only the first User ID */
+                    break;
+                i_status |= USER_ID_FOUND;
+                p_key->psz_username = (uint8_t*)malloc( i_packet_len + 1);
+                if( !p_key->psz_username )
+                    goto error;
+
+                memcpy( p_key->psz_username, pos, i_packet_len );
+                p_key->psz_username[i_packet_len] = '\0';
+                break;
+            
+            default:
+                break;
+        }
+        pos += i_packet_len;
+    }
+    free( p_key_unarmored );
+
+    if( !( i_status & ( PUBLIC_KEY_FOUND + USER_ID_FOUND ) ) )
+        return VLC_EGENERIC;
+
+    if( p_sig_issuer && !( i_status & SIGNATURE_FOUND ) )
+        return VLC_EGENERIC;
+
+    return VLC_SUCCESS;
+
+error:
+    free( p_key->sig.hashed_data );
+    free( p_key->sig.unhashed_data );
+    free( p_key->psz_username );
+    free( p_key_unarmored );
+    return VLC_EGENERIC;
+}
+
+/*
+ * return a sha1 hash of a file
+ */
+static uint8_t *hash_sha1_from_file( const char *psz_file,
+                            signature_packet_v3_t *p_sig )
+{
+    FILE *f = utf8_fopen( psz_file, "r" );
+    if( !f )
+        return NULL;
+
+    uint8_t buffer[4096]; //FIXME
+
+    gcry_md_hd_t hd;
+    if( gcry_md_open( &hd, GCRY_MD_SHA1, 0 ) )
+    {
+        fclose( f );
+        return NULL;
+    } 
+
+    size_t i_read;
+    while( ( i_read = fread( buffer, 1, sizeof(buffer), f ) ) > 0 )
+        gcry_md_write( hd, buffer, i_read );
+
+    gcry_md_putc( hd, p_sig->type );
+    gcry_md_write( hd, &p_sig->timestamp, 4 );
+
+    fclose( f );
+    gcry_md_final( hd );
+
+    return( (uint8_t*) gcry_md_read( hd, GCRY_MD_SHA1) );
+}
+
+/*
+ * download a public key (the last one) from videolan server, and parse it
+ */
+static public_key_t *download_key( vlc_object_t *p_this, const uint8_t *p_longid, const uint8_t *p_signature_issuer )
+{
+    char *psz_url;
+    if( asprintf( &psz_url, "http://download.videolan.org/pub/keys/%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x.asc",
+                            p_longid[0], p_longid[1],
+                            p_longid[2], p_longid[3],
+                            p_longid[4], p_longid[5],
+                            p_longid[6], p_longid[7] ) == -1 )
+        return NULL;
+
+    stream_t *p_stream = stream_UrlNew( p_this, psz_url );
+    free( psz_url );
+    if( !p_stream )
+        return NULL;
+
+    int64_t i_size = stream_Size( p_stream );
+    if( i_size < 0 )
+    {
+        stream_Delete( p_stream );
+        return NULL;
+    }
+
+    uint8_t *p_buf = (uint8_t*)malloc( i_size );
+    if( !p_buf )
+    {
+        stream_Delete( p_stream );
+        return NULL;
+    }
+
+    int i_read = stream_Read( p_stream, p_buf, (int)i_size );
+    stream_Delete( p_stream );
+
+    if( i_read != (int)i_size )
+    {
+        free( p_buf );
+        return NULL;
+    }
+
+    public_key_t *p_pkey = (public_key_t*) malloc( sizeof( public_key_t ) );
+    if( !p_pkey )
+    {
+        free( p_buf );
+        return NULL;
+    }
+
+    int i_error = parse_public_key( p_buf, i_read, p_pkey, p_signature_issuer );
+    free( p_buf );
+
+    if( i_error != VLC_SUCCESS )
+    {
+        free( p_pkey );
+        return NULL;
+    }
+
+    return p_pkey;
+}
+
+/*
+ * Generate a SHA-1 hash on a public key, to verify a signature made on that hash
+ * Note that we need the signature to compute the hash
+ */
+static uint8_t *key_sign_hash( public_key_t *p_pkey )
+{
+    gcry_error_t error = 0;
+    gcry_md_hd_t hd;
+
+    error = gcry_md_open( &hd, GCRY_MD_SHA1, 0 );
+    if( error )
+        return NULL;
+
+    gcry_md_putc( hd, 0x99 );
+
+    gcry_md_putc( hd, (418 >> 8) & 0xff );
+    gcry_md_putc( hd, 418 & 0xff );
+
+    gcry_md_write( hd, (uint8_t*)&p_pkey->key, 418 );
+
+    gcry_md_putc( hd, 0xb4 );
+
+    int i_len = strlen((char*)p_pkey->psz_username);
+
+    gcry_md_putc( hd, (i_len << 24) & 0xff );
+    gcry_md_putc( hd, (i_len << 16) & 0xff );
+    gcry_md_putc( hd, (i_len << 8) & 0xff );
+    gcry_md_putc( hd, (i_len) & 0xff );
+
+    gcry_md_write( hd, p_pkey->psz_username, i_len );
+
+    size_t i_hashed_data_len = scalar_number( p_pkey->sig.hashed_data_len, 2 );
+
+    gcry_md_putc( hd, p_pkey->sig.version );
+    gcry_md_putc( hd, p_pkey->sig.type );
+    gcry_md_putc( hd, p_pkey->sig.public_key_algo );
+    gcry_md_putc( hd, p_pkey->sig.digest_algo );
+    gcry_md_write( hd, p_pkey->sig.hashed_data_len, 2 );
+    gcry_md_write( hd, p_pkey->sig.hashed_data, i_hashed_data_len );
+
+    gcry_md_putc( hd, 0x04 );
+    gcry_md_putc( hd, 0xff );
+
+    i_hashed_data_len += 6; /* hashed data + 6 bytes header */
+
+    gcry_md_putc( hd, (i_hashed_data_len << 24) & 0xff);
+    gcry_md_putc( hd, (i_hashed_data_len << 16) &0xff );
+    gcry_md_putc( hd, (i_hashed_data_len << 8) & 0xff );
+    gcry_md_putc( hd, (i_hashed_data_len) & 0xff );
+
+    gcry_md_final( hd );
+
+    uint8_t *p_hash = gcry_md_read( hd, GCRY_MD_SHA1);
+
+    if( p_hash[0] != p_pkey->sig.hash_verification[0] ||
+        p_hash[1] != p_pkey->sig.hash_verification[1] )
+    {
+        free( p_hash );
+        return NULL;
+    }
+
+    return p_hash;
+}
+
 
 /*****************************************************************************
  * Update_t functions
@@ -325,3 +984,5 @@ int update_CompareReleaseToCurrent( update_t *p_update )
     }
     return i_result;
 }
+
+#endif