/// <summary> /// Note! This will propogate network exceptions, so client can catch them and warn or not warn the user. /// </summary> /// <returns></returns> public string GetAppcastUrl() { if (string.IsNullOrEmpty(TextContentsOfTable)) { var client = new WebClient(); { TextContentsOfTable = client.DownloadString(URLOfTable); } } if (RunningVersion == default(Version)) { RunningVersion = Assembly.GetExecutingAssembly().GetName().Version; } //NB Programmers: don't change this to some OS-specific line ending, this is file read by both OS's. '\n' is common to files edited on linux and windows. foreach (var line in TextContentsOfTable.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)) { if (line.TrimStart().StartsWith("#")) { continue; //comment } var parts = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 3) { throw new ApplicationException("Could not parse a line of the UpdateVersionTable on " + URLOfTable + " '" + line + "'"); } var lower = Version.Parse(parts[0]); var upper = Version.Parse(parts[1]); if (lower <= RunningVersion && upper >= RunningVersion) { return(parts[2].Trim()); } } return(string.Empty); }
private void LogTableContents() { //html may have javascript which has braces which will kill the string.format in WriteEvent var safeContents = TextContentsOfTable.Replace("{", "{{").Replace("}", "}}"); Logger.WriteEvent("***UpdateVersionTable contents are " + Environment.NewLine + safeContents); }
/// <summary> /// If we can successfully download the update version table for the current channel, /// we return true and set the TextContentsOfTable property. Otherwise we return false and /// an UpdateTableLookupResult with an embedded error as an 'out' param. /// This internal method enables testing of captive portal situations /// </summary> /// <param name="client"></param> /// <param name="errorResult"></param> /// <returns></returns> internal bool CanGetVersionTableFromWeb(IBloomWebClient client, out UpdateTableLookupResult errorResult) { errorResult = null; try { Logger.WriteEvent("Channel is '" + ApplicationUpdateSupport.ChannelName + "'"); Logger.WriteEvent("UpdateVersionTable looking for UpdateVersionTable URL: " + GetUrlOfTable()); TextContentsOfTable = client.DownloadString(GetUrlOfTable()); //things like captive portals will return an html page rather than the text file what we asked for, if the user isn't //logged in. if (TextContentsOfTable.ToLower().Contains("<html")) { LogTableContents(); var msg = "Internet connection did not allow check for update."; NonFatalProblem.Report(ModalIf.Alpha, PassiveIf.All, msg); // hopefully this will just 'toast' errorResult = new UpdateTableLookupResult { URL = string.Empty, Error = new WebException(msg) }; return(false); } } catch (WebException e) { Logger.WriteEvent("***Error (WebException) in CanGetVersionTableFromWeb: " + e.Message); if (e.Status == WebExceptionStatus.ProtocolError) { if (e.Response is HttpWebResponse resp && resp.StatusCode == HttpStatusCode.NotFound) { Logger.WriteEvent( $"***Error: UpdateVersionTable failed to find a file at {GetUrlOfTable()} (channel='{ApplicationUpdateSupport.ChannelName}'"); } } else if (IsConnectionError(e)) { Logger.WriteEvent("***Error: UpdateVersionTable could not connect to the server"); } errorResult = new UpdateTableLookupResult() { Error = e }; return(false); } catch (Exception e) { // We're getting some kind of exception thrown on some alpha users' machines, but we don't know why (BL-9211). // It isn't a WebException. I'm adding this catch block at least long enough to diagnose the problem, // but it is probably better to be here, anyway, since without it, Bloom crashes silently. Logger.WriteError("***Error (Exception) in CanGetVersionTableFromWeb:", e); errorResult = new UpdateTableLookupResult() { Error = new WebException(e.Message) }; return(false); } return(true); // no error yet anyway! }
/// <summary> /// If we can successfully download the update version table for the current channel, /// we return true and set the TextContentsOfTable property. Otherwise we return false and /// an UpdateTableLookupResult with an embedded error as an 'out' param. /// This internal method enables testing of captive portal situations /// </summary> /// <param name="client"></param> /// <param name="errorResult"></param> /// <returns></returns> internal bool CanGetVersionTableFromWeb(IBloomWebClient client, out UpdateTableLookupResult errorResult) { errorResult = null; try { Logger.WriteEvent("Channel is '" + ApplicationUpdateSupport.ChannelName + "'"); Logger.WriteEvent("UpdateVersionTable looking for UpdateVersionTable URL: " + GetUrlOfTable()); TextContentsOfTable = client.DownloadString(GetUrlOfTable()); //things like captive portals will return an html page rather than the text file what we asked for, if the user isn't //logged in. if (TextContentsOfTable.ToLower().Contains("<html")) { LogTableContents(); var msg = "Internet connection did not allow check for update."; NonFatalProblem.Report(ModalIf.Alpha, PassiveIf.All, msg); // hopefully this will just 'toast' errorResult = new UpdateTableLookupResult { URL = string.Empty, Error = new WebException(msg) }; return(false); } } catch (WebException e) { Logger.WriteEvent("***Error in LookupURLOfUpdate: " + e.Message); if (e.Status == WebExceptionStatus.ProtocolError) { var resp = e.Response as HttpWebResponse; if (resp != null && resp.StatusCode == HttpStatusCode.NotFound) { Logger.WriteEvent(String.Format("***Error: UpdateVersionTable failed to find a file at {0} (channel='{1}'", GetUrlOfTable(), ApplicationUpdateSupport.ChannelName)); } } else if (IsConnectionError(e)) { Logger.WriteEvent("***Error: UpdateVersionTable could not connect to the server"); } errorResult = new UpdateTableLookupResult() { Error = e }; return(false); } return(true); // no error yet anyway! }
/// <summary> /// Note! This will propagate network exceptions, so client can catch them and warn or not warn the user. /// </summary> /// <returns></returns> public UpdateTableLookupResult LookupURLOfUpdate(bool forceReload = false) { if (string.IsNullOrEmpty(TextContentsOfTable) || forceReload) { Logger.WriteEvent("Enter LookupURLOfUpdate()"); var client = new BloomWebClient(); { UpdateTableLookupResult errorResult; if (!CanGetVersionTableFromWeb(client, out errorResult)) { return(errorResult); } } } if (RunningVersion == default(Version)) { RunningVersion = Assembly.GetExecutingAssembly().GetName().Version; } var parsingErrorMsg = String.Empty; try { //NB Programmers: don't change this to some OS-specific line ending, this is file read by both OS's. '\n' is common to files edited on linux and windows. foreach (var line in TextContentsOfTable.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)) { if (line.TrimStart().StartsWith("#")) { continue; //comment } var parts = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 3) { Logger.WriteEvent("***Error: UpdateVersionTable could not parse line {0} of this updateTableContent:", line); LogTableContents(); throw new ApplicationException(line); } var lower = Version.Parse(parts[0]); var upper = Version.Parse(parts[1]); if (lower <= RunningVersion && upper >= RunningVersion) { return new UpdateTableLookupResult { URL = parts[2].Trim() } } ; } parsingErrorMsg = string.Format("{0} contains no record for this version of Bloom", GetUrlOfTable()); } catch (ApplicationException e) { // BL-2654 Failure when reading upgrade table should not give a crash // In this case, a line of the UpdateVersionTable was not parseable // Put a message in the log and don't upgrade (and return a message that will get into a 'toast') parsingErrorMsg = "Could not parse a line of the UpdateVersionTable" + e.Message; Logger.WriteEvent(parsingErrorMsg); } catch (ArgumentException e) { // BL-2654 Failure when reading upgrade table should not give a crash // In this case, a version number in the UpdateVersionTable was not parseable // Put a message in the log and don't upgrade (and return a message that will get into a 'toast') parsingErrorMsg = "Could not parse a version number in the UpdateVersionTable" + e.Message; Logger.WriteEvent(parsingErrorMsg); } return(new UpdateTableLookupResult { URL = String.Empty, Error = new WebException(parsingErrorMsg) }); }
/// <summary> /// Note! This will propogate network exceptions, so client can catch them and warn or not warn the user. /// </summary> /// <returns></returns> public UpdateTableLookupResult LookupURLOfUpdate() { if (String.IsNullOrEmpty(TextContentsOfTable)) { Logger.WriteEvent("Enter LookupURLOfUpdate()"); var client = new WebClient(); { try { Logger.WriteEvent("Channel is '" + ApplicationUpdateSupport.ChannelName + "'"); Logger.WriteEvent("UpdateVersionTable looking for UpdateVersionTable URL: " + GetUrlOfTable()); TextContentsOfTable = client.DownloadString(GetUrlOfTable()); //things like captive portals will return an html page rather than the text file what we asked for, if the user isn't //logged in. if (TextContentsOfTable.ToLower().Contains("<html")) { LogTableContents(); return(new UpdateTableLookupResult() { Error = new WebException("Internet connection did not allow check for update.") }); } } catch (WebException e) { Logger.WriteEvent("***Error in LookupURLOfUpdate: " + e.Message); if (e.Status == WebExceptionStatus.ProtocolError) { var resp = e.Response as HttpWebResponse; if (resp != null && resp.StatusCode == HttpStatusCode.NotFound) { Logger.WriteEvent(String.Format("***Error: UpdateVersionTable failed to find a file at {0} (channel='{1}'", GetUrlOfTable(), ApplicationUpdateSupport.ChannelName)); } } else if (IsConnectionError(e)) { Logger.WriteEvent("***Error: UpdateVersionTable could not connect to the server"); } return(new UpdateTableLookupResult() { Error = e }); } } } if (RunningVersion == default(Version)) { RunningVersion = Assembly.GetExecutingAssembly().GetName().Version; } var parsingErrorMsg = String.Empty; try { //NB Programmers: don't change this to some OS-specific line ending, this is file read by both OS's. '\n' is common to files edited on linux and windows. foreach (var line in TextContentsOfTable.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)) { if (line.TrimStart().StartsWith("#")) { continue; //comment } var parts = line.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 3) { Logger.WriteEvent("***Error: UpdateVersionTable could not parse line {0} of this updateTableContent:", line); LogTableContents(); throw new ApplicationException(line); } var lower = Version.Parse(parts[0]); var upper = Version.Parse(parts[1]); if (lower <= RunningVersion && upper >= RunningVersion) { return new UpdateTableLookupResult() { URL = parts[2].Trim() } } ; } parsingErrorMsg = string.Format("{0} contains no record for this version of Bloom", GetUrlOfTable()); } catch (ApplicationException e) { // BL-2654 Failure when reading upgrade table should not give a crash // In this case, a line of the UpdateVersionTable was not parseable // Put a message in the log and don't upgrade (and return a message that will get into a 'toast') parsingErrorMsg = "Could not parse a line of the UpdateVersionTable" + e.Message; Logger.WriteEvent(parsingErrorMsg); } catch (ArgumentException e) { // BL-2654 Failure when reading upgrade table should not give a crash // In this case, a version number in the UpdateVersionTable was not parseable // Put a message in the log and don't upgrade (and return a message that will get into a 'toast') parsingErrorMsg = "Could not parse a version number in the UpdateVersionTable" + e.Message; Logger.WriteEvent(parsingErrorMsg); } return(new UpdateTableLookupResult() { URL = String.Empty, Error = new WebException(parsingErrorMsg) }); }