]> git.sesse.net Git - vlc/blob - src/misc/update.c
2ba4773bc5fb87a3ae97071606cc5af94982397e
[vlc] / src / misc / update.c
1 /*****************************************************************************
2  * update.c: VLC update and plugins download
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Cellerier <dionoea -at- videolan -dot- org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either release 2 of the License, or
12  * (at your option) any later release.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /**
25  *   \file
26  *   This file contains functions related to VLC and plugins update management
27  */
28
29 /*****************************************************************************
30  * Preamble
31  *****************************************************************************/
32
33 #include <vlc/vlc.h>
34
35 #include <ctype.h>                                              /* tolower() */
36 #include <assert.h>
37
38
39 #include <vlc_update.h>
40
41 #include <vlc_block.h>
42 #include <vlc_stream.h>
43 #include <vlc_interface.h>
44 #include <vlc_charset.h>
45
46 /*****************************************************************************
47  * Misc defines
48  *****************************************************************************/
49
50 #if defined( UNDER_CE )
51 #   define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-ce"
52 #elif defined( WIN32 )
53 #   define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-win-x86"
54 #elif defined( __APPLE__ )
55 #   define UPDATE_VLC_OS "macosx"
56 #   if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
57 #       define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-ppc"
58 #   else
59 #       define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-x86"
60 #   endif
61 #elif defined( SYS_BEOS )
62 #       define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-beos-x86"
63 #else
64 #   define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status"
65 #endif
66
67 #define STRDUP( a ) ( a ? strdup( a ) : NULL )
68
69
70 /*****************************************************************************
71  * Local Prototypes
72  *****************************************************************************/
73 static void EmptyRelease( update_t *p_update );
74 static void GetUpdateFile( update_t *p_update );
75 static int extracmp( char *psz_1, char *psz_2 );
76 static int CompareReleases( const struct update_release_t *p1,
77                             const struct update_release_t *p2 );
78
79
80 /*****************************************************************************
81  * Update_t functions
82  *****************************************************************************/
83
84 /**
85  * Create a new update VLC struct
86  *
87  * \param p_this the calling vlc_object
88  * \return pointer to new update_t or NULL
89  */
90 update_t *__update_New( vlc_object_t *p_this )
91 {
92     update_t *p_update;
93
94     if( p_this == NULL ) return NULL;
95
96     p_update = (update_t *)malloc( sizeof( update_t ) );
97     if( !p_update ) return NULL;
98
99     vlc_mutex_init( p_this, &p_update->lock );
100
101     p_update->p_libvlc = p_this->p_libvlc;
102
103     p_update->release.psz_svnrev = NULL;
104     p_update->release.psz_extra = NULL;
105     p_update->release.psz_url = NULL;
106     p_update->release.psz_desc = NULL;
107
108     return p_update;
109 }
110
111 /**
112  * Delete an update_t struct
113  *
114  * \param p_update update_t* pointer
115  * \return nothing
116  */
117 void update_Delete( update_t *p_update )
118 {
119     assert( p_update );
120
121     vlc_mutex_destroy( &p_update->lock );
122
123     FREENULL( p_update->release.psz_svnrev );
124     FREENULL( p_update->release.psz_extra );
125     FREENULL( p_update->release.psz_url );
126     FREENULL( p_update->release.psz_desc );
127
128     free( p_update );
129 }
130
131 /**
132  * Empty the release struct
133  *
134  * \param p_update update_t* pointer
135  * \return nothing
136  */
137 static void EmptyRelease( update_t *p_update )
138 {
139     p_update->release.i_major = 0;
140     p_update->release.i_minor = 0;
141     p_update->release.i_revision = 0;
142
143     FREENULL( p_update->release.psz_svnrev );
144     FREENULL( p_update->release.psz_extra );
145     FREENULL( p_update->release.psz_url );
146     FREENULL( p_update->release.psz_desc );
147 }
148
149 /**
150  * Get the update file and parse it
151  * *p_update has to be unlocked when calling this function
152  *
153  * \param p_update pointer to update struct
154  * \return nothing
155  */
156 static void GetUpdateFile( update_t *p_update )
157 {
158     stream_t *p_stream = NULL;
159     int i_major = 0;
160     int i_minor = 0;
161     int i_revision = 0;
162     char *psz_extra = NULL;
163     char *psz_svnrev = NULL;
164     char *psz_line = NULL;
165
166     vlc_mutex_lock( &p_update->lock );
167
168     p_stream = stream_UrlNew( p_update->p_libvlc, UPDATE_VLC_STATUS_URL );
169     if( !p_stream )
170     {
171         msg_Err( p_update->p_libvlc, "Failed to open %s for reading",
172                  UPDATE_VLC_STATUS_URL );
173         goto error;
174     }
175
176     /* Try to read three lines */
177     if( !( psz_line = stream_ReadLine( p_stream ) ) )
178     {
179         msg_Err( p_update->p_libvlc, "Update file %s is corrupted : missing version",
180                  UPDATE_VLC_STATUS_URL );
181         goto error;
182     }
183
184     /* first line : version number */
185     if( sscanf( psz_line, "%i.%i.%i%as %as", &i_major, &i_minor, &i_revision, &psz_extra, &psz_svnrev ) )
186     {
187         p_update->release.i_major = i_major;
188         p_update->release.i_minor = i_minor;
189         p_update->release.i_revision = i_revision;
190
191         p_update->release.psz_svnrev = psz_svnrev ? psz_svnrev : STRDUP( "" );
192         p_update->release.psz_extra = psz_extra ? psz_extra : STRDUP( "" );
193     }
194     else
195     {
196         msg_Err( p_update->p_libvlc, "Update version false formated" );
197         free( psz_line );
198         goto error;
199     }
200
201     /* Second line : URL */
202     if( !( psz_line = stream_ReadLine( p_stream ) ) )
203     {
204         msg_Err( p_update->p_libvlc, "Update file %s is corrupted : URL missing",
205                  UPDATE_VLC_STATUS_URL );
206         goto error;
207     }
208     p_update->release.psz_url = psz_line;
209
210
211     /* Third line : description */
212     if( !( psz_line = stream_ReadLine( p_stream ) ) )
213     {
214         msg_Err( p_update->p_libvlc, "Update file %s is corrupted : description missing",
215                  UPDATE_VLC_STATUS_URL );
216         goto error;
217     }
218     p_update->release.psz_desc = psz_line;
219
220     error:
221         vlc_mutex_unlock( &p_update->lock );
222
223         if( p_stream )
224             stream_Delete( p_stream );
225 }
226
227 /**
228  * Check for updates
229  *
230  * \param p_update pointer to update struct
231  * \returns nothing
232  */
233 void update_Check( update_t *p_update )
234 {
235     assert( p_update );
236
237     EmptyRelease( p_update );
238
239     GetUpdateFile( p_update );
240 }
241
242 /**
243  * Compare two extra
244  *
245  * \param p1 first integer
246  * \param p2 second integer
247  * \return like strcmp
248  */
249 static int extracmp( char *psz_1, char *psz_2 )
250 {
251     if( psz_1[0] == '-' )
252     {
253         if( psz_2[0] == '-' )
254             return strcmp( psz_1, psz_2 );
255         else
256             return 1;
257     }
258     else
259     {
260         if( psz_2[0] == '-' )
261             return -1;
262         else
263             return strcmp( psz_1, psz_2 );
264     }
265 }
266 /**
267  * Compare two release numbers
268  *
269  * \param p1 first release
270  * \param p2 second release
271  * \return UpdateReleaseStatus(Older|Equal|Newer)
272  */
273 static int CompareReleases( const struct update_release_t *p1,
274                             const struct update_release_t *p2 )
275 {
276     int32_t d;
277     d = ( p1->i_major << 24 ) + ( p1->i_minor << 16 ) + ( p1->i_revision << 8 );
278     d = d - ( p2->i_major << 24 ) - ( p2->i_minor << 16 ) - ( p2->i_revision << 8 );
279     d += extracmp( p1->psz_extra, p2->psz_extra );
280
281     if( d == 0 )
282         d = strcmp( p1->psz_svnrev, p2->psz_svnrev );
283
284     if( d < 0 )
285         return UpdateReleaseStatusOlder;
286     else if( d == 0 )
287         return UpdateReleaseStatusEqual;
288     else
289         return UpdateReleaseStatusNewer;
290 }
291
292 /**
293  * Compare a given release's version number to the current VLC's one
294  *
295  * \param p a release
296  * \return UpdateReleaseStatus(Older|Equal|Newer)
297  */
298 int update_CompareReleaseToCurrent( update_t *p_update )
299 {
300     assert( p_update );
301
302     struct update_release_t c;
303     int i_major = 0;
304     int i_minor = 0;
305     int i_revision = 0;
306     char *psz_extra;
307     int i_result = UpdateReleaseStatusOlder;
308
309     /* get the current version number */
310     if( sscanf( PACKAGE_VERSION, "%i.%i.%i%as", &i_major, &i_minor, &i_revision, &psz_extra ) )
311     {
312         c.i_major = i_major;
313         c.i_minor = i_minor;
314         c.i_revision = i_revision;
315         if( psz_extra )
316             c.psz_extra = psz_extra;
317         else
318             c.psz_extra = STRDUP( "" );
319         c.psz_svnrev = STRDUP( VLC_Changeset() );
320
321         i_result = CompareReleases( &p_update->release, &c );
322
323         free( c.psz_extra );
324         free( c.psz_svnrev );
325     }
326     return i_result;
327 }