// by oggzee and Dr. Clipper // theme previews added by usptactical #include #include #include #include #include #include #include #include #include #include #include #include #include #include "disc.h" #include "fat.h" #include "cache.h" #include "gui.h" #include "menu.h" #include "restart.h" #include "sys.h" #include "util.h" #include "utils.h" #include "video.h" #include "wbfs.h" #include "wpad.h" #include "patchcode.h" #include "cfg.h" #include "http.h" #include "dns.h" #include "wdvd.h" #include "music.h" #include "subsystem.h" #include "net.h" #include "gettext.h" #include "xml.h" #include "unzip/unzip.h" //////////////////////////////////////// // // Updates // //////////////////////////////////////// #define MAX_UP_DESC 6 struct UpdateInfo { char version[32]; char url[128]; int size; char date[16]; // 2009-12-30 char desc[MAX_UP_DESC][40]; int ndesc; }; struct ThemeInfo { int ID; char name[32]; char url[128]; char thumbpath[200]; char creator[32]; int version; int downloads; int votes; int rating; int adult; int updated; int type; }; #define THEME_TYPE_NEW_THEME 0 #define THEME_TYPE_UPDATES_AVAILABLE 1 #define THEME_TYPE_UP_TO_DATE 2 #define MAX_UPDATES 20 int num_updates = 0; int num_themes = 0; int num_new_themes, num_theme_updates; struct UpdateInfo updates[MAX_UPDATES]; char meta_xml[4096]; struct ThemeInfo *themes = NULL; int themeIdx; size_t theme_updated; bool parsebuf_line(char *buf, int (*line_func)(char*)) { char line[200]; char *p, *nl; int len, ret; nl = buf; for (;;) { p = nl; if (p == NULL) break; while (*p == '\n') p++; if (*p == 0) break; nl = strchr(p, '\n'); if (nl == NULL) { len = strlen(p); } else { len = nl - p; } if (len >= sizeof(line)) len = sizeof(line) - 1; strcopy(line, p, len+1); ret = line_func(line); if (ret) break; } return true; } void themeinfo_set(char *name, char *val) { //is this the "id" property in the theme info file? if (!strcmp(name, "id")) { bool found; int i; //try to find the index for this theme in the themes struct for (i=0, found = false; !found && i < num_themes; i++) { if (atoi(val) == themes[i].ID) { found = true; themeIdx = i; } } } else if (!strcmp(name, "updated")) { theme_updated = atoi(val); } } int download_theme_preview(char *path, int idx) { char filename[200]; FILE *f = NULL; struct block file; file.data = NULL; printf_("%d. %s", idx, themes[idx].name); printf("\n"); snprintf(filename, sizeof(filename), "%s/%d.jpg", path, themes[idx].ID); file = downloadfile(themes[idx].thumbpath); if (file.data == NULL || file.size == 0) { goto err; } f = fopen(filename, "wb"); if (!f) { printf_(gt("Error opening: %s"), filename); printf("\n"); goto err; } fwrite(file.data, 1, file.size, f); fclose(f); SAFE_FREE(file.data); return 0; err: SAFE_FREE(file.data); printf_(gt("Error downloading theme preview...")); printf("\n"); return -1; } // Downloads the theme preview image files void download_all_theme_previews() { char pathname[200]; char path[200]; char old_path[200]; char old_name[200]; int i; struct stat st; int buttons; printf_("%s\n", gt("Downloading Theme previews...")); printf_h("%s\n\n", gt("Hold button B to cancel.")); snprintf(D_S(old_path), "%s/themes", USBLOADER_PATH); snprintf(D_S(path), "%s/theme_previews", USBLOADER_PATH); mkpath(path, 0777); for (i=0; i= 0) { if (themes[themeIdx].type != THEME_TYPE_NEW_THEME) continue; strcopy(themes[themeIdx].name, theme_list[i], sizeof(themes[0].name)); if (themes[themeIdx].updated > theme_updated) { // An update is available themes[themeIdx].type = THEME_TYPE_UPDATES_AVAILABLE; num_theme_updates++; num_new_themes--; //printf("Type 1 - update available\n"); //sleep(1); } else { // Theme is up to date themes[themeIdx].type = THEME_TYPE_UP_TO_DATE; num_new_themes--; //printf("Type 2 - up to date\n"); //sleep(1); } } } } } int themenum_set(char *line) { return sscanf(line, " %d", &num_updates); } int themedata_set(char *line) { char *tag = NULL; char *value = NULL; char *closetag = NULL; if ((tag = strchr(line,'<')) == NULL) return 0; tag++; if ((value = strchr(tag,'>')) == NULL) return 0; *value++ = '\0'; if ((closetag = strchr(value,'<')) != NULL) *closetag = '\0'; if (!strcmp(tag, "id")) { sscanf(value, " %d", &themes[num_themes].ID); } else if (!strcmp(tag, "name")) { strcopy(themes[num_themes].name, value, sizeof(themes[0].name)); } else if (!strcmp(tag, "creator")) { strcopy(themes[num_themes].creator, value, sizeof(themes[0].creator)); } else if (!strcmp(tag, "version")) { sscanf(value, " %d", &themes[num_themes].version); } else if (!strcmp(tag, "adult")) { sscanf(value, " %d", &themes[num_themes].adult); } else if (!strcmp(tag, "downloads")) { sscanf(value, " %d", &themes[num_themes].downloads); } else if (!strcmp(tag, "votes")) { sscanf(value, " %d", &themes[num_themes].votes); } else if (!strcmp(tag, "rating")) { sscanf(value, " %d", &themes[num_themes].rating); } else if (!strcmp(tag, "added") || !strcmp(tag, "lastupdated")) { int val; sscanf(value, " %d", &val); if (val > themes[num_themes].updated) themes[num_themes].updated = val; } else if (!strcmp(tag, "downloadpath")) { strcopy(themes[num_themes].url, value, sizeof(themes[0].url)); } else if (!strcmp(tag, "thumbpath")) { strcopy(themes[num_themes].thumbpath, value, sizeof(themes[0].thumbpath)); } else if (!strcmp(tag, "/theme")) { num_themes++; if (num_themes >= num_updates) return 1; } return 0; } int update_set(char *line) { char name[100], val[100]; struct UpdateInfo *u; bool opt = trimsplit(line, name, val, '=', sizeof(name)); // if space in opt name, then don't consider it an option // this is so to allow = in comments if (opt && strchr(name, ' ') != NULL) opt = false; if (opt) { if (stricmp("metaxml", name) == 0) { strncat(meta_xml, val, sizeof(meta_xml)-1); strncat(meta_xml, "\n", sizeof(meta_xml)-1); return 0; } if (stricmp("release", name) == 0) { if (num_updates >= MAX_UPDATES) { return 1; } num_updates++; u = &updates[num_updates-1]; u->ndesc = 0; u->size = 0; *u->url = 0; STRCOPY(u->version, val); return 0; } if (num_updates <= 0) return 0; u = &updates[num_updates-1]; if (stricmp("size", name) == 0) { int n; if (sscanf(val, "%d", &n) == 1) { if (n > 500000 && n < 5000000) { u->size = n; } } } else if (stricmp("date", name) == 0) { STRCOPY(u->date, val); } else if (stricmp("url", name) == 0) { STRCOPY(u->url, val); } else if (*u->url) { // anything unknown after url is a comment till a new release line goto comment; } else { // ignore unknown options } } else { comment: if (num_updates > 0) { u = &updates[num_updates-1]; if (u->ndesc < MAX_UP_DESC) { STRCOPY(u->desc[u->ndesc], line); u->ndesc++; } } } return 0; } void parse_updates(char *buf) { num_updates = 0; memset(updates, 0, sizeof(updates)); memset(meta_xml, 0, sizeof(meta_xml)); parsebuf_line(buf, update_set); } void parse_themes(char *buf) { num_updates = 0; parsebuf_line(buf, themenum_set); if (!num_updates) return; themes = calloc(num_updates, sizeof(struct ThemeInfo)); num_themes = 0; parsebuf_line(buf, themedata_set); } void Download_Update(int n, char *app_path, int update_meta) { struct UpdateInfo *u; struct block file; FILE *f = NULL; file.data = NULL; u = &updates[n]; printf_(gt("Downloading: %s"), u->version); printf("\n"); printf_("[."); file = downloadfile_progress(u->url, 1); printf("]\n"); if (file.data == NULL || file.size < 500000) { goto err; } if (u->size && u->size != file.size) { printf_(gt("Wrong Size: %d (%d)"), file.size, u->size); printf("\n"); goto err; } printf_(gt("Complete. Size: %d"), file.size); printf("\n"); printf_(gt("Saving: %s"), app_path); printf("\n"); // backup char bak_name[200]; strcpy(bak_name, app_path); strcat(bak_name, ".bak"); // remove old backup remove(bak_name); // rename current to backup rename(app_path, bak_name); // save new f = fopen(app_path, "wb"); if (!f) { printf_(gt("Error opening: %s"), app_path); printf("\n"); goto err; } fwrite(file.data, 1, file.size, f); fclose(f); if (update_meta) { // reformat date char date_long[32]; // YYYYmmddHHMMSS char *p; strcpy(date_long, u->date); // YYYY-mm-dd p = strchr(date_long, '-'); if (p) memmove(p, p+1, strlen(p)); p = strchr(date_long, '-'); if (p) memmove(p, p+1, strlen(p)); strcat(date_long, "000000"); strcpy(strrchr(app_path, '/')+1, "meta.xml"); f = fopen(app_path, "rb"); if (f) { char tmp_meta[sizeof(meta_xml)]; int size = fread(tmp_meta, 1, sizeof(tmp_meta)-32, f); fclose(f); if (size <= 0) { goto new_meta; } tmp_meta[size] = 0; // 0 terminate //dbg_printf("existing:\n%s\n", tmp_meta); // verify it's a valid meta.xml if (!strstr(tmp_meta, "")) { goto new_meta; } if (!str_replace_tag_val(tmp_meta, "", u->version)) { goto new_meta; } if (!str_replace_tag_val(tmp_meta, "", date_long)) { goto new_meta; } strcpy(meta_xml, tmp_meta); } else { new_meta: if (*meta_xml) { str_replace(meta_xml, "{VERSION}", u->version, sizeof(meta_xml)); str_replace(meta_xml, "{DATE}", date_long, sizeof(meta_xml)); printf_(gt("Saving: %s"), app_path); printf("\n"); f = fopen(app_path, "wb"); if (!f) { printf_(gt("Error opening: %s"), app_path); printf("\n"); } else { fwrite(meta_xml, 1, strlen(meta_xml), f); fclose(f); } } } if (*meta_xml) { printf_(gt("Saving: %s"), app_path); printf("\n"); //dbg_printf("saving:\n%s\n", meta_xml); f = fopen(app_path, "wb"); if (!f) { printf_(gt("Error opening: %s"), app_path); printf("\n"); } else { fwrite(meta_xml, 1, strlen(meta_xml), f); fclose(f); } } } Download_Translation(); //download new translation file printf_(gt("Done.")); printf("\n\n"); printf_(gt("NOTE: loader restart is required\nfor the update to take effect.")); printf("\n"); printf_(gt("If Cfg does not start properly\nnext time, copy boot.dol.bak over\nboot.dol and try again.")); printf("\n\n"); printf_(gt("Press any button...")); Wpad_WaitButtonsCommon(); SAFE_FREE(file.data); return; err: SAFE_FREE(file.data); printf_(gt("Error downloading update...")); printf("\n"); sleep(3); } void Menu_Updates() { struct Menu menu; struct UpdateInfo *u; char app_dir[100]; char app_path[100]; char app_bak[100]; struct stat st; int cols, rows; int max_desc; int win_size; int i; CON_GetMetrics(&cols, &rows); //calc_rows: // debug win_size = rows - 16; // rows >= 22 if (rows < 22 && rows > 16) win_size = 5; if (rows <= 16) win_size = rows - 12; if (win_size < 1) win_size = 1; if (win_size > num_updates) win_size = num_updates; menu_init(&menu, num_updates); STRCOPY(app_dir, APPS_DIR); snprintf(D_S(app_path),"%s/%s", app_dir, "boot.dol"); snprintf(D_S(app_bak),"%s/%s", app_dir, "boot.dol.bak"); // check if app_dir/boot.dol exists if (stat(app_path, &st) != 0 && stat(app_bak, &st) != 0) { // not found, use default path STRCOPY(app_dir, "sd:/apps/usbloader"); snprintf(D_S(app_path),"%s/%s", app_dir, "boot.dol"); } for (;;) { Con_Clear(); FgColor(CFG.color_header); printf_x(gt("Available Updates")); printf(":\n"); DefaultColor(); max_desc = MAX_UP_DESC; menu_begin(&menu); menu_window_begin(&menu, win_size, num_updates); for (i=0; i max_desc) { max_desc = updates[i].ndesc; } } DefaultColor(); menu_window_end(&menu, cols); FgColor(CFG.color_header); printf_x(gt("Release Notes: (short)")); printf("\n"); DefaultColor(); u = &updates[menu.current]; for (i=0; indesc) { printf_("%.*s\n", cols - strlen(CFG.menu_plus_s) - 1, u->desc[i]); } else { printf("\n"); } } if (rows > 18) { printf_h(gt("Press %s to download and update"), (button_names[CFG.button_confirm.num])); printf("\n"); if (rows > 20) { printf_h(gt("Press %s to update without meta.xml"), (button_names[CFG.button_other.num])); printf("\n"); } printf_h(gt("Press %s to return"), (button_names[CFG.button_cancel.num])); printf("\n"); } else { printf_h(gt("Press %s to download, %s to return"), (button_names[CFG.button_confirm.num]), (button_names[CFG.button_cancel.num])); printf("\n"); } if (rows > 19) printf("\n"); FgColor(CFG.color_inactive); printf_(gt("Current Version: %s"), CFG_VERSION); printf("\n"); printf_(gt("App. Path: %s"), app_dir); DefaultColor(); //Con_SetPosition(0, rows-1); printf(" -- %d %d --", rows, win_size); __console_flush(0); u32 buttons = Wpad_WaitButtonsRpt(); menu_move(&menu, buttons); if (buttons & CFG.button_exit.mask) { Handle_Home(0); } if (buttons & CFG.button_cancel.mask) break; if (buttons & CFG.button_confirm.mask) { printf("\n\n"); Download_Update(menu.current, app_path, 1); break; } if (buttons & CFG.button_other.mask) { printf("\n\n"); Download_Update(menu.current, app_path, 0); break; } //if (buttons & WPAD_BUTTON_MINUS) { rows--; goto calc_rows; } //if (buttons & WPAD_BUTTON_PLUS) { rows++; goto calc_rows; } } printf("\n"); } int Download_Theme(int n) { struct ThemeInfo *u; struct block file; int rename = 0; char theme_dir[200] = ""; char filename[200] = ""; char theme_name[32]; FILE *f = NULL; file.data = NULL; u = &themes[n]; snprintf(theme_dir, sizeof(theme_dir), "%s/themes/%s", USBLOADER_PATH, u->name); if (themes[n].type == THEME_TYPE_NEW_THEME) { while (mkpath(theme_dir, 0777) != 0) { if (errno != EEXIST) goto err2; rename++; snprintf(theme_name, sizeof(theme_name), "%.29s_%d", u->name, rename + 1); snprintf(theme_dir, sizeof(theme_dir), "%s/themes/%s", USBLOADER_PATH, theme_name); } } printf("\n"); if (rename) printf_(gt("Downloading: %s as %s"), u->name, theme_name); else printf_(gt("Downloading: %s"), u->name); printf("\n"); snprintf(filename, sizeof(filename), "%s/%s", theme_dir, "theme.zip"); printf_("[."); file = downloadfile_progress_fname(u->url, 1, filename); printf("]\n"); if (file.filesize == 0) { goto err; } /*if (u->size && u->size != file.size) { printf_(gt("Wrong Size: %d (%d)"), file.size, u->size); printf("\n"); goto err; }*/ printf_(gt("Complete. Size: %d"), file.filesize); printf("\n"); /*f = fopen(filename, "wb"); if (!f) { printf_(gt("Error opening: %s"), filename); printf("\n"); goto err; } fwrite(file.data, 1, file.size, f); fclose(f);*/ SAFE_FREE(file.data); //unzip theme unzFile zf; zf = unzOpen(filename); unzGoToFirstFile(zf); int ret = UNZ_OK; while (ret == UNZ_OK) { unz_file_info file_info; char zippedname[200]; char savename[200]; char *p, *zn; void *buf; FILE *f; ret = unzGetCurrentFileInfo(zf,&file_info,zippedname,sizeof(zippedname),NULL,0,NULL,0); for (p = zn = zippedname; *p != '\0'; p++) { if (*p == '/' || *p == '\\') zn = p + 1; } if (zn[0] == '\0') { ret = unzGoToNextFile(zf); continue; } snprintf(savename, sizeof(savename), "%s/%s", theme_dir, zn); if ((f = fopen(savename, "wb")) == NULL) { unzClose(zf); goto err3; } if ((ret = unzOpenCurrentFile(zf)) != UNZ_OK) { unzClose(zf); goto err3; } printf(gt("Extracting: %s"), zn); printf("\n"); buf = malloc(file_info.uncompressed_size); unzReadCurrentFile(zf, buf, file_info.uncompressed_size); unzCloseCurrentFile(zf); fwrite(buf,1,file_info.uncompressed_size,f); fclose(f); free(buf); ret = unzGoToNextFile(zf); } unzClose(zf); //delete zip remove(filename); //create info.txt snprintf(filename, sizeof(filename), "%s/%s", theme_dir, "info.txt"); f = fopen(filename, "w"); if (f == NULL) goto err; fprintf(f, "id = %d\n", u->ID); fprintf(f, "version = %d\n", u->version); fprintf(f, "updated = %d\n", u->updated); fprintf(f, "creator = %s\n", u->creator); fprintf(f, "adult = %d\n", u->adult); fclose(f); //Rename theme if (rename) strcopy(themes[n].name, theme_name, sizeof(themes[0].name)); printf_(gt("Done.")); printf("\n\n"); printf_(gt("Press any button...")); printf("\n"); Wpad_WaitButtonsCommon(); return 0; err: SAFE_FREE(file.data); printf_(gt("Error downloading theme...")); printf("\n"); printf_(gt("Theme may be too large.\nReboot of Cfg suggested.\n")); printf_(gt("Press any button...")); Wpad_WaitButtonsCommon(); return -1; err2: SAFE_FREE(file.data); printf_(gt("Error creating directory...")); printf("\n"); printf_(gt("Press any button...")); Wpad_WaitButtonsCommon(); return -2; err3: SAFE_FREE(file.data); printf_(gt("Error extracting theme...")); printf("\n"); printf_(gt("Press any button...")); Wpad_WaitButtonsCommon(); return -3; } void Menu_Themes() { struct Menu menu; int rows, cols, size, n, count, menu_rows; CON_GetMetrics(&cols, &rows); if ((size = rows-10) < 3) size = 3; menu_rows = 0; if (num_theme_updates) menu_rows += num_theme_updates + 1; if (num_new_themes) menu_rows += num_new_themes + 1; char active[menu_rows]; int lookup[menu_rows]; //redraw the background without the current cover Video_DrawBg(); menu_init(&menu, menu_rows); menu.current = 1; for (;;) { n = 0; count = 0; menu_init_active(&menu, active, sizeof(active)); active[0] = 0; if (num_theme_updates && num_new_themes) active[num_theme_updates+1] = 0; Con_Clear(); FgColor(CFG.color_header); printf_x(gt("Themes provided by wii.spiffy360.com")); printf("\n%s:\n", gt("Themes to download")); DefaultColor(); menu_begin(&menu); menu_window_begin(&menu, size, menu_rows); if (num_theme_updates) { lookup[count++] = -1; if (menu_window_mark(&menu)) printf("%s:\n", gt("Themes with updates")); for (n = 0; n < num_themes; n++) { if (themes[n].type == THEME_TYPE_UPDATES_AVAILABLE) { lookup[count++] = n; if (menu_window_mark(&menu)) printf("%s\n", themes[n].name); } } } if (num_new_themes) { lookup[count++] = -1; if (menu_window_mark(&menu)) printf("%s:\n", gt("New Themes")); for (n = 0; n < num_themes; n++) { if (themes[n].type == THEME_TYPE_NEW_THEME) { lookup[count++] = n; if (menu_window_mark(&menu)) printf("%s\n", themes[n].name); } } } DefaultColor(); menu_window_end(&menu, cols); //printf("\n"); FgColor(CFG.color_header); printf_x("%s:\n", gt("Theme Info")); DefaultColor(); if (m_active(&menu, menu.current)) { printf_(" %s: %s\n", gt("Creator"), themes[lookup[menu.current]].creator); printf_(" %s: %d", gt("Version"), themes[lookup[menu.current]].version); printf(" %s: %s\n", gt("Adult"), (themes[lookup[menu.current]].adult) ? gt("Yes") : gt("No")); printf_(" %s: %d", gt("Downloads"), themes[lookup[menu.current]].downloads); printf(" %s: ", gt("Rating")); if (themes[lookup[menu.current]].votes) printf("%.1f\n", (float)themes[lookup[menu.current]].rating/themes[lookup[menu.current]].votes); else printf("--\n"); printf_h(gt("Press %s to download this theme"), (button_names[CFG.button_confirm.num])); printf("\n"); printf_h(gt("Press %s for fullscreen preview"), (button_names[CFG.button_other.num])); //draw the theme preview image if (CFG.theme_previews) { Gui_DrawThemePreview(themes[lookup[menu.current]].name, themes[lookup[menu.current]].ID); } } __console_flush(0); u32 buttons = Wpad_WaitButtonsRpt(); menu_move(&menu, buttons); if ((buttons & CFG.button_confirm.mask) && lookup[menu.current] >= 0) { int ret = Download_Theme(lookup[menu.current]); if (ret == 0) { if (num_theme < MAX_THEME) { strcopy(theme_list[num_theme], themes[lookup[menu.current]].name, sizeof(theme_list[num_theme])); num_theme++; } } if (themes[lookup[menu.current]].type == THEME_TYPE_NEW_THEME) num_new_themes--; else if (themes[lookup[menu.current]].type == THEME_TYPE_UPDATES_AVAILABLE) num_theme_updates--; themes[lookup[menu.current]].type = THEME_TYPE_UP_TO_DATE; menu_rows = 0; if (num_theme_updates) menu_rows += num_theme_updates + 1; if (num_new_themes) menu_rows += num_new_themes + 1; menu.num_opt = menu_rows; if (menu.current == (menu_rows)) menu.current = menu_rows-1; } // HOME button if (buttons & CFG.button_exit.mask) { Handle_Home(0); } if (buttons & CFG.button_cancel.mask) break; // button 1 if (buttons & CFG.button_other.mask) { //draw the theme preview image if (CFG.theme_previews) { Gui_DrawThemePreviewLarge( themes[lookup[menu.current]].name, themes[lookup[menu.current]].ID); } } } //redraw the background and current cover image Video_DrawBg(); extern void __Menu_ShowCover(); __Menu_ShowCover(); } // Main method for Themes // Downloads the theme xml file from spiffy360.com // Parses the file and stores theme info in a ThemeInfo struct // Displays the Themes menu (console mode) void Theme_Update() { char *themes_url; if (CFG.adult_themes) themes_url = "http://wii.spiffy360.com/themes.php?xml=1&adult=1&category=5"; else themes_url = "http://wii.spiffy360.com/themes.php?xml=1&category=5"; struct block file; file.data = NULL; DefaultColor(); printf("\n"); printf_(gt("Checking for themes...")); printf("\n"); //download the latest theme xml if (Init_Net()) { file = downloadfile(themes_url); } if (file.data == NULL || file.size == 0) { printf_(gt("Error downloading themes...")); printf("\n"); sleep(3); return; } // null terminate char *newbuf; newbuf = mem_realloc(file.data, file.size+4); if (!newbuf) goto err; newbuf[file.size] = 0; file.data = (void*)newbuf; //check if any updates are available parse_themes((char*)file.data); SAFE_FREE(file.data); if (num_updates <= 0) { printf_(gt("No themes found.")); printf("\n"); goto out; } //printf("\n"); //printf_("Available: %d updates.\n", num_updates); //sleep(1); num_new_themes = num_themes; num_theme_updates = 0; read_themeinfo(); //update all the theme preview images if (CFG.theme_previews) download_all_theme_previews(); //if all themes have been downloaded get out if (num_new_themes == 0) { printf_(gt("All themes up to date.")); printf("\n"); goto out; } Menu_Themes(); SAFE_FREE(themes); return; err: printf_(gt("Error downloading themes...")); printf("\n"); out: sleep(3); SAFE_FREE(file.data); return; } void Online_Update() { #if defined(BUILD_222) && (BUILD_222 == 1) char *updates_url = "http://cfgusbloader.ntd.homelinux.org/svn/CfgUSBLoader/trunk/updates-222.txt"; #else char *updates_url = "http://cfgusbloader.ntd.homelinux.org/svn/CfgUSBLoader/trunk/updates.txt"; #endif struct block file; file.data = NULL; DefaultColor(); printf("\n"); printf_(gt("Checking for updates...")); printf("\n"); if (Init_Net()) { file = downloadfile(updates_url); } if (file.data == NULL || file.size == 0) { printf_(gt("Error downloading updates...")); printf("\n"); sleep(3); return; } // null terminate char *newbuf; newbuf = mem_realloc(file.data, file.size+4); if (newbuf) { newbuf[file.size] = 0; file.data = (void*)newbuf; } else { goto err; } // parse parse_updates((char*)file.data); SAFE_FREE(file.data); if (num_updates <= 0) { printf_(gt("No updates found.")); printf("\n"); goto out; } //printf("\n"); //printf_("Available: %d updates.\n", num_updates); //sleep(1); Menu_Updates(); return; err: printf_(gt("Error downloading updates...")); printf("\n"); out: sleep(3); SAFE_FREE(file.data); return; } void Download_Titles() { struct block file; file.data = NULL; char fname[100]; char url[128]; FILE *f; DefaultColor(); printf("\n"); if (!Init_Net()) goto out; printf_(gt("Downloading titles.txt ...")); printf("\n"); extern char *get_cc(); char *cc = get_cc(); char * dbl = ((strlen(CFG.db_language) == 2) ? VerifyLangCode(CFG.db_language) : ConvertLangTextToCode(CFG.db_language)); //if (strcmp(cc, "JA") ==0 || strcmp(cc, "KO") ==0) cc = "EN"; strcpy(url, CFG.titles_url); str_replace(url, "{CC}", cc, sizeof(url)); str_replace(url, "{DBL}", dbl, sizeof(url)); printf_("%s\n", url); file = downloadfile(url); if (file.data == NULL || file.size == 0) { printf_(gt("Error downloading updates...")); printf("\n"); sleep(3); return; } snprintf(D_S(fname),"%s/%s", USBLOADER_PATH, "titles.txt"); printf_(gt("Saving: %s"), fname); printf("\n"); f = fopen(fname, "wb"); if (!f) { printf_(gt("Error opening: %s"), fname); printf("\n"); } else { fwrite(file.data, 1, file.size, f); fclose(f); printf_(gt("Done.")); printf("\n\n"); printf_(gt("NOTE: loader restart is required\nfor the update to take effect.")); printf("\n\n"); } out: printf_(gt("Press any button...")); Wpad_WaitButtonsCommon(); SAFE_FREE(file.data); return; }