/* =============== HTTP_QueueDownload Called from the precache check to queue a download. Return value of Q_ERR_NOSYS will cause standard UDP downloading to be used instead. =============== */ qerror_t HTTP_QueueDownload(const char *path, dltype_t type) { size_t len; qboolean need_list; char temp[MAX_QPATH]; qerror_t ret; // no http server (or we got booted) if (!curl_multi || !cl_http_downloads->integer) return Q_ERR_NOSYS; // first download queued, so we want the mod filelist need_list = LIST_EMPTY(&cls.download.queue); ret = CL_QueueDownload(path, type); if (ret) { return ret; } if (!cl_http_filelists->integer) return Q_ERR_SUCCESS; if (need_list) { //grab the filelist len = Q_snprintf(temp, sizeof(temp), "%s.filelist", http_gamedir()); if (len < sizeof(temp)) CL_QueueDownload(temp, DL_LIST); //this is a nasty hack to let the server know what we're doing so admins don't //get confused by a ton of people stuck in CNCT state. it's assumed the server //is running r1q2 if we're even able to do http downloading so hopefully this //won't spew an error msg. CL_ClientCommand("download http\n"); } //special case for map file lists, i really wanted a server-push mechanism for this, but oh well len = strlen(path); if (len > 4 && !Q_stricmp(path + len - 4, ".bsp")) { len = Q_snprintf(temp, sizeof(temp), "%s/%s", http_gamedir(), path); if (len < sizeof(temp) - 5) { memcpy(temp + len - 4, ".filelist", 10); CL_QueueDownload(temp, DL_LIST); } } return Q_ERR_SUCCESS; }
bool Bootstrap_UpdateEXE(int exeSize) { const char* fn = _tempnam(NULL, "cup"); CL_QueueDownload(va(CONTENT_URL "/%s/bootstrap/CitizenFX.exe.xz", GetUpdateChannel()), fn, exeSize, true); UI_DoCreation(); if (!DL_RunLoop()) { UI_DoDestruction(); return false; } UI_DoDestruction(); // verify the signature on the EXE wchar_t wfn[512]; MultiByteToWideChar(CP_ACP, 0, fn, -1, wfn, 512); WINTRUST_FILE_INFO info; memset(&info, 0, sizeof(info)); info.cbStruct = sizeof(info); info.pcwszFilePath = wfn; info.hFile = NULL; info.pgKnownSubject = NULL; GUID WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2; WINTRUST_DATA data; memset(&data, 0, sizeof(data)); data.cbStruct = sizeof(data); data.pPolicyCallbackData = NULL; data.pSIPClientData = NULL; data.dwUIChoice = WTD_UI_NONE; data.fdwRevocationChecks = WTD_REVOKE_NONE; data.dwUnionChoice = WTD_CHOICE_FILE; data.dwStateAction = 0; data.hWVTStateData = NULL; data.pwszURLReference = NULL; data.dwUIContext = 0; data.pFile = &info; LONG status = WinVerifyTrust(NULL, &WVTPolicyGUID, &data); if (status != ERROR_SUCCESS) { //MessageBox(NULL, va(L"A trust chain error occurred in the downloaded rtcg.exe. The specific error code is 0x%08x.", status), L"O\x448\x438\x431\x43A\x430", MB_OK | MB_ICONSTOP); //return false; } wchar_t exePath[512]; GetModuleFileName(GetModuleHandle(NULL), exePath, sizeof(exePath) / 2); STARTUPINFO startupInfo; memset(&startupInfo, 0, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo); startupInfo.wShowWindow = SW_HIDE; startupInfo.dwFlags |= STARTF_USESHOWWINDOW; PROCESS_INFORMATION processInfo; CreateProcess(wfn, (LPWSTR)va(L"%s -bootstrap \"%s\"", wfn, exePath), NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo); return false; }
// Validate a path supplied by a filelist. static void check_and_queue_download(char *path) { size_t len; char *ext; dltype_t type; unsigned flags; int valid; len = strlen(path); if (len >= MAX_QPATH) return; ext = strrchr(path, '.'); if (!ext) return; ext++; if (!ext[0]) return; Q_strlwr(ext); if (!strcmp(ext, "pak") || !strcmp(ext, "pkz")) { Com_Printf("[HTTP] Filelist is requesting a .%s file '%s'\n", ext, path); type = DL_PAK; } else { type = DL_OTHER; if (!CL_CheckDownloadExtension(ext)) { Com_WPrintf("[HTTP] Illegal file type '%s' in filelist.\n", path); return; } } if (path[0] == '@') { if (type == DL_PAK) { Com_WPrintf("[HTTP] '@' prefix used on a pak file '%s' in filelist.\n", path); return; } flags = FS_PATH_GAME; path++; len--; } else if (type == DL_PAK) { //by definition paks are game-local flags = FS_PATH_GAME | FS_TYPE_REAL; } else { flags = 0; } len = FS_NormalizePath(path, path); if (len == 0) return; valid = FS_ValidatePath(path); if (valid == PATH_INVALID || !Q_ispath(path[0]) || !Q_ispath(path[len - 1]) || strstr(path, "..") || (type == DL_OTHER && !strchr(path, '/')) || (type == DL_PAK && strchr(path, '/'))) { Com_WPrintf("[HTTP] Illegal path '%s' in filelist.\n", path); return; } if (FS_FileExistsEx(path, flags)) return; if (valid == PATH_MIXED_CASE) Q_strlwr(path); if (CL_IgnoreDownload(path)) return; CL_QueueDownload(path, type); }