private bool SingleDownload(string url, string dst) { try { using (HttpFileDownloader dl = new HttpFileDownloader()) { dl.Download(url, dst, null); } } catch { return(false); } return(true); }
public static List <LogInfo> WebGet(EngineState s, CodeCommand cmd) { // WebGet,<URL>,<DestPath>[<HashType>=<HashDigest>][,TimeOut=<Int>][,Referer=<URL>][,UserAgent=<Agent>][,NOERR] List <LogInfo> logs = new List <LogInfo>(); CodeInfo_WebGet info = cmd.Info.Cast <CodeInfo_WebGet>(); string url = StringEscaper.Preprocess(s, info.URL); string destPath = StringEscaper.Preprocess(s, info.DestPath); int timeOut = 10; if (info.TimeOut != null) { string timeOutStr = StringEscaper.Preprocess(s, info.TimeOut); if (!NumberHelper.ParseInt32(timeOutStr, out timeOut)) { return(LogInfo.LogErrorMessage(logs, $"TimeOut [{timeOutStr}] is not a valid positive integer")); } if (timeOut <= 0) { return(LogInfo.LogErrorMessage(logs, $"TimeOut [{timeOutStr}] is not a valid positive integer")); } } string refererUrl = null; if (info.Referer != null) { refererUrl = StringEscaper.Preprocess(s, info.Referer); } // Check PathSecurity in destPath if (!StringEscaper.PathSecurityCheck(destPath, out string pathErrorMsg)) { return(LogInfo.LogErrorMessage(logs, pathErrorMsg)); } Uri uri = new Uri(url); string destFile; if (Directory.Exists(destPath)) { destFile = Path.Combine(destPath, Path.GetFileName(uri.LocalPath)); } else // downloadTo is file { if (File.Exists(destPath)) { if (cmd.Type == CodeType.WebGetIfNotExist) { logs.Add(new LogInfo(LogState.Ignore, $"File [{destPath}] already exists")); return(logs); } logs.Add(new LogInfo(LogState.Overwrite, $"File [{destPath}] will be overwritten")); } else { Directory.CreateDirectory(FileHelper.GetDirNameEx(destPath)); } destFile = destPath; } string destFileExt = Path.GetExtension(destFile); s.MainViewModel.SetBuildCommandProgress("WebGet Progress"); try { // Set User-Agent to use // (1) Use Command's custom User-Agent // (2) Use EngineState's custom User-Agent // (3) Use PEBakery's default User-Agent string userAgent = null; if (info.UserAgent != null) { userAgent = info.UserAgent; } else { userAgent = s.CustomUserAgent; } if (info.HashType == HashHelper.HashType.None) { // Standard WebGet string tempPath = FileHelper.GetTempFile(destFileExt); HttpFileDownloader downloader = new HttpFileDownloader(s.MainViewModel, timeOut, userAgent, refererUrl); HttpFileDownloader.Report report; try { CancellationTokenSource ct = new CancellationTokenSource(); s.CancelWebGet = ct; Task <HttpFileDownloader.Report> task = downloader.Download(url, tempPath, ct.Token); task.Wait(ct.Token); report = task.Result; } catch (Exception e) { report = new HttpFileDownloader.Report(false, 0, Logger.LogExceptionMessage(e)); } finally { s.CancelWebGet = null; } int statusCode = report.StatusCode; if (report.Result) { FileHelper.FileReplaceEx(tempPath, destFile); logs.Add(new LogInfo(LogState.Success, $"[{destFile}] downloaded from [{url}]")); } else { LogState state = info.NoErrFlag ? LogState.Warning : LogState.Error; logs.Add(new LogInfo(state, $"Error occured while downloading [{url}]")); logs.Add(new LogInfo(LogState.Info, report.ErrorMsg)); if (statusCode == 0) { logs.Add(new LogInfo(LogState.Info, "Request failed, no response received.")); } else { logs.Add(new LogInfo(LogState.Info, $"Response returned HTTP status code [{statusCode}]")); } } // PEBakery extension -> Report exit code via #r if (!s.CompatDisableExtendedSectionParams) { s.ReturnValue = statusCode.ToString(); if (statusCode < 100) { logs.Add(new LogInfo(LogState.Success, $"Returned [{statusCode}] into [#r]")); } else { logs.Add(new LogInfo(LogState.Success, $"Returned HTTP status code [{statusCode}] to [#r]")); } } } else { // Validate downloaded file with hash Debug.Assert(info.HashDigest != null); string tempPath = FileHelper.GetTempFile(destFileExt); HttpFileDownloader downloader = new HttpFileDownloader(s.MainViewModel, timeOut, userAgent, refererUrl); HttpFileDownloader.Report report; try { CancellationTokenSource ct = new CancellationTokenSource(); s.CancelWebGet = ct; Task <HttpFileDownloader.Report> task = downloader.Download(url, tempPath, ct.Token); task.Wait(ct.Token); report = task.Result; } catch (Exception e) { report = new HttpFileDownloader.Report(false, 0, Logger.LogExceptionMessage(e)); } finally { s.CancelWebGet = null; } int statusCode = report.StatusCode; if (report.Result) { // Success -> Check hash string hashDigest = StringEscaper.Preprocess(s, info.HashDigest); if (hashDigest.Length != 2 * HashHelper.GetHashByteLen(info.HashType)) { return(LogInfo.LogErrorMessage(logs, $"Hash digest [{hashDigest}] is not [{info.HashType}]")); } string downDigest; using (FileStream fs = new FileStream(tempPath, FileMode.Open, FileAccess.Read)) { byte[] digest = HashHelper.GetHash(info.HashType, fs); downDigest = StringHelper.ToHexStr(digest); } if (hashDigest.Equals(downDigest, StringComparison.OrdinalIgnoreCase)) // Success { FileHelper.FileReplaceEx(tempPath, destFile); logs.Add(new LogInfo(LogState.Success, $"[{destFile}] downloaded from [{url}] and verified ")); } else { statusCode = 1; // 1 means hash mismatch logs.Add(new LogInfo(LogState.Error, $"Downloaded file from [{url}] was corrupted")); } } else { // Failure -> Log error message LogState state = info.NoErrFlag ? LogState.Warning : LogState.Error; logs.Add(new LogInfo(state, $"Error occured while downloading [{url}]")); logs.Add(new LogInfo(LogState.Info, report.ErrorMsg)); if (statusCode == 0) { logs.Add(new LogInfo(LogState.Info, "Request failed, no response received.")); } else { logs.Add(new LogInfo(LogState.Info, $"Response returned HTTP Status Code [{statusCode}]")); } } // PEBakery extension -> Report exit code via #r if (!s.CompatDisableExtendedSectionParams) { s.ReturnValue = statusCode.ToString(); if (statusCode < 100) { logs.Add(new LogInfo(LogState.Success, $"Returned [{statusCode}] into [#r]")); } else { logs.Add(new LogInfo(LogState.Success, $"Returned HTTP status code [{statusCode}] to [#r]")); } } } } finally { s.MainViewModel.ResetBuildCommandProgress(); } return(logs); }