/* $Id: update.c,v 1.7 2005/03/26 23:04:14 titer Exp $ This file is part of the HandBrake source code. Homepage: . It may be used under the terms of the GNU General Public License. */ #include "hb.h" static void UpdateFunc( void * ); typedef struct { int * build; char * version; } hb_update_t; hb_thread_t * hb_update_init( int * build, char * version ) { hb_update_t * data = calloc( sizeof( hb_update_t ), 1 ); data->build = build; data->version = version; return hb_thread_init( "update", UpdateFunc, data, HB_NORMAL_PRIORITY ); } static void UpdateFunc( void * _data ) { hb_update_t * data = (hb_update_t *) _data; char * hb_query, * hb_query_two; hb_net_t * net; int ret; char buf[4096]; char * cur, * end; int size; int stable, unstable; char stable_str[16], unstable_str[16]; int i; /* Setup hb_query and hb_query_two with the correct appcast file */ if( HB_PROJECT_BUILD % 100 ) { hb_log("Using http://handbrake.fr/appcast_unstable.xml (primary)"); hb_log("Using http://handbrake.fr/appcast.xml (secondary)"); } else { hb_log("Using http://handbrake.fr/appcast.xml (primary)"); hb_log("Using http://handbrake.fr/appcast_unstable.xml (secondary)"); } hb_query = "GET /appcast.xml HTTP/1.0\r\nHost: handbrake.fr\r\n\r\n"; hb_query_two = "GET /appcast_unstable.xml HTTP/1.0\r\nHost: handbrake.fr\r\n\r\n"; /* Grab the data from the web server */ if( !( net = hb_net_open( "handbrake.fr", 80 ) ) ) { goto error; } if( hb_net_send( net, hb_query ) < 0 ) { hb_log("Error: Unable to connect to server"); hb_net_close( &net ); goto error; } size = 0; memset( buf, 0, 4096 ); for( ;; ) { ret = hb_net_recv( net, &buf[size], sizeof( buf ) - size ); if( ret < 1 ) { hb_net_close( &net ); break; } size += ret; } cur = buf; end = &buf[sizeof( buf )]; /* Make sure we got it */ cur += 9; if( size < 15 || strncmp( cur, "200 OK", 6 ) ) { hb_log("Error: We did not get a 200 OK from the server. \n"); goto error; } cur += 6; /* Find the end of the headers and the beginning of the content */ for( ; &cur[3] < end; cur++ ) { if( cur[0] == '\r' && cur[1] == '\n' && cur[2] == '\r' && cur[3] == '\n' ) { cur += 4; break; } } if( cur >= end ) { hb_log("Error: Found the end of the buffer before the end of the HTTP header information! \n"); goto error; } /* * Find the tag * Scan though each character of the buffer until we find that the first 4 characters of "cur" are "' ) { cur += 1; break; } /* If the CLI tag has not been found in the first 768 characters, or the end is reached, something bad happened.*/ if (( i > 768) || ( cur >= end )) { hb_log("Error: Did not find the tag in the expected maximum amount of characters into the file. \n"); goto error; } } if( cur >= end ) { goto error; } /* * Ok, The above code didn't position cur, it only found = end ) { hb_log("Error: Unexpected end of buffer! Could not find the build information. \n"); goto error; } /* Stable HB_PROJECT_BUILD */ stable = strtol( cur, &cur, 10 ); if( cur >= end ) { hb_log("Error: Unexpected end of buffer! \n"); goto error; } /* * The Version number is 2 places after the build, so shift cur, 2 places. * Get all the characters in cur until the point where " is found. */ cur += 2; if( cur >= end ) { hb_log("Error: Unexpected end of buffer! Could not get version number. \n"); goto error; } memset( stable_str, 0, sizeof( stable_str ) ); for( i = 0; i < sizeof( stable_str ) - 1 && cur < end && *cur != '"'; i++, cur++ ) { stable_str[i] = *cur; /* If the CLI tag has not been found in the first 768 characters, or the end is reached, something bad happened.*/ if (( i > 7) || ( cur >= end )) { hb_log("Error: Version number too long, or end of buffer reached. \n"); goto error; } } if( cur >= end ) { goto error; } /* HANDLE THE SECOND APPCAST FILE NOW */ /* Grab the data from the web server */ if( !( net = hb_net_open( "handbrake.fr", 80 ) ) ) { goto error; } if( hb_net_send( net, hb_query_two ) < 0 ) { hb_log("Error: Unable to connect to server"); hb_net_close( &net ); goto error; } size = 0; memset( buf, 0, 4096 ); for( ;; ) { ret = hb_net_recv( net, &buf[size], sizeof( buf ) - size ); if( ret < 1 ) { hb_net_close( &net ); break; } size += ret; } cur = buf; end = &buf[sizeof( buf )]; /* Make sure we got it */ cur += 9; if( size < 15 || strncmp( cur, "200 OK", 6 ) ) { /* Something went wrong */ hb_log("Error: We did not get a 200 OK from the server. \n"); goto error; } cur += 6; /* Find the end of the headers and the beginning of the content */ for( ; &cur[3] < end; cur++ ) { if( cur[0] == '\r' && cur[1] == '\n' && cur[2] == '\r' && cur[3] == '\n' ) { cur += 4; break; } } if( cur >= end ) { hb_log("Error: Found the end of the buffer before the end of the HTTP header information! \n"); goto error; } /* * Find the tag * Scan though each character of the buffer until we find that the first 4 characters of "cur" are "' ) { cur += 1; break; } // If the CLI tag has not been found in the first 768 characters, or the end is reached, something bad happened. if (( i > 768) || ( cur >= end )) { hb_log("Error: Did not find the tag in the expected maximum amount of characters into the file. \n"); goto error; } } if( cur >= end ) { goto error; } /* * Ok, The above code didn't position cur, it only found = end ) { hb_log("Error: Unexpected end of buffer! Could not find the build information. \n"); goto error; } /* UnStable HB_PROJECT_BUILD */ unstable = strtol( cur, &cur, 10 ); if( cur >= end ) { hb_log("Error: Unexpected end of buffer! \n"); goto error; } /* * The Version number is 2 places after the build, so shift cur, 2 places. * Get all the characters in cur until the point where " is found. */ cur += 2; if( cur >= end ) { hb_log("Error: Unexpected end of buffer! Could not get version number. \n"); goto error; } memset( unstable_str, 0, sizeof( unstable_str ) ); for( i = 0; i < sizeof( unstable_str ) - 1 && cur < end && *cur != '"'; i++, cur++ ) { unstable_str[i] = *cur; // If the version number is longer than 7 characters, or the end is reached, something has gone wrong. if (( i > 7) || ( cur >= end )) { hb_log("Error: Version number too long, or end of buffer reached. \n"); goto error; } } if( cur >= end ) { goto error; } /* Print the version information */ hb_log( "latest stable: %s, build %d", stable_str, stable ); hb_log( "latest unstable: %s, build %d", unstable_str, unstable ); /* Return the build information */ if( HB_PROJECT_BUILD % 100 ) { /* We are runnning an unstable build */ if( unstable > HB_PROJECT_BUILD ) { memcpy( data->version, unstable_str, sizeof( unstable_str ) ); *(data->build) = unstable; } } else { /* We are runnning an stable build */ if( stable > HB_PROJECT_BUILD ) { memcpy( data->version, stable_str, sizeof( stable_str ) ); *(data->build) = stable; } } error: free( data ); return; }