|
Atrinik Client 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00087 #include <global.h> 00088 00090 static curl_data *dl_data = NULL; 00092 static update_file_struct *download_packages; 00094 static size_t download_packages_num = 0; 00096 static size_t download_package_next = 0; 00098 static size_t download_packages_downloaded = 0; 00100 static uint8 download_package_process = 0; 00102 static progress_dots progress; 00103 00109 static char *updater_get_dir(char *buf, size_t len) 00110 { 00111 snprintf(buf, len, "%s/.atrinik/temp", get_config_dir()); 00112 return buf; 00113 } 00114 00118 static void cleanup_patch_files() 00119 { 00120 char dir_path[HUGE_BUF]; 00121 00122 rmrf(updater_get_dir(dir_path, sizeof(dir_path))); 00123 } 00124 00127 static void popup_draw_func_post(popup_struct *popup) 00128 { 00129 SDL_Rect box; 00130 00131 box.x = popup->x; 00132 box.y = popup->y + 10; 00133 box.w = popup->surface->w; 00134 box.h = popup->surface->h; 00135 00136 string_blt(ScreenSurface, FONT_SERIF20, "<u>Settings</u>", box.x, box.y + 10, COLOR_HGOLD, TEXT_ALIGN_CENTER | TEXT_MARKUP, &box); 00137 box.y += 50; 00138 00139 /* Show the progress dots. */ 00140 progress_dots_show(&progress, ScreenSurface, box.x + box.w / 2 - progress_dots_width(&progress) / 2, box.y); 00141 box.y += 30; 00142 00143 /* Not done yet and downloading something, inform the user. */ 00144 if (!progress.done && dl_data) 00145 { 00146 /* Downloading list of updates? */ 00147 if (!strncmp(dl_data->url, UPDATER_CHECK_URL, strlen(UPDATER_CHECK_URL))) 00148 { 00149 string_blt_shadow(ScreenSurface, FONT_ARIAL11, "Downloading list of updates...", box.x, box.y, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER, &box); 00150 } 00151 else 00152 { 00153 string_blt_shadow_format(ScreenSurface, FONT_ARIAL11, box.x, box.y, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER, &box, "Downloading update #%"FMT64" out of %"FMT64"...", (uint64) download_package_next, (uint64) download_packages_num); 00154 } 00155 } 00156 00157 /* There is something being downloaded. */ 00158 if (dl_data) 00159 { 00160 sint8 ret = curl_download_finished(dl_data); 00161 00162 /* We are not done yet... */ 00163 progress.done = 0; 00164 00165 /* Failed? */ 00166 if (ret == -1) 00167 { 00168 /* Remove the temporary directory. */ 00169 cleanup_patch_files(); 00170 progress.done = 1; 00171 00172 string_blt_shadow(ScreenSurface, FONT_ARIAL11, "Connection timed out.", box.x, box.y, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER, &box); 00173 00174 box.y += 20; 00175 00176 /* Give the user a chance to retroy. */ 00177 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, box.x + box.w / 2 - Bitmaps[BITMAP_BUTTON]->bitmap->w / 2, box.y, "Retry", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00178 { 00179 popup_destroy_visible(); 00180 updater_open(); 00181 return; 00182 } 00183 } 00184 /* Finished downloading. */ 00185 else if (ret == 1) 00186 { 00187 /* Is it the list of updates? */ 00188 if (!strncmp(dl_data->url, UPDATER_CHECK_URL, strlen(UPDATER_CHECK_URL))) 00189 { 00190 if (dl_data->memory) 00191 { 00192 char *cp, *line, *tmp[2]; 00193 00194 cp = strdup(dl_data->memory); 00195 00196 line = strtok(cp, "\n"); 00197 00198 while (line) 00199 { 00200 if (split_string(line, tmp, arraysize(tmp), '\t') == 2) 00201 { 00202 download_packages = realloc(download_packages, sizeof(*download_packages) * (download_packages_num + 1)); 00203 download_packages[download_packages_num].filename = strdup(tmp[0]); 00204 download_packages[download_packages_num].sha1 = strdup(tmp[1]); 00205 download_packages_num++; 00206 } 00207 00208 line = strtok(NULL, "\n"); 00209 } 00210 00211 free(cp); 00212 } 00213 00214 #ifdef WIN32 00215 if (download_packages_num) 00216 { 00217 download_package_process = 1; 00218 download_package_next = 0; 00219 } 00220 #endif 00221 00222 curl_data_free(dl_data); 00223 dl_data = NULL; 00224 } 00225 00226 /* Are we downloading packages? */ 00227 if (download_package_process) 00228 { 00229 /* Have we got anything to store yet, or are we just starting the download? */ 00230 if (download_package_next != 0 && dl_data) 00231 { 00232 char sha1_output_ascii[41]; 00233 unsigned char sha1_output[20]; 00234 size_t i; 00235 00236 /* Calculate the SHA-1 sum of the downloaded data. */ 00237 sha1((unsigned char *) dl_data->memory, dl_data->size, sha1_output); 00238 00239 /* Create the ASCII SHA-1 sum. snprintf() is not 00240 * needed, because no overflow can happen in this 00241 * case. */ 00242 for (i = 0; i < 20; i++) 00243 { 00244 sprintf(sha1_output_ascii + i * 2, "%02x", sha1_output[i]); 00245 } 00246 00247 /* Compare the SHA-1 sum. */ 00248 if (!strcmp(download_packages[download_package_next - 1].sha1, sha1_output_ascii)) 00249 { 00250 char dir_path[HUGE_BUF], filename[HUGE_BUF]; 00251 FILE *fp; 00252 00253 /* Get the temporary directory. */ 00254 updater_get_dir(dir_path, sizeof(dir_path)); 00255 00256 /* Create the temporary directory if it doesn't exist yet. */ 00257 if (access(dir_path, R_OK) != 0) 00258 { 00259 mkdir(dir_path, 0755); 00260 } 00261 00262 /* Construct the path. */ 00263 snprintf(filename, sizeof(filename), "%s/client_patch_%09"FMT64".tar.gz", dir_path, (uint64) download_package_next - 1); 00264 fp = fopen(filename, "wb"); 00265 00266 if (fp) 00267 { 00268 fwrite(dl_data->memory, 1, dl_data->size, fp); 00269 fclose(fp); 00270 download_packages_downloaded++; 00271 } 00272 } 00273 /* Did not match, stop downloading, even if there are more. */ 00274 else 00275 { 00276 download_package_next = download_packages_num; 00277 } 00278 00279 curl_data_free(dl_data); 00280 dl_data = NULL; 00281 } 00282 00283 /* Starting the download (possibly next package). */ 00284 if (download_package_next < download_packages_num) 00285 { 00286 char url[HUGE_BUF]; 00287 00288 /* Construct the URL. */ 00289 snprintf(url, sizeof(url), UPDATER_PATH_URL"/%s", download_packages[download_package_next].filename); 00290 dl_data = curl_download_start(url); 00291 download_package_next++; 00292 } 00293 } 00294 } 00295 } 00296 /* Finished all downloads. */ 00297 else 00298 { 00299 progress.done = 1; 00300 00301 /* No packages, so the client is up-to-date. */ 00302 if (!download_packages_num) 00303 { 00304 string_blt_shadow(ScreenSurface, FONT_ARIAL11, "Your client is up-to-date.", box.x, box.y, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER, &box); 00305 box.y += 60; 00306 00307 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, box.x + box.w / 2 - Bitmaps[BITMAP_BUTTON]->bitmap->w / 2, box.y, "Close", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00308 { 00309 popup_destroy_visible(); 00310 return; 00311 } 00312 } 00313 else 00314 { 00315 #ifdef WIN32 00316 string_blt_shadow_format(ScreenSurface, FONT_ARIAL11, box.x, box.y, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER, &box, "%"FMT64" update(s) downloaded successfully.", (uint64) download_packages_downloaded); 00317 box.y += 20; 00318 string_blt_shadow(ScreenSurface, FONT_ARIAL11, "Restart the client to complete the update.", box.x, box.y, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER, &box); 00319 00320 if (download_packages_downloaded < download_packages_num) 00321 { 00322 string_blt_shadow_format(ScreenSurface, FONT_ARIAL11, box.x, box.y + 20, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER, &box, "%"FMT64" update(s) failed to download (possibly due to a connection failure).", (uint64) (download_packages_num - download_packages_downloaded)); 00323 string_blt_shadow(ScreenSurface, FONT_ARIAL11, "You may need to retry updating after restarting the client.", box.x, box.y + 40, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER, &box); 00324 } 00325 00326 box.y += 60; 00327 00328 /* Show a restart button, which will call up_dater.exe to 00329 * apply the updates (using atrinik_updater.bat) and restarts 00330 * the client. */ 00331 if (button_show(BITMAP_BUTTON, -1, BITMAP_BUTTON_DOWN, box.x + box.w / 2 - Bitmaps[BITMAP_BUTTON]->bitmap->w / 2, box.y, "Restart", FONT_ARIAL10, COLOR_WHITE, COLOR_BLACK, COLOR_HGOLD, COLOR_BLACK, 0)) 00332 { 00333 char path[HUGE_BUF], wdir[HUGE_BUF]; 00334 00335 snprintf(path, sizeof(path), "%s\\up_dater.exe", getcwd(wdir, sizeof(wdir) - 1)); 00336 ShellExecute(NULL, "open", path, NULL, NULL, SW_SHOWNORMAL); 00337 system_end(); 00338 exit(0); 00339 } 00340 #else 00341 string_blt_shadow(ScreenSurface, FONT_ARIAL11, "Updates are available; please use your distribution's package/update", box.x, box.y, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER, &box); 00342 box.y += 20; 00343 string_blt_shadow(ScreenSurface, FONT_ARIAL11, "manager to update, or visit <a=url:http://www.atrinik.org/>www.atrinik.org</a> for help.", box.x, box.y, COLOR_WHITE, COLOR_BLACK, TEXT_ALIGN_CENTER | TEXT_MARKUP, &box); 00344 #endif 00345 } 00346 } 00347 } 00348 00353 static int popup_destroy_callback(popup_struct *popup) 00354 { 00355 size_t i; 00356 00357 (void) popup; 00358 00359 /* Free data that is being downloaded, if the user quits mid-download. 00360 * Also remove the temp directory, as the update has clearly not 00361 * finished downloading its data */ 00362 if (dl_data) 00363 { 00364 cleanup_patch_files(); 00365 curl_data_free(dl_data); 00366 dl_data = NULL; 00367 } 00368 00369 /* Free the allocated filenames and SHA-1 sums. */ 00370 for (i = 0; i < download_packages_num; i++) 00371 { 00372 free(download_packages[i].filename); 00373 free(download_packages[i].sha1); 00374 } 00375 00376 if (download_packages) 00377 { 00378 free(download_packages); 00379 download_packages = NULL; 00380 } 00381 00382 download_packages_num = 0; 00383 download_package_next = 0; 00384 download_package_process = 0; 00385 download_packages_downloaded = 0; 00386 00387 return 1; 00388 } 00389 00392 void updater_open() 00393 { 00394 popup_struct *popup; 00395 CURL *curl; 00396 char url[HUGE_BUF], version[MAX_BUF], *version_escaped; 00397 00398 /* Create the popup. */ 00399 popup = popup_create(BITMAP_POPUP); 00400 popup->destroy_callback_func = popup_destroy_callback; 00401 popup->draw_func_post = popup_draw_func_post; 00402 00403 /* Construct URL. */ 00404 curl = curl_easy_init(); 00405 package_get_version_full(version, sizeof(version)); 00406 version_escaped = curl_easy_escape(curl, version, 0); 00407 snprintf(url, sizeof(url), UPDATER_CHECK_URL"&version=%s", version_escaped); 00408 curl_free(version_escaped); 00409 curl_easy_cleanup(curl); 00410 00411 /* Start downloading the list of available updates. */ 00412 dl_data = curl_download_start(url); 00413 00414 progress_dots_create(&progress); 00415 }
1.7.4