Example #1
0
        // Answer true if the current clipboard contents are something that makes sense to paste into the href
        // of a hyperlink in a Bloom Book. Currently we allow all http(s) and mailto links, plus internal links
        // (starting with #) provided they are to a non-xmatter page that is present in the book.
        private void HandleIsClipboardBookHyperlink(ApiRequest request)
        {
            string clipContent = "";             // initial value is not used, delegate will set it.

            Program.MainContext.Send(o =>
            {
                try
                {
                    clipContent = PortableClipboard.GetText();
                }
                catch (Exception e)
                {
                    // Need to make sure to handle exceptions.
                    // If the worker thread dies with an unhandled exception,
                    // it causes the whole program to immediately crash without opportunity for error reporting
                    Bloom.Utils.MiscUtils.SuppressUnusedExceptionVarWarning(e);

                    request.ReplyWithBoolean(false);
                }
            }, null);

            request.ReplyWithBoolean(IsBloomHyperlink(clipContent, request.CurrentBook));
        }
Example #2
0
        public void RegisterWithApiHandler(BloomApiHandler apiHandler)
        {
            apiHandler.RegisterEndpointLegacy("uiLanguages", HandleUiLanguages, false);                               // App
            apiHandler.RegisterEndpointLegacy("currentUiLanguage", HandleCurrentUiLanguage, false);                   // App
            apiHandler.RegisterEndpointLegacy("bubbleLanguages", HandleBubbleLanguages, false);                       // Move to EditingViewApi
            apiHandler.RegisterEndpointLegacy("authorMode", HandleAuthorMode, false);                                 // Move to EditingViewApi
            apiHandler.RegisterEndpointLegacy("topics", HandleTopics, false);                                         // Move to EditingViewApi
            apiHandler.RegisterEndpointLegacy("common/error", HandleJavascriptError, false);                          // Common
            apiHandler.RegisterEndpointLegacy("common/preliminaryError", HandlePreliminaryJavascriptError, false);    // Common
            apiHandler.RegisterEndpointLegacy("common/saveChangesAndRethinkPageEvent", RethinkPageAndReloadIt, true); // Move to EditingViewApi
            apiHandler.RegisterEndpointLegacy("common/chooseFolder", HandleChooseFolder, true);
            apiHandler.RegisterEndpointLegacy("common/showInFolder", HandleShowInFolderRequest, true);                // Common
            apiHandler.RegisterEndpointLegacy("common/canModifyCurrentBook", HandleCanModifyCurrentBook, true);
            apiHandler.RegisterEndpointLegacy("common/showSettingsDialog", HandleShowSettingsDialog, false);          // Common
            apiHandler.RegisterEndpointLegacy("common/problemWithBookMessage", request =>
            {
                request.ReplyWithText(CommonMessages.GetProblemWithBookMessage(Path.GetFileName(_bookSelection.CurrentSelection?.FolderPath)));
            }, false);
            apiHandler.RegisterEndpointLegacy("common/clickHereForHelp", request =>
            {
                var problemFilePath = UrlPathString.CreateFromUrlEncodedString(request.RequiredParam("problem")).NotEncoded;
                request.ReplyWithText(CommonMessages.GetPleaseClickHereForHelpMessage(problemFilePath));
            }, false);
            // Used when something in JS land wants to copy text to or from the clipboard. For POST, the text to be put on the
            // clipboard is passed as the 'text' property of a JSON requestData.
            // Somehow the get version of this fires while initializing a page (probably hooking up CkEditor, an unwanted
            // invocation of the code that decides whether to enable the paste hyperlink button). This causes a deadlock
            // unless we make this endpoint requiresSync:false. I think this is safe as it doesn't interact with any other
            // Bloom objects.
            apiHandler.RegisterEndpointLegacy("common/clipboardText",
                                              request =>
            {
                if (request.HttpMethod == HttpMethods.Get)
                {
                    string result = "";                             // initial value is not used, delegate will set it.
                    Program.MainContext.Send(o =>
                    {
                        try
                        {
                            result = PortableClipboard.GetText();
                        }
                        catch (Exception e)
                        {
                            // Need to make sure to handle exceptions.
                            // If the worker thread dies with an unhandled exception,
                            // it causes the whole program to immediately crash without opportunity for error reporting
                            NonFatalProblem.Report(ModalIf.All, PassiveIf.None, "Error pasting text", exception: e);
                        }
                    }, null);
                    request.ReplyWithText(result);
                }
                else
                {
                    // post
                    var requestData = DynamicJson.Parse(request.RequiredPostJson());
                    string content  = requestData.text;
                    if (!string.IsNullOrEmpty(content))
                    {
                        Program.MainContext.Post(o =>
                        {
                            try
                            {
                                PortableClipboard.SetText(content);
                            }
                            catch (Exception e)
                            {
                                // Need to make sure to handle exceptions.
                                // If the worker thread dies with an unhandled exception,
                                // it causes the whole program to immediately crash without opportunity for error reporting
                                NonFatalProblem.Report(ModalIf.All, PassiveIf.None, "Error copying text", exception: e);
                            }
                        }, null);
                    }
                    request.PostSucceeded();
                }
            }, false, false);
            apiHandler.RegisterEndpointLegacy("common/checkForUpdates",
                                              request =>
            {
                WorkspaceView.CheckForUpdates();
                request.PostSucceeded();
            }, false);
            apiHandler.RegisterEndpointLegacy("common/channel",
                                              request =>
            {
                request.ReplyWithText(ApplicationUpdateSupport.ChannelName);
            }, false);
            // This is useful for debugging TypeScript code, especially on Linux.  I wouldn't necessarily expect
            // to see it used anywhere in code that gets submitted and merged.
            apiHandler.RegisterEndpointLegacy("common/debugMessage",
                                              request =>
            {
                var message = request.RequiredPostString();
                Debug.WriteLine("FROM JS: " + message);
                request.PostSucceeded();
            }, false);

            apiHandler.RegisterEndpointLegacy("common/loginData",
                                              request =>
            {
                var requestData = DynamicJson.Parse(request.RequiredPostJson());
                string token    = requestData.sessionToken;
                string email    = requestData.email;
                string userId   = requestData.userId;
                //Debug.WriteLine("Got login data " + email + " with token " + token + " and id " + userId);
                _parseClient.SetLoginData(email, userId, token, BookUpload.Destination);
                _doWhenLoggedIn?.Invoke();
                request.PostSucceeded();
            }, false);

            // At this point we open dialogs from c# code; if we opened dialogs from javascript, we wouldn't need this
            // api to do it. We just need a way to close a c#-opened dialog from javascript (e.g. the Close button of the dialog).
            //
            // This must set requiresSync:false because the API call which opened the dialog may already have
            // the lock in which case we would be deadlocked.
            // ErrorReport.NotifyUserOfProblem is a particularly problematic case. We tried to come up with some
            // other solutions for that including opening the dialog on Application.Idle. But the dialog needs
            // to give a real-time result so callers can know what do with button presses. Since some of those
            // callers are in libpalaso, we can't just ignore the result and handle the actions ourselves.
            apiHandler.RegisterEndpointLegacy("common/closeReactDialog", request =>
            {
                ReactDialog.CloseCurrentModal(request.GetPostStringOrNull());
                request.PostSucceeded();
            }, true, requiresSync: false);

            // TODO: move to the new App API (BL-9635)
            apiHandler.RegisterEndpointLegacy("common/reloadCollection", HandleReloadCollection, true);
        }