public void NavigateNimigemScheme(string fullQuery, System.Windows.Navigation.NavigatingCancelEventArgs e, string payload, bool requireSecure = true) { var NimigemUri = e.Uri.OriginalString; //at present we only support UTF8 plain text payloads byte[] nimigemBody = Encoding.UTF8.GetBytes(payload); var mime = "text/plain; charset=utf-8"; var settings = new UserSettings(); var uri = new Uri(fullQuery); //use a proxy for any other scheme that is not Nimigem var proxy = ""; //use none var connectInsecure = false; if (uri.Host == "localhost") { //to support local testing servers, dont require secure connection on localhost //**FIX ME, or have an option connectInsecure = true; } X509Certificate2 certificate; certificate = Session.Instance.CertificatesManager.GetCertificate(uri.Host); try { NimigemResponse nimigemResponse; try { nimigemResponse = (NimigemResponse)Nimigem.Fetch(uri, nimigemBody, mime, certificate, proxy, connectInsecure, settings.MaxDownloadSizeMb * 1024, settings.MaxDownloadTimeSeconds); } catch (Exception err) { //warn, but continue if there are server validation errors //in these early days of Nimigem we dont forbid visiting a site with an expired cert or mismatched host name //but we do give a warning each time if (err.Message == "The remote certificate was rejected by the provided RemoteCertificateValidationCallback.") { mMainWindow.ToastNotify("Note: " + err.Message + " for: " + e.Uri.Authority, ToastMessageStyles.Warning); //try again insecure this time nimigemResponse = (NimigemResponse)Nimigem.Fetch(uri, nimigemBody, mime, certificate, proxy, connectInsecure, settings.MaxDownloadSizeMb * 1024, settings.MaxDownloadTimeSeconds); } else { //reraise throw; } } if (nimigemResponse.codeMajor == '1') { //invalid in nimigem HandleInvalidResponse(nimigemResponse); } else if (nimigemResponse.codeMajor == '2') { //success if (nimigemResponse.codeMinor == '5') { //valid submission - get the new target to retrieve mMainWindow.ToastNotify(String.Format("Submit successful: retrieving result: {0}", nimigemResponse.meta)); var successUri = new Uri(nimigemResponse.meta); //must be a response redirect to gemini URL if (successUri.Scheme != "gemini") { HandleInvalidResponse(nimigemResponse); } var geminiTarget = new GeminiNavigator(mMainWindow, mMainWindow.BrowserControl); var normalisedUri = UriTester.NormaliseUri(successUri); var siteIdentity = new SiteIdentity(normalisedUri, Session.Instance); geminiTarget.NavigateGeminiScheme(successUri.OriginalString, e, siteIdentity); } else { //no other 2X responses are valid HandleInvalidResponse(nimigemResponse); } } // codemajor = 3 is redirect - should eventually end in success or raise an error else if (nimigemResponse.codeMajor == '4') { //same as normal Gemini mMainWindow.ToastNotify("Temporary failure (status 4X)\n\n" + nimigemResponse.meta + "\n\n" + e.Uri.ToString(), ToastMessageStyles.Warning); } else if (nimigemResponse.codeMajor == '5') { //same as normal Gemini if (nimigemResponse.codeMinor == '1') { mMainWindow.ToastNotify("Page not found\n\n" + e.Uri.ToString(), ToastMessageStyles.Warning); } else { mMainWindow.ToastNotify("Permanent failure (status 5X)\n\n" + nimigemResponse.meta + "\n\n" + e.Uri.ToString(), ToastMessageStyles.Warning); } } else if (nimigemResponse.codeMajor == '6') { mMainWindow.ToastNotify("Certificate required. Choose one and try again.\n\n" + e.Uri.ToString(), ToastMessageStyles.Warning); } else { mMainWindow.ToastNotify("Unexpected output from server " + "(status " + nimigemResponse.codeMajor + "." + nimigemResponse.codeMinor + ") " + nimigemResponse.meta + "\n\n" + e.Uri.ToString(), ToastMessageStyles.Warning); } } catch (Exception err) { //generic handler for other runtime errors mMainWindow.ToastNotify("Error getting Nimigem content for " + e.Uri.ToString() + "\n\n" + err.Message, ToastMessageStyles.Warning); } //make the window responsive again mMainWindow.ToggleContainerControlsForBrowser(true); //no further navigation right now e.Cancel = true; }
private void BrowserControl_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e) { var normalisedUri = UriTester.NormaliseUri(e.Uri); var siteIdentity = new SiteIdentity(normalisedUri, Session.Instance); var fullQuery = normalisedUri.OriginalString; //sanity check we have a valid URL syntax at least if (e.Uri.Scheme == null) { ToastNotify("Invalid URL: " + normalisedUri.OriginalString, ToastMessageStyles.Error); e.Cancel = true; } var settings = new Settings(); ToggleContainerControlsForBrowser(false); //these are the only ones we "navigate" to. We do this by downloading the GMI content //converting to HTML and then actually navigating to that. if (normalisedUri.Scheme == "gemini") { var geminiNavigator = new GeminiNavigator(this, this.BrowserControl); geminiNavigator.NavigateGeminiScheme(fullQuery, e, siteIdentity); } else if (normalisedUri.Scheme == "gopher") { var gopherNavigator = new GopherNavigator(this, this.BrowserControl); gopherNavigator.NavigateGopherScheme(fullQuery, e, siteIdentity); } else if (normalisedUri.Scheme == "about") { var aboutNavigator = new AboutNavigator(this, this.BrowserControl); aboutNavigator.NavigateAboutScheme(e, siteIdentity); } else if (normalisedUri.Scheme.StartsWith("http")) //both http and https { var linkId = ""; ////doc might be null - you need to check when using! var doc = (HTMLDocument)BrowserControl.Document; ////this is how we could detect a click on a link to an image... if (doc?.activeElement != null) { linkId = doc.activeElement.id; } //detect ctrl click if ( Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl) || settings.HandleWebLinks == "System web browser" || linkId == "web-launch-external" ) { //open in system web browser var launcher = new ExternalNavigator(this); launcher.LaunchExternalUri(e.Uri.ToString()); ToggleContainerControlsForBrowser(true); e.Cancel = true; } else if (settings.HandleWebLinks == "Gemini HTTP proxy") { // use a gemini proxy for http links var geminiNavigator = new GeminiNavigator(this, this.BrowserControl); geminiNavigator.NavigateGeminiScheme(fullQuery, e, siteIdentity); } else { //use internal navigator var httpNavigator = new HttpNavigator(this, this.BrowserControl); httpNavigator.NavigateHttpScheme(fullQuery, e, siteIdentity, linkId); } } else if (normalisedUri.Scheme == "file") { //just load the converted html file //no further action. } else { //we don't care about any other protocols //so we open those in system web browser to deal with var launcher = new ExternalNavigator(this); launcher.LaunchExternalUri(e.Uri.ToString()); ToggleContainerControlsForBrowser(true); e.Cancel = true; } }