]> git.sesse.net Git - vlc/blob - src/misc/update.c
Modify the update system : I will add more functionnality but this is the beginning
[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 //#define UPDATE_VLC_STATUS_URL "http://zen.via.ecp.fr/~ivoire/videolan/update"
51
52 #if defined( UNDER_CE )
53 #   define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-ce"
54 #elif defined( WIN32 )
55 #   define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-win-x86"
56 #elif defined( __APPLE__ )
57 #   define UPDATE_VLC_OS "macosx"
58 #   if defined( __powerpc__ ) || defined( __ppc__ ) || defined( __ppc64__ )
59 #       define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-ppc"
60 #   else
61 #       define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-mac-x86"
62 #   endif
63 #elif defined( SYS_BEOS )
64 #       define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status-beos-x86"
65 #else
66 #   define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status"
67 #endif
68
69 #define STRDUP( a ) ( a ? strdup( a ) : NULL )
70
71
72 /*****************************************************************************
73  * Local Prototypes
74  *****************************************************************************/
75 static void EmptyRelease( update_t *p_update );
76 static void GetUpdateFile( update_t *p_update );
77 static int cmp( int i1, int i2 );
78 static int CompareReleases( const struct update_release_t *p1,
79                             const struct update_release_t *p2 );
80
81
82 /*****************************************************************************
83  * Update_t functions
84  *****************************************************************************/
85
86 /**
87  * Create a new update VLC struct
88  *
89  * \param p_this the calling vlc_object
90  * \return pointer to new update_t or NULL
91  */
92 update_t *__update_New( vlc_object_t *p_this )
93 {
94     update_t *p_update;
95
96     if( p_this == NULL ) return NULL;
97
98     p_update = (update_t *)malloc( sizeof( update_t ) );
99     if( !p_update ) return NULL;
100
101     vlc_mutex_init( p_this, &p_update->lock );
102
103     p_update->p_libvlc = p_this->p_libvlc;
104
105     p_update->release.psz_svnrev = NULL;
106     p_update->release.psz_extra = NULL;
107     p_update->release.psz_url = NULL;
108     p_update->release.psz_desc = NULL;
109
110     return p_update;
111 }
112
113 /**
114  * Delete an update_t struct
115  *
116  * \param p_update update_t* pointer
117  * \return nothing
118  */
119 void update_Delete( update_t *p_update )
120 {
121     assert( p_update );
122
123     vlc_mutex_destroy( &p_update->lock );
124
125     if( p_update->release.psz_svnrev )
126     {
127         free( p_update->release.psz_svnrev );
128         p_update->release.psz_svnrev = NULL;
129     }
130
131     if( p_update->release.psz_extra )
132     {
133         free( p_update->release.psz_extra );
134         p_update->release.psz_extra = NULL;
135     }
136
137     if( p_update->release.psz_url )
138     {
139         free( p_update->release.psz_url );
140         p_update->release.psz_url = NULL;
141     }
142
143     if( p_update->release.psz_desc )
144     {
145         free( p_update->release.psz_desc );
146         p_update->release.psz_desc = NULL;
147     }
148
149     free( p_update );
150 }
151
152 /**
153  * Empty the release struct
154  *
155  * \param p_update update_t* pointer
156  * \return nothing
157  */
158 static void EmptyRelease( update_t *p_update )
159 {
160     p_update->release.i_major = 0;
161     p_update->release.i_minor = 0;
162     p_update->release.i_revision = 0;
163
164     if( p_update->release.psz_svnrev )
165     {
166         free( p_update->release.psz_svnrev );
167         p_update->release.psz_svnrev = NULL;
168     }
169
170     if( p_update->release.psz_extra )
171     {
172         free( p_update->release.psz_extra );
173         p_update->release.psz_extra = NULL;
174     }
175
176     if( p_update->release.psz_url )
177     {
178         free( p_update->release.psz_url );
179         p_update->release.psz_url = NULL;
180     }
181
182     if( p_update->release.psz_desc )
183     {
184         free( p_update->release.psz_desc );
185         p_update->release.psz_desc = NULL;
186     } 
187 }
188
189 /**
190  * Get the update file and parse it
191  * *p_update has to be unlocked when calling this function
192  *
193  * \param p_update pointer to update struct
194  * \return nothing
195  */
196 static void GetUpdateFile( update_t *p_update )
197 {
198     stream_t *p_stream = NULL;
199     int i_major = 0;
200     int i_minor = 0;
201     int i_revision = 0;
202     char *psz_extra = NULL;
203     char *psz_svnrev = NULL;
204     char *psz_line = NULL;
205
206     vlc_mutex_lock( &p_update->lock );
207
208     p_stream = stream_UrlNew( p_update->p_libvlc, UPDATE_VLC_STATUS_URL );
209     if( !p_stream )
210     {
211         msg_Err( p_update->p_libvlc, "Failed to open %s for reading",
212                  UPDATE_VLC_STATUS_URL );
213         goto error;
214     }
215
216     /* Try to read three lines */
217     if( !( psz_line = stream_ReadLine( p_stream ) ) )
218     {
219         msg_Err( p_update->p_libvlc, "Update file %s is corrupted : missing version",
220                  UPDATE_VLC_STATUS_URL );
221         goto error;
222     }
223
224     /* first line : version number */
225     if( sscanf( psz_line, "%i.%i.%i%as %as", &i_major, &i_minor, &i_revision, &psz_extra, &psz_svnrev ) )
226     {
227         p_update->release.i_major = i_major;
228         p_update->release.i_minor = i_minor;
229         p_update->release.i_revision = i_revision;
230
231         if( psz_svnrev )
232             p_update->release.psz_svnrev = psz_svnrev;
233         else
234             p_update->release.psz_svnrev = STRDUP( "" );
235
236         if( psz_extra )
237             p_update->release.psz_extra = psz_extra;
238         else
239             p_update->release.psz_extra = STRDUP( "" );
240     }
241     else
242     {
243         msg_Err( p_update->p_libvlc, "Update version false formated" );
244         free( psz_line );
245         goto error;
246     }
247
248     /* Second line : URL */
249     if( !( psz_line = stream_ReadLine( p_stream ) ) )
250     {
251         msg_Err( p_update->p_libvlc, "Update file %s is corrupted : URL missing",
252                  UPDATE_VLC_STATUS_URL );
253         goto error;
254     }
255     p_update->release.psz_url = psz_line;
256
257
258     /* Third line : description */
259     if( !( psz_line = stream_ReadLine( p_stream ) ) )
260     {
261         msg_Err( p_update->p_libvlc, "Update file %s is corrupted : description missing",
262                  UPDATE_VLC_STATUS_URL );
263         goto error;
264     }
265     p_update->release.psz_desc = psz_line;
266
267     error:
268         vlc_mutex_unlock( &p_update->lock );
269
270         if( p_stream )
271             stream_Delete( p_stream );
272 }
273
274 /**
275  * Check for updates
276  *
277  * \param p_update pointer to update struct
278  * \returns nothing
279  */
280 void update_Check( update_t *p_update )
281 {
282     assert( p_update );
283
284     EmptyRelease( p_update );
285
286     GetUpdateFile( p_update );
287 }
288
289 /**
290  * Compare two integers
291  *
292  * \param p1 first integer
293  * \param p2 second integer
294  * \return like strcmp
295  */
296 static int cmp( int i1, int i2 )
297 {
298     if( i1 < i2 )
299         return -1;
300     else if(i1 == i2)
301         return 0;
302     else
303         return 1;
304 }
305
306 /**
307  * Compare two release numbers
308  *
309  * \param p1 first release
310  * \param p2 second release
311  * \return UpdateReleaseStatus(Older|Equal|Newer)
312  */
313 static int CompareReleases( const struct update_release_t *p1,
314                             const struct update_release_t *p2 )
315 {
316     int d;
317     if( ( d = cmp( p1->i_major, p2->i_major ) ) ) ;
318     else if( ( d = cmp( p1->i_minor, p2->i_minor ) ) ) ;
319     else if( ( d = cmp( p1->i_revision, p2->i_revision ) ) ) ;
320     else
321     {
322         if( p1->psz_extra[0] == '-' )
323         {
324             if( p2->psz_extra[0] == '-' )
325                 d = strcmp( p1->psz_extra, p2->psz_extra );
326             else
327                 d = 1;
328         }
329         else
330         {
331             if( p2->psz_extra[0] == '-' )
332                 d = -1;
333             else
334                 d = strcmp(p1->psz_extra, p2->psz_extra );
335         }
336         if( d == 0 )
337             d = strcmp( p1->psz_svnrev, p2->psz_svnrev );
338     }
339
340     if( d < 0 )
341         return UpdateReleaseStatusOlder;
342     else if( d == 0 )
343         return UpdateReleaseStatusEqual;
344     else
345         return UpdateReleaseStatusNewer;
346 }
347
348 /**
349  * Compare a given release's version number to the current VLC's one
350  *
351  * \param p a release
352  * \return UpdateReleaseStatus(Older|Equal|Newer)
353  */
354 int update_CompareReleaseToCurrent( update_t *p_update )
355 {
356     assert( p_update );
357
358     struct update_release_t c;
359     int i_major = 0;
360     int i_minor = 0;
361     int i_revision = 0;
362     char *psz_extra;
363     int i_result = UpdateReleaseStatusOlder;
364
365     /* get the current version number */
366     if( sscanf( PACKAGE_VERSION, "%i.%i.%i%as", &i_major, &i_minor, &i_revision, &psz_extra ) )
367     {
368         c.i_major = i_major;
369         c.i_minor = i_minor;
370         c.i_revision = i_revision;
371         if( psz_extra )
372             c.psz_extra = psz_extra;
373         else
374             c.psz_extra = STRDUP( "" );
375         c.psz_svnrev = STRDUP( VLC_Changeset() );
376
377         i_result = CompareReleases( &p_update->release, &c );
378
379         free( c.psz_extra );
380         free( c.psz_svnrev );
381     }
382     return i_result;
383 }