# HG changeset patch # User Tero Marttila # Date 1216740546 -10800 # Node ID fa96e29d7187d0f3c6b74beb1dbc34d2bc00f5e6 # Parent aa617a8b4f34d81fc7c3753cecf8c0db401b7fa1 error messages, typos/omissions, and it can now actually download the .tar into cache/-.tar diff -r aa617a8b4f34 -r fa96e29d7187 .hgignore --- a/.hgignore Sat Jul 19 01:38:52 2008 +0300 +++ b/.hgignore Tue Jul 22 18:29:06 2008 +0300 @@ -1,7 +1,7 @@ syntax: regexp ^objs/ -^bin/ +^bin(-server)?/ ^Makefile(.am)?$ \.swp$ ^src/rev\.cpp$ diff -r aa617a8b4f34 -r fa96e29d7187 src/fileio.cpp --- a/src/fileio.cpp Sat Jul 19 01:38:52 2008 +0300 +++ b/src/fileio.cpp Tue Jul 22 18:29:06 2008 +0300 @@ -216,7 +216,8 @@ "scenario" PATHSEP "heightmap" PATHSEP, "gm" PATHSEP, "data" PATHSEP, - "lang" PATHSEP + "lang" PATHSEP, + "cache" PATHSEP }; const char *_searchpaths[NUM_SEARCHPATHS]; diff -r aa617a8b4f34 -r fa96e29d7187 src/fileio.h --- a/src/fileio.h Sat Jul 19 01:38:52 2008 +0300 +++ b/src/fileio.h Tue Jul 22 18:29:06 2008 +0300 @@ -32,6 +32,7 @@ GM_DIR, ///< Subdirectory for all music DATA_DIR, ///< Subdirectory for all data (GRFs, sample.cat, intro game) LANG_DIR, ///< Subdirectory for all translation files + CACHE_DIR, ///< Subdirectory for all cache data (not user-visible) NUM_SUBDIRS, ///< Number of subdirectories NO_DIRECTORY, ///< A path without any base directory }; diff -r aa617a8b4f34 -r fa96e29d7187 src/lang/english.txt --- a/src/lang/english.txt Sat Jul 19 01:38:52 2008 +0300 +++ b/src/lang/english.txt Tue Jul 22 18:29:06 2008 +0300 @@ -3191,9 +3191,12 @@ STR_NEWGRF_RESCAN_FILES_TIP :{BLACK}Update the list of available NewGRF files STR_NEWGRF_DUPLICATE_GRFID :{WHITE}Cannot add file: duplicate GRF ID +STR_NEWGRF_DOWNLOAD_CAPTION :{WHITE}Download NewGRF files STR_NEWGRF_DOWNLOAD_LIST_TIP :{BLACK}A list of the NewGRF files that are missing. STR_NEWGRF_CHECK_AVAILABLE :{BLACK}Check Available STR_NEWGRF_DOWNLOAD_AVAILABLE :{BLACK}Download Available +STR_NEWGRF_DOWNLOAD_CHECK_FAILED :{WHITE}Checking for available NewGRFs failed +STR_NEWGRF_DOWNLOAD_CHECK_NONE :{WHITE}No NewGRFs available for download STR_NEWGRF_NOT_FOUND :{RED}Matching file not found STR_NEWGRF_DISABLED :{RED}Disabled diff -r aa617a8b4f34 -r fa96e29d7187 src/network/newgrf_download.cpp --- a/src/network/newgrf_download.cpp Sat Jul 19 01:38:52 2008 +0300 +++ b/src/network/newgrf_download.cpp Tue Jul 22 18:29:06 2008 +0300 @@ -20,6 +20,7 @@ #include "../gfx_func.h" #include "../querystring_gui.h" #include "../sortlist_type.h" +#include "../fileio.h" #include "../rev.h" // XXX: ... @@ -81,7 +82,7 @@ /** Ask the master database about the availablity of the given NewGRFs, and update * the GRFConfigs that are avilable to GCS_AVAILABLE * @param config pointer to a linked-list of grfconfig's needed */ -static void CheckAvailableNewGRFs(GRFConfig *list) +static int CheckAvailableNewGRFs(GRFConfig *list) { GRFConfig *c; int i; @@ -93,6 +94,8 @@ long http_code; char *buf_ptr; CURLcode err; + int ret = -1; + int found = 0; // initialize to a safe state for error handling curl = write_ctx.buf = NULL; @@ -153,7 +156,7 @@ curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, XXX) */ || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1))) // no progress meter on stdout, thx - || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf))) // human-readable error messages + || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf))) // XXX: human-readable error messages || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_URL, api_url))) // the URL to retrieve || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_USERAGENT, useragent))) // the User-agent to use || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query_buf))) // the POST data @@ -231,6 +234,9 @@ c->filename = url; c->status = GCS_AVAILABLE; + + found++; + break; } } @@ -243,6 +249,9 @@ // move on to the next line buf_ptr = nl + 1; } + + // return number of NewGRFs found, defaults to -1 for errors + ret = found; error : // cleanup @@ -250,6 +259,117 @@ if (curl) curl_easy_cleanup(curl); + + // return as defined by ret + return ret; +} + +/** Download the NewGRFs that are listed as GCS_AVAILABLE + * @param config pointer to a linked-list of grfconfig's to be downloaded */ +static int DownloadAvailableNewGRFs(GRFConfig *list) +{ + GRFConfig *c; + CURL *curl = NULL; + CURLcode err; + FILE *fh = NULL; + char md5buf[64], filename[256], useragent[512]; + long http_code; + int ret = -1; + + // set up curl + if ((err = do_init_curl())) { + DEBUG(grfdl, 0, "curl_global_init failed: %s", curl_easy_strerror(err)); + goto error; + } + + // allocate a new curl_easy + if ((curl = curl_easy_init()) == NULL) { + DEBUG(grfdl, 0, "curl_easy_init failed"); + goto error; + } + + // our useragent + assert(snprintf(useragent, sizeof(useragent), NETWORK_HTTP_USER_AGENT, _openttd_revision) < 512); + + // let's set some options... + if ( + (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_VERBOSE, 1))) // XXX: tie this in with OpenTTD's debug stuff + /* + curl_easy_setopt(curl, CURLOPT_DEBUGFUNCTION, XXX) + */ + || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1))) // no progress meter on stdout, thx +// || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_ERRORBUFFER, curl_errbuf))) // human-readable error messages + + || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_USERAGENT, useragent))) // the User-agent to use + +/* + || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_POSTFIELDS, query_buf))) // the POST data + || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &check_available_write_cb))) +*/ + ) { + DEBUG(grfdl, 0, "curl_easy_setopt failed: %s", curl_easy_strerror(err)); + goto error; + } + + // then start looping through the NewGRFs to download + for (c = list; c != NULL; c = c->next) { + // skip the ones that are not available + if (c->status != GCS_AVAILABLE) + continue; + + // format the md5sum + md5sumToString(md5buf, lastof(md5buf), c->md5sum); + + // snprintf the entry into the query buffer + assert(snprintf(filename, sizeof(filename), "%08X-%32s.tar", BSWAP32(c->grfid), md5buf) < 256); + + // open the file + if ((fh = FioFOpenFile(filename, "wb", CACHE_DIR)) == NULL) { + DEBUG(grfdl, 0, "Opening local GRF file failed: %s", filename); + goto error; + } + + // set up curl + if ( + (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_URL, c->filename))) // the URL to retrieve + || (CURLE_OK != (err = curl_easy_setopt(curl, CURLOPT_WRITEDATA, fh))) // XXX: need to fwrite() ourself + ) { + DEBUG(grfdl, 0, "curl_easy_setopt failed: %s", curl_easy_strerror(err)); + goto error; + } + + // XXX: currently this freezes the UI.. + if ((err = curl_easy_perform(curl))) { + DEBUG(grfdl, 0, "the curl request failed: %s", curl_easy_strerror(err)); + goto error; + } + + // get the HTTP return code + if ((err = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code))) { + DEBUG(grfdl, 0, "curl_easy_getinfo failed: %s", curl_easy_strerror(err)); + goto error; + } + + if (http_code != 200) { + DEBUG(grfdl, 0, "Bad HTTP response code: %d", http_code); + goto error; + } + + // OK, great + c->status = GCS_UNKNOWN; + } + + // success + ret = 0; + +error: + if (fh) + fclose(fh); + + if (curl) + curl_easy_cleanup(curl); + + return ret; } // XXX: copy-pasted from newgrf_gui.cpp @@ -473,16 +593,42 @@ virtual void OnClick(Point pt, int widget) { + int found; + switch (widget) { case DNGRFS_CHECK_AVAILABLE: - CheckAvailableNewGRFs(this->list); + // do the HTTP request etc. + found = CheckAvailableNewGRFs(this->list); + + if (found < 0) { + // failed + ShowErrorMessage(INVALID_STRING_ID, STR_NEWGRF_DOWNLOAD_CHECK_FAILED, 0, 0); + + } else if (found == 0) { + // no NewGRFs found + ShowErrorMessage(INVALID_STRING_ID, STR_NEWGRF_DOWNLOAD_CHECK_NONE, 0, 0); + + } else { + // success, flip the button enabled states + this->SetWidgetDisabledState(DNGRFS_CHECK_AVAILABLE, 1); + this->SetWidgetDisabledState(DNGRFS_DOWNLOAD_AVAILABLE, 0); + + // redraw with new status + this->SetDirty(); + } - this->SetDirty(); break; case DNGRFS_DOWNLOAD_AVAILABLE: - // XXX: implement + // do a bunch of HTTP requests + found = DownloadAvailableNewGRFs(this->list); + + // disable the button, not useful anymore + this->SetWidgetDisabledState(DNGRFS_DOWNLOAD_AVAILABLE, 1); + + // redraw with new status + this->SetDirty(); break; @@ -520,7 +666,7 @@ /* Widget definition of the download newgrfs window */ static const Widget _newgrf_download_widgets[] = { { WWT_CLOSEBOX, RESIZE_NONE, 10, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW }, // DNGRFS_CLOSEBOX -{ WWT_CAPTION, RESIZE_RIGHT, 10, 11, 299, 0, 13, STR_NEWGRF_SETTINGS_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS }, // DNGRFS_CAPTION +{ WWT_CAPTION, RESIZE_RIGHT, 10, 11, 299, 0, 13, STR_NEWGRF_DOWNLOAD_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS }, // DNGRFS_CAPTION { WWT_PANEL, RESIZE_RIGHT, 10, 0, 299, 14, 29, STR_NULL, STR_NULL }, // DNGRFS_BACKGROUND /*