Example #1
0
        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;
        }
Example #2
0
        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;
            }
        }