diff --git a/src/net.c b/src/net.c index 50516f0b..608b2584 100644 --- a/src/net.c +++ b/src/net.c @@ -226,6 +226,41 @@ const char* WinInetErrorString(void) } } +// Open an Internet session +static HINTERNET GetInternetSession(BOOL bRetry) +{ + int i; + char agent[64]; + BOOL r; + DWORD dwFlags; + HINTERNET hSession = NULL; + + PF_TYPE_DECL(WINAPI, BOOL, InternetGetConnectedState, (LPDWORD, DWORD)); + PF_TYPE_DECL(WINAPI, HINTERNET, InternetOpenA, (LPCSTR, DWORD, LPCSTR, LPCSTR, DWORD)); + PF_INIT_OR_OUT(InternetGetConnectedState, WinInet); + PF_INIT_OR_OUT(InternetOpenA, WinInet); + + for (i = 0; i <= WRITE_RETRIES; i++) { + r = pfInternetGetConnectedState(&dwFlags, 0); + if (r || !bRetry) + break; + Sleep(1000); + } + if (!r) { + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong... + SetLastError(ERROR_INTERNET_NOT_INITIALIZED); + uprintf("Network is unavailable: %s", WinInetErrorString()); + goto out; + } + static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", + rufus_version[0], rufus_version[1], rufus_version[2], + nWindowsVersion >> 4, nWindowsVersion & 0x0F, is_x64() ? "; WOW64" : ""); + hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + +out: + return hSession; +} + /* * Download a file or fill a buffer from an URL * Mostly taken from http://support.microsoft.com/kb/234913 @@ -236,24 +271,21 @@ const char* WinInetErrorString(void) */ static uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** buffer, HWND hProgressDialog) { - HWND hProgressBar = NULL; - BOOL r = FALSE; - DWORD dwFlags, dwSize, dwWritten, dwDownloaded; - HANDLE hFile = INVALID_HANDLE_VALUE; const char* accept_types[] = {"*/*\0", NULL}; const char* short_name; unsigned char buf[DOWNLOAD_BUFFER_SIZE]; - char agent[64], hostname[64], urlpath[128], strsize[32];; + char hostname[64], urlpath[128], strsize[32]; + HWND hProgressBar = NULL; + BOOL r = FALSE; + DWORD dwSize, dwWritten, dwDownloaded; + HANDLE hFile = INVALID_HANDLE_VALUE; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1}; uint64_t size = 0, total_size = 0; - size_t i; // Can't link with wininet.lib because of sideloading issues PF_TYPE_DECL(WINAPI, BOOL, InternetCrackUrlA, (LPCSTR, DWORD, DWORD, LPURL_COMPONENTSA)); - PF_TYPE_DECL(WINAPI, BOOL, InternetGetConnectedState, (LPDWORD, DWORD)); - PF_TYPE_DECL(WINAPI, HINTERNET, InternetOpenA, (LPCSTR, DWORD, LPCSTR, LPCSTR, DWORD)); PF_TYPE_DECL(WINAPI, HINTERNET, InternetConnectA, (HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD_PTR)); PF_TYPE_DECL(WINAPI, BOOL, InternetReadFile, (HINTERNET, LPVOID, DWORD, LPDWORD)); PF_TYPE_DECL(WINAPI, BOOL, InternetCloseHandle, (HINTERNET)); @@ -261,8 +293,6 @@ static uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** PF_TYPE_DECL(WINAPI, BOOL, HttpSendRequestA, (HINTERNET, LPCSTR, DWORD, LPVOID, DWORD)); PF_TYPE_DECL(WINAPI, BOOL, HttpQueryInfoA, (HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD)); PF_INIT_OR_OUT(InternetCrackUrlA, WinInet); - PF_INIT_OR_OUT(InternetGetConnectedState, WinInet); - PF_INIT_OR_OUT(InternetOpenA, WinInet); PF_INIT_OR_OUT(InternetConnectA, WinInet); PF_INIT_OR_OUT(InternetReadFile, WinInet); PF_INIT_OR_OUT(InternetCloseHandle, WinInet); @@ -283,6 +313,8 @@ static uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** } assert(url != NULL); + if (buffer != NULL) + *buffer = NULL; short_name = (file != NULL) ? PathFindFileNameU(file) : PathFindFileNameU(url); @@ -298,20 +330,7 @@ static uint64_t DownloadToFileOrBuffer(const char* url, const char* file, BYTE** } hostname[sizeof(hostname)-1] = 0; - // Open an Internet session - for (i=5; (i>0) && (!pfInternetGetConnectedState(&dwFlags, 0)); i--) { - Sleep(1000); - } - if (i <= 0) { - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384702.aspx is wrong... - SetLastError(ERROR_INTERNET_NOT_INITIALIZED); - uprintf("Network is unavailable: %s", WinInetErrorString()); - goto out; - } - static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", - rufus_version[0], rufus_version[1], rufus_version[2], - nWindowsVersion>>4, nWindowsVersion&0x0F, is_x64()?"; WOW64":""); - hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + hSession = GetInternetSession(TRUE); if (hSession == NULL) { uprintf("Could not open Internet session: %s", WinInetErrorString()); goto out; @@ -544,10 +563,10 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) static const char* archname[] = {"win_x86", "win_x64", "win_arm", "win_arm64", "win_none"}; static const char* channel[] = {"release", "beta", "test"}; // release channel const char* accept_types[] = {"*/*\0", NULL}; - DWORD dwFlags, dwSize, dwDownloaded, dwTotalSize, dwStatus; - BYTE *sig = NULL; char* buf = NULL; char agent[64], hostname[64], urlpath[128], sigpath[256]; + DWORD dwSize, dwDownloaded, dwTotalSize, dwStatus; + BYTE *sig = NULL; OSVERSIONINFOA os_version = {sizeof(OSVERSIONINFOA), 0, 0, 0, 0, ""}; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; URL_COMPONENTSA UrlParts = {sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, @@ -558,8 +577,6 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) // Can't link with wininet.lib because of sideloading issues PF_TYPE_DECL(WINAPI, BOOL, InternetCrackUrlA, (LPCSTR, DWORD, DWORD, LPURL_COMPONENTSA)); - PF_TYPE_DECL(WINAPI, BOOL, InternetGetConnectedState, (LPDWORD, DWORD)); - PF_TYPE_DECL(WINAPI, HINTERNET, InternetOpenA, (LPCSTR, DWORD, LPCSTR, LPCSTR, DWORD)); PF_TYPE_DECL(WINAPI, HINTERNET, InternetConnectA, (HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD_PTR)); PF_TYPE_DECL(WINAPI, BOOL, InternetReadFile, (HINTERNET, LPVOID, DWORD, LPDWORD)); PF_TYPE_DECL(WINAPI, BOOL, InternetCloseHandle, (HINTERNET)); @@ -567,8 +584,6 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) PF_TYPE_DECL(WINAPI, BOOL, HttpSendRequestA, (HINTERNET, LPCSTR, DWORD, LPVOID, DWORD)); PF_TYPE_DECL(WINAPI, BOOL, HttpQueryInfoA, (HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD)); PF_INIT_OR_OUT(InternetCrackUrlA, WinInet); - PF_INIT_OR_OUT(InternetGetConnectedState, WinInet); - PF_INIT_OR_OUT(InternetOpenA, WinInet); PF_INIT_OR_OUT(InternetConnectA, WinInet); PF_INIT_OR_OUT(InternetReadFile, WinInet); PF_INIT_OR_OUT(InternetCloseHandle, WinInet); @@ -619,14 +634,14 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) goto out; } - if ((!pfInternetCrackUrlA(server_url, (DWORD)safe_strlen(server_url), 0, &UrlParts)) || (!pfInternetGetConnectedState(&dwFlags, 0))) + if (!pfInternetCrackUrlA(server_url, (DWORD)safe_strlen(server_url), 0, &UrlParts)) goto out; hostname[sizeof(hostname)-1] = 0; static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", rufus_version[0], rufus_version[1], rufus_version[2], nWindowsVersion >> 4, nWindowsVersion & 0x0F, is_x64() ? "; WOW64" : ""); - hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); + hSession = GetInternetSession(FALSE); if (hSession == NULL) goto out; hConnection = pfInternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); @@ -731,10 +746,10 @@ static DWORD WINAPI CheckForUpdatesThread(LPVOID param) static_sprintf(sigpath, "%s/%s.sig", server_url, urlpath); dwDownloaded = (DWORD)DownloadToFileOrBuffer(sigpath, NULL, &sig, NULL); if ((dwDownloaded != RSA_SIGNATURE_SIZE) || (!ValidateOpensslSignature(buf, dwTotalSize, sig, dwDownloaded))) { - uprintf("FATAL: Version signature is invalid!"); + uprintf("FATAL: Version signature is invalid ✗"); goto out; } - vuprintf("Version signature is valid"); + vuprintf("Version signature is valid ✓"); status++; parse_update(buf, dwTotalSize + 1); @@ -809,7 +824,7 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) { char cmdline[512], locale_str[1024], iso_name[128], pipe[64] = "\\\\.\\pipe\\"; char powershell_path[MAX_PATH], icon_path[MAX_PATH] = "", script_path[MAX_PATH] = ""; - char *p, *url = NULL; + char *p, *url = NULL, sig_url[128]; BYTE *sig = NULL; HANDLE hFile, hPipe; DWORD i, dwSize, dwAvail, dwPipeSize = 4096; @@ -833,10 +848,11 @@ static DWORD WINAPI DownloadISOThread(LPVOID param) #else // If we don't have the script, download it if (fido_len == 0) { - fido_len = (DWORD)DownloadToFileOrBuffer(FIDO_URL, NULL, &fido_script, hMainDialog); + fido_len = (DWORD)DownloadToFileOrBuffer(fido_url, NULL, &fido_script, hMainDialog); if (fido_len == 0) goto out; - dwSize = (DWORD)DownloadToFileOrBuffer(FIDO_URL ".sig", NULL, &sig, NULL); + static_sprintf(sig_url, "%s.sig", fido_url); + dwSize = (DWORD)DownloadToFileOrBuffer(sig_url, NULL, &sig, NULL); if ((dwSize != RSA_SIGNATURE_SIZE) || (!ValidateOpensslSignature(fido_script, fido_len, sig, dwSize))) { uprintf("FATAL: Signature is invalid ✗"); free(sig); @@ -974,91 +990,65 @@ BOOL DownloadISO() return TRUE; } -BOOL IsDownloadable(char* url) +BOOL IsDownloadable(const char* url) { - DWORD dwFlags, dwSize, dwTotalSize = 0; + DWORD dwSize, dwTotalSize = 0; const char* accept_types[] = { "*/*\0", NULL }; - char agent[64], hostname[64], urlpath[128]; + char hostname[64], urlpath[128]; HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; URL_COMPONENTSA UrlParts = { sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1 }; PF_TYPE_DECL(WINAPI, BOOL, InternetCrackUrlA, (LPCSTR, DWORD, DWORD, LPURL_COMPONENTSA)); - PF_TYPE_DECL(WINAPI, BOOL, InternetGetConnectedState, (LPDWORD, DWORD)); - PF_TYPE_DECL(WINAPI, HINTERNET, InternetOpenA, (LPCSTR, DWORD, LPCSTR, LPCSTR, DWORD)); PF_TYPE_DECL(WINAPI, HINTERNET, InternetConnectA, (HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD_PTR)); PF_TYPE_DECL(WINAPI, BOOL, InternetCloseHandle, (HINTERNET)); PF_TYPE_DECL(WINAPI, HINTERNET, HttpOpenRequestA, (HINTERNET, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPCSTR*, DWORD, DWORD_PTR)); PF_TYPE_DECL(WINAPI, BOOL, HttpSendRequestA, (HINTERNET, LPCSTR, DWORD, LPVOID, DWORD)); PF_TYPE_DECL(WINAPI, BOOL, HttpQueryInfoA, (HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD)); PF_INIT_OR_OUT(InternetCrackUrlA, WinInet); - PF_INIT_OR_OUT(InternetGetConnectedState, WinInet); - PF_INIT_OR_OUT(InternetOpenA, WinInet); PF_INIT_OR_OUT(InternetConnectA, WinInet); PF_INIT_OR_OUT(InternetCloseHandle, WinInet); PF_INIT_OR_OUT(HttpOpenRequestA, WinInet); PF_INIT_OR_OUT(HttpSendRequestA, WinInet); PF_INIT_OR_OUT(HttpQueryInfoA, WinInet); + if (url == NULL) + return FALSE; + FormatStatus = 0; DownloadStatus = 404; - assert(url != NULL); - if ((!pfInternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) - || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) { - uprintf("Unable to decode URL: %s", WinInetErrorString()); + || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) goto out; - } hostname[sizeof(hostname) - 1] = 0; // Open an Internet session - if (!pfInternetGetConnectedState(&dwFlags, 0)) { - SetLastError(ERROR_INTERNET_NOT_INITIALIZED); - uprintf("Network is unavailable: %s", WinInetErrorString()); + hSession = GetInternetSession(FALSE); + if (hSession == NULL) goto out; - } - - static_sprintf(agent, APPLICATION_NAME "/%d.%d.%d (Windows NT %d.%d%s)", - rufus_version[0], rufus_version[1], rufus_version[2], - nWindowsVersion >> 4, nWindowsVersion & 0x0F, is_x64() ? "; WOW64" : ""); - hSession = pfInternetOpenA(agent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); - if (hSession == NULL) { - uprintf("Could not open Internet session: %s", WinInetErrorString()); - goto out; - } hConnection = pfInternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); - if (hConnection == NULL) { - uprintf("Could not connect to server %s:%d: %s", UrlParts.lpszHostName, UrlParts.nPort, WinInetErrorString()); + if (hConnection == NULL) goto out; - } hRequest = pfHttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types, INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_HYPERLINK | ((UrlParts.nScheme == INTERNET_SCHEME_HTTPS) ? INTERNET_FLAG_SECURE : 0), (DWORD_PTR)NULL); - if (hRequest == NULL) { - uprintf("Could not open URL %s: %s", url, WinInetErrorString()); + if (hRequest == NULL) goto out; - } - if (!pfHttpSendRequestA(hRequest, NULL, 0, NULL, 0)) { - uprintf("Unable to send request: %s", WinInetErrorString()); + if (!pfHttpSendRequestA(hRequest, NULL, 0, NULL, 0)) goto out; - } // Get the file size dwSize = sizeof(DownloadStatus); pfHttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL); - if (DownloadStatus != 200) { - error_code = ERROR_INTERNET_ITEM_NOT_FOUND; - uprintf("Unable to access file: %d", DownloadStatus); + if (DownloadStatus != 200) goto out; - } dwSize = sizeof(dwTotalSize); - if (!pfHttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL)) - uprintf("Unable to retrieve file length: %s", WinInetErrorString()); + pfHttpQueryInfoA(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwTotalSize, &dwSize, NULL); out: if (hRequest) @@ -1070,3 +1060,74 @@ out: return (dwTotalSize > 0); } + +// Resolve an HTTP 301/302 redirect (for a *SINGLE* level) +// If no redirect is in effect, or if there is an error, the original URL is returned +const char* ResolveRedirect(const char* url) +{ + static char ret_url[128]; + const char* accept_types[] = { "*/*\0", NULL }; + char hostname[64], urlpath[128]; + BOOL r = FALSE; + DWORD dwSize; + HINTERNET hSession = NULL, hConnection = NULL, hRequest = NULL; + URL_COMPONENTSA UrlParts = { sizeof(URL_COMPONENTSA), NULL, 1, (INTERNET_SCHEME)0, + hostname, sizeof(hostname), 0, NULL, 1, urlpath, sizeof(urlpath), NULL, 1 }; + + PF_TYPE_DECL(WINAPI, BOOL, InternetCrackUrlA, (LPCSTR, DWORD, DWORD, LPURL_COMPONENTSA)); + PF_TYPE_DECL(WINAPI, HINTERNET, InternetConnectA, (HINTERNET, LPCSTR, INTERNET_PORT, LPCSTR, LPCSTR, DWORD, DWORD, DWORD_PTR)); + PF_TYPE_DECL(WINAPI, BOOL, InternetReadFile, (HINTERNET, LPVOID, DWORD, LPDWORD)); + PF_TYPE_DECL(WINAPI, BOOL, InternetCloseHandle, (HINTERNET)); + PF_TYPE_DECL(WINAPI, HINTERNET, HttpOpenRequestA, (HINTERNET, LPCSTR, LPCSTR, LPCSTR, LPCSTR, LPCSTR*, DWORD, DWORD_PTR)); + PF_TYPE_DECL(WINAPI, BOOL, HttpSendRequestA, (HINTERNET, LPCSTR, DWORD, LPVOID, DWORD)); + PF_TYPE_DECL(WINAPI, BOOL, HttpQueryInfoA, (HINTERNET, DWORD, LPVOID, LPDWORD, LPDWORD)); + PF_INIT_OR_OUT(InternetCrackUrlA, WinInet); + PF_INIT_OR_OUT(InternetConnectA, WinInet); + PF_INIT_OR_OUT(InternetReadFile, WinInet); + PF_INIT_OR_OUT(InternetCloseHandle, WinInet); + PF_INIT_OR_OUT(HttpOpenRequestA, WinInet); + PF_INIT_OR_OUT(HttpSendRequestA, WinInet); + PF_INIT_OR_OUT(HttpQueryInfoA, WinInet); + + if (url == NULL) + return NULL; + + if ((!pfInternetCrackUrlA(url, (DWORD)safe_strlen(url), 0, &UrlParts)) + || (UrlParts.lpszHostName == NULL) || (UrlParts.lpszUrlPath == NULL)) + goto out; + hostname[sizeof(hostname) - 1] = 0; + + hSession = GetInternetSession(FALSE); + if (hSession == NULL) + goto out; + + hConnection = pfInternetConnectA(hSession, UrlParts.lpszHostName, UrlParts.nPort, NULL, NULL, INTERNET_SERVICE_HTTP, 0, (DWORD_PTR)NULL); + if (hConnection == NULL) + goto out; + + hRequest = pfHttpOpenRequestA(hConnection, "GET", UrlParts.lpszUrlPath, NULL, NULL, accept_types, + INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP | INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTPS | INTERNET_FLAG_NO_AUTO_REDIRECT | + INTERNET_FLAG_NO_COOKIES | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE | INTERNET_FLAG_HYPERLINK | + ((UrlParts.nScheme == INTERNET_SCHEME_HTTPS) ? INTERNET_FLAG_SECURE : 0), (DWORD_PTR)NULL); + if (hRequest == NULL) + goto out; + + if (!pfHttpSendRequestA(hRequest, NULL, 0, NULL, 0)) + goto out; + + DownloadStatus = 404; + dwSize = sizeof(DownloadStatus); + pfHttpQueryInfoA(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&DownloadStatus, &dwSize, NULL); + switch (DownloadStatus) { + case 301: + case 302: + dwSize = sizeof(ret_url); + r = (pfHttpQueryInfoA(hRequest, HTTP_QUERY_LOCATION, (LPVOID)ret_url, &dwSize, NULL) && (dwSize > 0)); + break; + default: + break; + } + +out: + return r ? ret_url : url; +} diff --git a/src/rufus.c b/src/rufus.c index 0581abdb..ea62fc99 100755 --- a/src/rufus.c +++ b/src/rufus.c @@ -116,7 +116,7 @@ char embedded_sl_version_str[2][12] = { "?.??", "?.??" }; char embedded_sl_version_ext[2][32]; char ClusterSizeLabel[MAX_CLUSTER_SIZES][64]; char msgbox[1024], msgbox_title[32], *ini_file = NULL, *image_path = NULL, *short_image_path; -char image_option_txt[128]; +char image_option_txt[128], fido_url[128]; StrArray DriveID, DriveLabel, DriveHub, BlockingProcess, ImageList; // Number of steps for each FS for FCC_STRUCTURE_PROGRESS const int nb_steps[FS_MAX] = { 5, 5, 12, 1, 10 }; @@ -1886,7 +1886,7 @@ static INT_PTR CALLBACK MainCallback(HWND hDlg, UINT message, WPARAM wParam, LPA case WM_COMMAND: #ifdef RUFUS_TEST if (LOWORD(wParam) == IDC_TEST) { - uprintf("%s is %s", FIDO_URL, IsDownloadable(FIDO_URL) ? "available" : "NOT available"); + uprintf("%s -> %s", FIDO_BASE, ResolveRedirect(FIDO_BASE)); break; } #endif diff --git a/src/rufus.h b/src/rufus.h index 1f2c1a0e..4fce017b 100644 --- a/src/rufus.h +++ b/src/rufus.h @@ -103,8 +103,8 @@ #endif #define DOWNLOAD_URL RUFUS_URL "/downloads" #define FILES_URL RUFUS_URL "/files" -// TODO: Resolve https://github.com/pbatard/Fido/releases/latest and use that as our base -#define FIDO_URL "https://github.com/pbatard/Fido/releases/download/v1.0/Fido.ps1" +#define FIDO_BASE "https://github.com/pbatard/Fido/releases/latest" +#define FIDO_NAME "Fido.ps1" #define SECURE_BOOT_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#Why_do_I_need_to_disable_Secure_Boot_to_use_UEFINTFS" #define WPPRECORDER_MORE_INFO_URL "https://github.com/pbatard/rufus/wiki/FAQ#BSODs_with_Windows_To_Go_drives_created_from_Windows_10_1809_ISOs" #define SEVENZIP_URL "https://www.7-zip.org" @@ -459,7 +459,7 @@ extern int fs, bt, pt, tt; extern unsigned long syslinux_ldlinux_len[2]; extern char WindowsVersionStr[128], ubuffer[UBUFFER_SIZE], embedded_sl_version_str[2][12]; extern char szFolderPath[MAX_PATH], app_dir[MAX_PATH], temp_dir[MAX_PATH], system_dir[MAX_PATH]; -extern char sysnative_dir[MAX_PATH]; +extern char sysnative_dir[MAX_PATH], fido_url[128]; extern char* image_path; /* @@ -529,7 +529,8 @@ extern BOOL SetUpdateCheck(void); extern BOOL CheckForUpdates(BOOL force); extern void DownloadNewVersion(void); extern BOOL DownloadISO(void); -extern BOOL IsDownloadable(char* url); +extern BOOL IsDownloadable(const char* url); +extern const char* ResolveRedirect(const char* url); extern BOOL IsShown(HWND hDlg); extern char* get_token_data_file_indexed(const char* token, const char* filename, int index); #define get_token_data_file(token, filename) get_token_data_file_indexed(token, filename, 1) diff --git a/src/rufus.rc b/src/rufus.rc index e60f42a0..2f46dc8e 100644 --- a/src/rufus.rc +++ b/src/rufus.rc @@ -33,7 +33,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL IDD_DIALOG DIALOGEX 12, 12, 232, 326 STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_MINIMIZEBOX | WS_POPUP | WS_CAPTION | WS_SYSMENU EXSTYLE WS_EX_ACCEPTFILES -CAPTION "Rufus 3.5.1450" +CAPTION "Rufus 3.5.1451" FONT 9, "Segoe UI Symbol", 400, 0, 0x0 BEGIN LTEXT "Drive Properties",IDS_DRIVE_PROPERTIES_TXT,8,6,53,12,NOT WS_GROUP @@ -394,8 +394,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 3,5,1450,0 - PRODUCTVERSION 3,5,1450,0 + FILEVERSION 3,5,1451,0 + PRODUCTVERSION 3,5,1451,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -413,13 +413,13 @@ BEGIN VALUE "Comments", "https://akeo.ie" VALUE "CompanyName", "Akeo Consulting" VALUE "FileDescription", "Rufus" - VALUE "FileVersion", "3.5.1450" + VALUE "FileVersion", "3.5.1451" VALUE "InternalName", "Rufus" VALUE "LegalCopyright", "© 2011-2019 Pete Batard (GPL v3)" VALUE "LegalTrademarks", "https://www.gnu.org/copyleft/gpl.html" VALUE "OriginalFilename", "rufus-3.5.exe" VALUE "ProductName", "Rufus" - VALUE "ProductVersion", "3.5.1450" + VALUE "ProductVersion", "3.5.1451" END END BLOCK "VarFileInfo" diff --git a/src/stdlg.c b/src/stdlg.c index f9127584..6ecf9d08 100644 --- a/src/stdlg.c +++ b/src/stdlg.c @@ -1542,13 +1542,31 @@ BOOL SetUpdateCheck(void) ((ReadSetting32(SETTING_UPDATE_INTERVAL) == -1) && enable_updates) ) WriteSetting32(SETTING_UPDATE_INTERVAL, 86400); } - // Also detect if we can use FIDO, which depends on: + // Also detect if we can use Fido, which depends on: // - Update check being enabled // - URL for the script being reachable if (ReadSetting32(SETTING_UPDATE_INTERVAL) > 0) { - uprintf("Checking for %s...", FIDO_URL); - enable_fido = IsDownloadable(FIDO_URL); + char *p, url[128]; + // Obviously, we could fetch https://api.github.com/repos/pbatard/Fido/releases/latest + // and then parse 'browser_download_url' in the JSON data to get the direct link we + // want. But that would force us to download an extra 5 KB of data, which we *really* + // don't want to do when we need a superfast availability check. + // Therefore, since we don't expect GitHub to change their scheme anytime soon, we + // just hack the redirected URL we got back to replace '/tag/' with '/download/'... + static_sprintf(url, "%s/%s", ResolveRedirect(FIDO_BASE), FIDO_NAME); + p = strstr(url, "/tag/"); + if (p != NULL) { + *p = 0; + strcpy(fido_url, url); + strcat(fido_url, "/download/"); + strcat(fido_url, &p[5]); + } else { + strcpy(fido_url, url); + } + enable_fido = IsDownloadable(fido_url); } + if (!enable_fido) + uprintf("Note: ISO download feature will be disabled"); return TRUE; }