예제 #1
0
        public static string CollectionIdFromCollectionFolder(string collectionFolder)
        {
            try
            {
                var settingsFilePath = Path.Combine(collectionFolder,
                                                    Path.ChangeExtension(Path.GetFileName(collectionFolder), "bloomCollection"));
                if (!RobustFile.Exists(settingsFilePath))
                {
                    // When we're joining a TC, we extract settings in to a temp folder whose name does not
                    // match the settings file.
                    var collections = Directory.EnumerateFiles(collectionFolder,
                                                               "*.bloomCollection").ToList();
                    if (collections.Count >= 1)
                    {
                        // Hopefully this repairs things.
                        settingsFilePath = collections[0];
                    }
                    else
                    {
                        return("");
                    }
                }

                var settingsContent = RobustFile.ReadAllText(settingsFilePath, Encoding.UTF8);
                var xml             = XElement.Parse(settingsContent);
                return(ReadString(xml, "CollectionId", ""));
            }
            catch (Exception ex)
            {
                Bloom.Utils.MiscUtils.SuppressUnusedExceptionVarWarning(ex);
                return("");
            }
        }
예제 #2
0
        /// <summary>
        /// Examine the stylesheets and collect the font families they mention.
        /// Note that the process used by ePub and bloomPub publication to
        /// determine fonts is more complicated, using the DOM in an actual browser.
        /// </summary>
        /// <returns>Enumerable of font names</returns>
        internal static IEnumerable <string> GetFontsUsed(string bookPath)
        {
            string bookHtmContent           = null;
            string defaultLangStylesContent = null;

            var result = new HashSet <string>();

            // Css for styles are contained in the actual html
            foreach (var filePath in Directory.EnumerateFiles(bookPath, "*.*").Where(f => f.EndsWith(".css") || f.EndsWith(".htm") || f.EndsWith(".html")))
            {
                var fileContents = RobustFile.ReadAllText(filePath, Encoding.UTF8);

                if (filePath.EndsWith(".htm"))
                {
                    bookHtmContent = fileContents;
                }
                else if (filePath.EndsWith("defaultLangStyles.css"))
                {
                    defaultLangStylesContent = fileContents;
                    // Delay processing defaultLangStyles to the end when we know we have the htm content.
                    continue;
                }

                HtmlDom.FindFontsUsedInCss(fileContents, result, false);
            }

            ProcessDefaultLangStyles(bookHtmContent, defaultLangStylesContent, result);

            return(result);
        }
예제 #3
0
        private static string GetReaderSettings(CollectionSettings currentCollectionSettings)
        {
            var settingsPath = DecodableReaderTool.GetReaderToolsSettingsFilePath(currentCollectionSettings);

            // if file exists, return current settings
            if (RobustFile.Exists(settingsPath))
            {
                var result = RobustFile.ReadAllText(settingsPath, Encoding.UTF8);
                if (!string.IsNullOrWhiteSpace(result))
                {
                    return(result);
                }
            }

            // file does not exist, so make a new one
            // The literal string here defines our default reader settings for a collection.
            var settingsString = "{\"letters\":\"a b c d e f g h i j k l m n o p q r s t u v w x y z\","
                                 + "\"moreWords\":\"\","
                                 + "\"stages\":[{\"letters\":\"\",\"sightWords\":\"\"}],"
                                 + "\"levels\":[{\"maxWordsPerSentence\":2,\"maxWordsPerPage\":2,\"maxWordsPerBook\":20,\"maxUniqueWordsPerBook\":0,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":5,\"maxWordsPerPage\":5,\"maxWordsPerBook\":23,\"maxUniqueWordsPerBook\":8,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":7,\"maxWordsPerPage\":10,\"maxWordsPerBook\":72,\"maxUniqueWordsPerBook\":16,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":8,\"maxWordsPerPage\":18,\"maxWordsPerBook\":206,\"maxUniqueWordsPerBook\":32,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":12,\"maxWordsPerPage\":25,\"maxWordsPerBook\":500,\"maxUniqueWordsPerBook\":64,\"thingsToRemember\":[]},"
                                 + "{\"maxWordsPerSentence\":20,\"maxWordsPerPage\":50,\"maxWordsPerBook\":1000,\"maxUniqueWordsPerBook\":0,\"thingsToRemember\":[]}]}";

            RobustFile.WriteAllText(settingsPath, settingsString);

            return(settingsString);
        }
예제 #4
0
        public void CreateBookOnDiskFromShell_OriginalCC0_BookIsCC0()
        {
            var originalSource = Path.Combine(BloomFileLocator.SampleShellsDirectory, "Vaccinations");

            using (var tempFolder = new TemporaryFolder("VaccinationsCc0"))
                using (var destFolder = new TemporaryFolder("Vaccinations_BookIsCC0"))
                {
                    var source = Path.Combine(tempFolder.Path, "Vaccinations");
                    if (Directory.Exists(source))
                    {
                        Directory.Delete(source, true);
                    }
                    DirectoryUtilities.CopyDirectory(originalSource, tempFolder.Path);
                    var htmPath = Path.Combine(source, "Vaccinations.htm");
                    var content = RobustFile.ReadAllText(htmPath);
                    // insert cc0 stuff in data div
                    var patched = content.Replace("http://creativecommons.org/licenses/by-nc/3.0/", "http://creativecommons.org/publicdomain/zero/1.0/");
                    RobustFile.WriteAllText(htmPath, patched);
                    var bookPath       = GetPathToHtml(_starter.CreateBookOnDiskFromTemplate(source, destFolder.Path));
                    var assertThatBook = AssertThatXmlIn.HtmlFile(bookPath);
                    // For some reason Vaccinations specifies licenseUrl in three ways (no lang, lang="en", lang="*").
                    // We don't want any of them messed with.
                    assertThatBook.HasSpecifiedNumberOfMatchesForXpath("//div[@data-book='licenseUrl' and contains(text(), '/zero/1.0')]", 3);
                }
        }
예제 #5
0
        private (string version, bool old) GetAceByDaisyVersion(string daisyDirectory)
        {
            try
            {
                // The path typically ends in something like \ace\bin\, at least on Windows.
                // We're looking for the ace directory. One GetDirectoryName just strips of the
                // final slash, so we need two to get to ace.
                var    packagePath   = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(daisyDirectory)), "package.json");
                var    packageJson   = DynamicJson.Parse(RobustFile.ReadAllText(packagePath));
                string versionString = packageJson.version;
                var    match         = new Regex(@"(\d+)\.(\d+)").Match(versionString);
                if (match.Success)
                {
                    var old = int.Parse(match.Groups[1].Value) * 100 + int.Parse(match.Groups[2].Value) < 102;
                    return(versionString, old);
                }
            }
            catch (Exception ex)
            {
                // just log then ignore not being able to get the version.
                Bloom.Utils.MiscUtils.SuppressUnusedExceptionVarWarning(ex);
            }

            return("unknown", true);
        }
예제 #6
0
        /// <summary>
        /// This method assumes we just did IsBookOnServer() and got a positive response.
        /// </summary>
        public dynamic GetBookOnServer(string bookPath)
        {
            var metadata = BookMetaData.FromString(RobustFile.ReadAllText(bookPath.CombineForPath(BookInfo.MetaDataFileName)));

            // 'true' parameter tells the query to include language information so we can get the names.
            return(ParseClient.GetSingleBookRecord(metadata.Id, true));
        }
예제 #7
0
        private static string GetMetaJsonModfiedForTemplate(string path)
        {
            var meta = BookMetaData.FromString(RobustFile.ReadAllText(path));

            meta.IsSuitableForMakingShells = true;
            return(meta.Json);
        }
예제 #8
0
        public static UserPrefs LoadOrMakeNew(string fileName)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                return(null);
            }

            UserPrefs userPrefs = null;

            if (RobustFile.Exists(fileName))
            {
                try
                {
                    userPrefs = JsonConvert.DeserializeObject <UserPrefs>(RobustFile.ReadAllText(fileName));
                    if (userPrefs == null)
                    {
                        throw new ApplicationException("JsonConvert.DeserializeObject() returned null");
                    }
                }
                catch (Exception e)
                {
                    Logger.WriteEvent("error reading UserPrefs at " + fileName + "  " + e.Message);
                    //otherwise, just give them a new user prefs
                    userPrefs = null;
                }
            }
            if (userPrefs == null)
            {
                userPrefs = new UserPrefs();
            }
            userPrefs._filePath = fileName;
            userPrefs._loading  = false;
            return(userPrefs);
        }
예제 #9
0
        /// <summary>
        /// Initializes a new instance of the <see cref="LanguageLookup"/> class.
        /// It gets its data from the LanguageDataIndex resource
        /// </summary>
        public LanguageLookup()
        {
            Sldr.InitializeLanguageTags();             // initialise SLDR language tags for implicit script codes

            string langTagsContent = LanguageRegistryResources.langTags;
            // The cached file is renamed if it's invalid during Sldr.InitializeLanguageTags().
            var cachedAllTagsPath = Path.Combine(Sldr.SldrCachePath, "langtags.json");

            if (File.Exists(cachedAllTagsPath))
            {
                langTagsContent = RobustFile.ReadAllText(cachedAllTagsPath);
            }
            List <AllTagEntry> rootObject = JsonConvert.DeserializeObject <List <AllTagEntry> >(langTagsContent);

            foreach (AllTagEntry entry in rootObject)
            {
                // tags starting with x- have undefined structure so ignoring them as well as deprecated tags
                // tags starting with _ may provide some sort of undefined variant information, but we ignore them as well
                if (!entry.deprecated && !entry.tag.StartsWith("x-", StringComparison.Ordinal) && !entry.tag.StartsWith("_", StringComparison.Ordinal))
                {
                    AddLanguage(entry.tag, entry.iso639_3, entry.full, entry.name, entry.localname, entry.region, entry.names, entry.regions, entry.tags, entry.iana, entry.regionName);
                }
            }
            AddLanguage("qaa", "qaa", "qaa", "Unlisted Language");
        }
        public void ForgetChanges_RenameAndReplace_UndoesAndMoves()
        {
            using (var collectionFolder =
                       new TemporaryFolder("ForgetChanges_HtmlChangeAndRename_UndoesBoth_Collection"))
            {
                using (var repoFolder =
                           new TemporaryFolder("ForgetChanges_HtmlChangeAndRename_UndoesBoth_Repo"))
                {
                    var tc = MakeAndRenameBook(collectionFolder, repoFolder, out var bookPath,
                                               out var newBookFolderPath);
                    Directory.CreateDirectory(Path.GetDirectoryName(bookPath));
                    RobustFile.WriteAllText(bookPath, "This is some other book created after the rename");

                    var changedFolders = tc.ForgetChangesCheckin("Renamed book");

                    Assert.That(RobustFile.Exists(bookPath));
                    Assert.That(Directory.Exists(newBookFolderPath), Is.False);
                    Assert.That(RobustFile.ReadAllText(bookPath), Is.EqualTo("This is just a dummy"));
                    Assert.That(tc.GetStatus("My book").lockedBy, Is.Null);
                    Assert.That(changedFolders.Count, Is.EqualTo(3));
                    var movedFolder   = changedFolders[2];
                    var movedBookPath = Path.Combine(movedFolder,
                                                     Path.ChangeExtension(Path.GetFileName(movedFolder), "htm"));
                    Assert.That(RobustFile.ReadAllText(movedBookPath),
                                Is.EqualTo("This is some other book created after the rename"));
                }
            }
        }
        public void ForgetChanges_HtmlChange_UndoesIt()
        {
            using (var collectionFolder =
                       new TemporaryFolder("ForgetChanges_HtmlChange_UndoesIt_Collection"))
            {
                using (var repoFolder =
                           new TemporaryFolder("ForgetChanges_HtmlChange_UndoesIt_Repo"))
                {
                    var mockTcManager = new Mock <ITeamCollectionManager>();
                    var tc            = new TestFolderTeamCollection(mockTcManager.Object, collectionFolder.FolderPath,
                                                                     repoFolder.FolderPath);
                    var bookFolderPath = Path.Combine(collectionFolder.FolderPath, "My book");
                    Directory.CreateDirectory(bookFolderPath);
                    var bookPath = Path.Combine(bookFolderPath, "My book.htm");
                    RobustFile.WriteAllText(bookPath, "This is just a dummy");
                    tc.PutBook(bookFolderPath);
                    tc.AttemptLock("My book", "*****@*****.**");
                    RobustFile.WriteAllText(bookPath, "This is the edited content");

                    var changedFolders = tc.ForgetChangesCheckin("My book");

                    Assert.That(changedFolders.Count, Is.EqualTo(0));
                    Assert.That(RobustFile.ReadAllText(bookPath), Is.EqualTo("This is just a dummy"));
                    Assert.That(tc.GetStatus("My book").lockedBy, Is.Null);
                }
            }
        }
예제 #12
0
        public void BulkPublishBloomPubSettings_GivenBulkPublishSettings_SavesToXmlProperly()
        {
            var settings = CreateCollectionSettings(_folder.Path, "test");

            settings.BulkPublishBloomPubSettings = new Bloom.Publish.Android.BulkBloomPubPublishSettings()
            {
                makeBookshelfFile = false,
                makeBloomBundle   = false,
                bookshelfColor    = "#FF0000",
                distributionTag   = "distTag",
                bookshelfLabel    = "bookshelfLabel"
            };

            // System under test
            settings.Save();

            // Verification
            var    text     = RobustFile.ReadAllText(settings.SettingsFilePath);
            string expected = @"<BulkPublishBloomPubSettings>
    <MakeBookshelfFile>False</MakeBookshelfFile>
    <MakeBloomBundle>False</MakeBloomBundle>
    <BookshelfColor>#FF0000</BookshelfColor>
    <DistributionTag>distTag</DistributionTag>
    <BookshelfLabel>bookshelfLabel</BookshelfLabel>
  </BulkPublishBloomPubSettings>";

            StringAssert.Contains(expected, text);
        }
예제 #13
0
        public void HandleBookOrder(string bookOrderPath, string projectPath)
        {
            var metadata = BookMetaData.FromString(RobustFile.ReadAllText(bookOrderPath));
            var s3BookId = metadata.DownloadSource;
            var bucket   = BloomS3Client.ProductionBucketName;           //TODO

            _s3Client.DownloadBook(bucket, s3BookId, Path.GetDirectoryName(projectPath));
        }
예제 #14
0
        public static IEnumerable <Layout> GetLayoutChoices(HtmlDom dom, IFileLocator fileLocator)
        {
            //here we walk through all the stylesheets, looking for one with the special style which tells us which page/orientations it supports
            foreach (XmlElement link in dom.SafeSelectNodes("//link[@rel='stylesheet']"))
            {
                var fileName = link.GetStringAttribute("href");
                if (fileName.ToLowerInvariant().Contains("mode") || fileName.ToLowerInvariant().Contains("page") ||
                    fileName.ToLowerInvariant().Contains("matter") || fileName.ToLowerInvariant().Contains("languagedisplay") ||
                    fileName.ToLowerInvariant().Contains("origami"))
                {
                    continue;
                }

                fileName = fileName.Replace("file://", "").Replace("%5C", "/").Replace("%20", " ");
                var path = fileLocator.LocateFile(fileName);
                if (string.IsNullOrEmpty(path))
                {
                    // We're looking for a block of json that is typically found in Basic Book.css or a comparable place for
                    // a book based on some other template. Caling code is prepared for not finding this block.
                    // It seems safe to ignore a reference to some missing style sheet.
                    NonFatalProblem.Report(ModalIf.None, PassiveIf.Alpha, "Could not find " + fileName + " while looking for size choices");
                    continue;
                }
                var contents = RobustFile.ReadAllText(path);
                var start    = contents.IndexOf("STARTLAYOUTS");
                if (start < 0)
                {
                    continue;                      //yield break; // continue;//move on to the next stylesheet
                }
                start += "STARTLAYOUTS".Length;
                var end = contents.IndexOf("ENDLAYOUTS", start);
                var s   = contents.Substring(start, end - start);

                IEnumerable <Layout> layouts = null;

                try
                {
                    layouts = Layout.GetConfigurationsFromConfigurationOptionsString(s);
                }
                catch (Exception e)
                {
                    throw new ApplicationException("Problem parsing the 'layouts' comment of " + fileName + ". The contents were\r\n" + s, e);
                }


                foreach (var p in layouts)
                {
                    yield return(p);
                }
                yield break;
            }

            //default to A5Portrait
            yield return(new Layout {
                SizeAndOrientation = FromString("A5Portrait")
            });
        }
예제 #15
0
 internal bool CheckAgainstLocalHashfile(string currentHashes, string uploadInfoPath)
 {
     if (RobustFile.Exists(uploadInfoPath))
     {
         var previousHashes = RobustFile.ReadAllText(uploadInfoPath);
         return(currentHashes == previousHashes);
     }
     return(false);
 }
예제 #16
0
        private void VerifyCorrectCssRuleExists(string collectionName, string oldNumberStyle)
        {
            var mainFile = CollectionSettings.GetPathForNewSettings(_folder.Path, collectionName);
            var cssFile  = Path.Combine(Path.GetDirectoryName(mainFile), "settingsCollectionStyles.css");
            var css      = RobustFile.ReadAllText(cssFile);

            Assert.IsTrue(Regex.Match(css, @"@media\s+print\s+{\s+\.numberedPage:after\s+{\s+content:\s+counter\(pageNumber,\s+" + oldNumberStyle + @"\);\s+}\s+}").Success,
                          "Css did not generate PageNumber style rule match.");
        }
        public void ConnectToTeamCollection_SetsUpRequiredFiles()
        {
            using (var collectionFolder = new TemporaryFolder("FolderTeamCollectionTests2_Collection"))
            {
                using (var sharedFolder = new TemporaryFolder("FolderTeamCollectionTests2_Shared"))
                {
                    var bookFolderName1 = "Some book";
                    SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, bookFolderName1, "Something");
                    // BL-9573 tests cases where the book name isn't exactly the same as the folder name
                    var bookFolderName2 = "Some other book";
                    SyncAtStartupTests.MakeFakeBook(collectionFolder.FolderPath, "Some other name altogether",
                                                    "Strange book content", bookFolderName2);
                    var settingsFileName =
                        Path.ChangeExtension(Path.GetFileName(collectionFolder.FolderPath), "bloomCollection");
                    var settingsPath = Path.Combine(collectionFolder.FolderPath, settingsFileName);

                    // As an aside, this is a convenient place to check that a TC manager created when TC settings does not exist
                    // functions and does not have a current collection.
                    var tcManager = new TeamCollectionManager(settingsPath, null, new BookRenamedEvent(),
                                                              new BookStatusChangeEvent(), null, null);
                    Assert.That(tcManager.CurrentCollection, Is.Null);

                    RobustFile.WriteAllText(settingsPath, "This is a fake settings file");
                    FolderTeamCollection.CreateTeamCollectionLinkFile(collectionFolder.FolderPath,
                                                                      sharedFolder.FolderPath);

                    var nonBookFolder = Path.Combine(collectionFolder.FolderPath, "Some other folder");
                    Directory.CreateDirectory(nonBookFolder);
                    tcManager = new TeamCollectionManager(settingsPath, null, new BookRenamedEvent(),
                                                          new BookStatusChangeEvent(), null, null);
                    var collection = tcManager.CurrentCollection;

                    // sut
                    (collection as FolderTeamCollection)?.SetupTeamCollection(sharedFolder.FolderPath,
                                                                              new NullWebSocketProgress());

                    Assert.That(collection, Is.Not.Null);
                    var joinCollectionPath =
                        Path.Combine(sharedFolder.FolderPath, "Join this Team Collection.JoinBloomTC");
                    Assert.That(File.Exists(joinCollectionPath));

                    var teamCollectionLinkPath =
                        Path.Combine(collectionFolder.FolderPath, TeamCollectionManager.TeamCollectionLinkFileName);
                    Assert.That(File.Exists(teamCollectionLinkPath));
                    var collectionFileContent = RobustFile.ReadAllText(teamCollectionLinkPath);
                    Assert.That(collectionFileContent, Is.EqualTo(sharedFolder.FolderPath));
                    var sharedSettingsPath = Path.Combine(collectionFolder.FolderPath, settingsFileName);
                    Assert.That(RobustFile.ReadAllText(sharedSettingsPath), Is.EqualTo("This is a fake settings file"));
                    var bookPath = Path.Combine(sharedFolder.FolderPath, "Books", bookFolderName1 + ".bloom");
                    Assert.That(File.Exists(bookPath));
                    var bookPath2 = Path.Combine(sharedFolder.FolderPath, "Books", bookFolderName2 + ".bloom");
                    Assert.That(File.Exists(bookPath2));
                }
            }
        }
예제 #18
0
 /// <summary>
 /// Remove language specific style settings for unwanted languages from all CSS files in the given directory.
 /// </summary>
 public static void RemoveUnwantedLanguageRulesFromCssFiles(string dirName, IEnumerable <string> wantedLanguages)
 {
     foreach (var filepath in Directory.EnumerateFiles(dirName, "*.css"))
     {
         var cssTextOrig = RobustFile.ReadAllText(filepath);
         var cssText     = HtmlDom.RemoveUnwantedLanguageRulesFromCss(cssTextOrig, wantedLanguages);
         if (cssText != cssTextOrig)
         {
             RobustFile.WriteAllText(filepath, cssText);
         }
     }
 }
예제 #19
0
        public void SyncAtStartup_RemoteRename_RenamedLocally()
        {
            var oldFolder = Path.Combine(_collectionFolder.FolderPath, kBookRenamedRemotely);

            Assert.That(Directory.Exists(oldFolder), Is.False);
            var newFolder = Path.Combine(_collectionFolder.FolderPath, kNewNameForRemoteRename);

            Assert.That(Directory.Exists(newFolder), Is.True);
            var newBookFile = Path.Combine(_collectionFolder.FolderPath, kNewNameForRemoteRename,
                                           kNewNameForRemoteRename + ".htm");

            Assert.That(RobustFile.ReadAllText(newBookFile), Does.Contain("This is the new book content after remote editing and rename"));
        }
예제 #20
0
        /// <summary>
        /// Initialize a new instance of the <see cref="Bloom.Registration.LicenseDialog"/> class.
        /// </summary>
        /// <param name="licenseMdFile">filename of the license in HTML format</param>
        /// <param name="prolog">prolog to the license (optional, already localized)</param>
        /// <remarks>
        /// The HTML file content should be suitable for inserting inside a body element.
        /// (I.e., it should not contain html, head, or body elements.)
        /// </remarks>
        public LicenseDialog(string licenseHtmlFile, string prolog = null)
        {
            InitializeComponent();

            Text = string.Format(Text, Assembly.GetExecutingAssembly().GetName().Version);

            // If there's no prolog, normalize the variable to an empty string.
            // If there is a prolog, add a horizontal rule separating the prolog from the license.
            if (String.IsNullOrWhiteSpace(prolog))
            {
                prolog = String.Empty;
            }
            else
            {
                prolog = String.Format("<p>{0}</p>{1}<hr>{1}", prolog, Environment.NewLine);
            }

            _licenseBrowser          = new Browser();
            _licenseBrowser.Isolator = new NavigationIsolator();             // never used while other browsers are around
            _licenseBrowser.Anchor   = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
            _licenseBrowser.Location = new Point(12, 12);
            _licenseBrowser.Name     = "licenseBrowser";
            _licenseBrowser.Size     = new Size(_acceptButton.Right - 12, _acceptButton.Top - 24);
            Controls.Add(_licenseBrowser);
            var    locale                   = CultureInfo.CurrentUICulture.Name;
            string licenseFilePath          = BloomFileLocator.GetFileDistributedWithApplication(licenseHtmlFile);
            var    localizedLicenseFilePath = licenseFilePath.Substring(0, licenseFilePath.Length - 3) + "-" + locale + ".htm";

            if (RobustFile.Exists(localizedLicenseFilePath))
            {
                licenseFilePath = localizedLicenseFilePath;
            }
            else
            {
                var index = locale.IndexOf('-');
                if (index > 0)
                {
                    locale = locale.Substring(0, index);
                    localizedLicenseFilePath = licenseFilePath.Substring(0, licenseFilePath.Length - 3) + "-" + locale + ".htm";
                    if (RobustFile.Exists(localizedLicenseFilePath))
                    {
                        licenseFilePath = localizedLicenseFilePath;
                    }
                }
            }
            var contents = prolog + RobustFile.ReadAllText(licenseFilePath, Encoding.UTF8);
            var html     = string.Format("<html><head><head/><body style=\"font-family:sans-serif\">{0}</body></html>", contents);

            _licenseBrowser.NavigateRawHtml(html);
            _licenseBrowser.Visible = true;
        }
예제 #21
0
        public string GetLibraryData()
        {
            if (!RobustFile.Exists(PathToLibraryJson))
            {
                return("{}");               //return "{\"dummy\": \"x\"}";//TODO
            }
            var s = RobustFile.ReadAllText(PathToLibraryJson);

            if (string.IsNullOrEmpty(s))
            {
                return(string.Empty);
            }

            return("{\"library\": " + s + "}");
        }
예제 #22
0
 private static bool TryReadMetaData(string path, out BookMetaData result)
 {
     result = null;
     if (!RobustFile.Exists(path))
     {
         return(false);
     }
     try
     {
         result = FromString(RobustFile.ReadAllText(path));
         return(true);
     }
     catch (Exception e)
     {
         return(false);
     }
 }
예제 #23
0
        /// <summary>
        /// branding folders can optionally contain a branding.json file which aligns with this Settings class
        /// </summary>
        /// <param name="brandingNameOrFolderPath"> Normally, the branding is just a name, which we look up in the official branding folder
        //but unit tests can instead provide a path to the folder.
        /// </param>
        public static Settings GetSettings(string brandingNameOrFolderPath)
        {
            try
            {
                ParseBrandingKey(brandingNameOrFolderPath, out var brandingFolderName, out var flavor);

                // check to see if we have a special branding.json just for this flavor.
                // Note that we could instead add code that allows a single branding.json to
                // have rules that apply only on a flavor basis. As of 4.9, all we have is the
                // ability for a branding.json (and anything else) to use "{flavor}" anywhere in the
                // name of an image; this will often be enough to avoid making a new branding.json.
                // But if we needed to have different boilerplate text, well then we would need to
                // either use this here mechanism (separate json) or implement the ability to add
                // "flavor:" to the rules.
                string settingsPath = null;
                if (!string.IsNullOrEmpty(flavor))
                {
                    settingsPath = BloomFileLocator.GetOptionalBrandingFile(brandingFolderName, "branding[" + flavor + "].json");
                }

                // if not, fall bck to just "branding.json"
                if (string.IsNullOrEmpty(settingsPath))
                {
                    settingsPath = BloomFileLocator.GetOptionalBrandingFile(brandingFolderName, "branding.json");
                }

                if (!string.IsNullOrEmpty(settingsPath))
                {
                    var content  = RobustFile.ReadAllText(settingsPath);
                    var settings = JsonConvert.DeserializeObject <Settings>(content);
                    if (settings == null)
                    {
                        NonFatalProblem.Report(ModalIf.Beta, PassiveIf.All, "Trouble reading branding settings",
                                               "branding.json of the branding " + brandingNameOrFolderPath + " may be corrupt. It had: " + content);
                        return(null);
                    }
                    return(settings);
                }
            }
            catch (Exception e)
            {
                NonFatalProblem.Report(ModalIf.Beta, PassiveIf.All, "Trouble reading branding settings", exception: e);
            }
            return(null);
        }
예제 #24
0
        public LicenseDialog()
        {
            InitializeComponent();

            Text = string.Format(Text, Assembly.GetExecutingAssembly().GetName().Version);

            _licenseBrowser          = new Browser();
            _licenseBrowser.Isolator = new NavigationIsolator();             // never used while other browsers are around
            _licenseBrowser.Anchor   = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
            _licenseBrowser.Location = new Point(12, 12);
            _licenseBrowser.Name     = "licenseBrowser";
            _licenseBrowser.Size     = new Size(_acceptButton.Right - 12, _acceptButton.Top - 24);
            Controls.Add(_licenseBrowser);
            var options = new MarkdownOptions()
            {
                LinkEmails = true, AutoHyperlink = true
            };
            var    m                        = new Markdown(options);
            var    locale                   = CultureInfo.CurrentUICulture.Name;
            string licenseFilePath          = BloomFileLocator.GetFileDistributedWithApplication("license.md");
            var    localizedLicenseFilePath = licenseFilePath.Substring(0, licenseFilePath.Length - 3) + "-" + locale + ".md";

            if (RobustFile.Exists(localizedLicenseFilePath))
            {
                licenseFilePath = localizedLicenseFilePath;
            }
            else
            {
                var index = locale.IndexOf('-');
                if (index > 0)
                {
                    locale = locale.Substring(0, index);
                    localizedLicenseFilePath = licenseFilePath.Substring(0, licenseFilePath.Length - 3) + "-" + locale + ".md";
                    if (RobustFile.Exists(localizedLicenseFilePath))
                    {
                        licenseFilePath = localizedLicenseFilePath;
                    }
                }
            }
            var contents = m.Transform(RobustFile.ReadAllText(licenseFilePath, Encoding.UTF8));
            var html     = string.Format("<html><head><head/><body>{0}</body></html>", contents);

            _licenseBrowser.NavigateRawHtml(html);
            _licenseBrowser.Visible = true;
        }
예제 #25
0
        /// <summary>
        /// Does some pre-processing on reader files
        /// </summary>
        /// <param name="bookPath"></param>
        private static string GetBookReplacedWithTemplate(string bookPath)
        {
            //TODO: the following, which is the original code before late in 3.6, just modified the tags in the HTML
            //Whereas currently, we use the meta.json as the authoritative source.
            //TODO Should we just get rid of these tags in the HTML? Can they be accessed from javascript? If so,
            //then they will be needed eventually (as we involve c# less in the UI)
            var text = RobustFile.ReadAllText(bookPath, Encoding.UTF8);
            // Note that we're getting rid of preceding newline but not following one. Hopefully we cleanly remove a whole line.
            // I'm not sure the </meta> ever occurs in html files, but just in case we'll match if present.
            var regex = new Regex("\\s*<meta\\s+name=(['\\\"])lockedDownAsShell\\1 content=(['\\\"])true\\2>(</meta>)? *");
            var match = regex.Match(text);

            if (match.Success)
            {
                text = text.Substring(0, match.Index) + text.Substring(match.Index + match.Length);
            }

            // BL-2476: Readers made from BloomPacks should have the formatting dialog disabled
            regex = new Regex("\\s*<meta\\s+name=(['\\\"])pageTemplateSource\\1 content=(['\\\"])(Leveled|Decodable) Reader\\2>(</meta>)? *");
            match = regex.Match(text);
            if (match.Success)
            {
                // has the lockFormatting meta tag been added already?
                var regexSuppress = new Regex("\\s*<meta\\s+name=(['\\\"])lockFormatting\\1 content=(['\\\"])(.*)\\2>(</meta>)? *");
                var matchSuppress = regexSuppress.Match(text);
                if (matchSuppress.Success)
                {
                    // the meta tag already exists, make sure the value is "true"
                    if (matchSuppress.Groups[3].Value.ToLower() != "true")
                    {
                        text = text.Substring(0, matchSuppress.Groups[3].Index) + "true"
                               + text.Substring(matchSuppress.Groups[3].Index + matchSuppress.Groups[3].Length);
                    }
                }
                else
                {
                    // the meta tag has not been added, add it now
                    text = text.Insert(match.Index + match.Length,
                                       "\r\n    <meta name=\"lockFormatting\" content=\"true\"></meta>");
                }
            }

            return(text);
        }
예제 #26
0
        private void ShowBook(bool updatePreview = true)
        {
            if (_bookSelection.CurrentSelection == null || !_visible)
            {
                HidePreview();
            }
            else
            {
                Debug.WriteLine("LibraryBookView.ShowBook() currentselection ok");

                _readmeBrowser.Visible = false;
                _splitContainerForPreviewAndAboutBrowsers.Visible = true;
                if (updatePreview && !TroubleShooterDialog.SuppressBookPreview)
                {
                    var previewDom = _bookSelection.CurrentSelection.GetPreviewHtmlFileForWholeBook();
                    XmlHtmlConverter.MakeXmlishTagsSafeForInterpretationAsHtml(previewDom.RawDom);
                    var fakeTempFile = BloomServer.MakeSimulatedPageFileInBookFolder(previewDom, setAsCurrentPageForDebugging: false, source: BloomServer.SimulatedPageFileSource.Preview);
                    _reactBookPreviewControl.Props = new { initialBookPreviewUrl = fakeTempFile.Key }; // need this for initial selection
                    _webSocketServer.SendString("bookStatus", "changeBook", fakeTempFile.Key);         // need this for changing selection display
                    _webSocketServer.SendEvent("bookStatus", "reload");                                // need this for changing selection's book info display if team collection
                    _reactBookPreviewControl.Visible = true;
                    RecordAndCleanupFakeFiles(fakeTempFile);
                }
                _splitContainerForPreviewAndAboutBrowsers.Panel2Collapsed = true;
                if (_bookSelection.CurrentSelection.HasAboutBookInformationToShow)
                {
                    if (RobustFile.Exists(_bookSelection.CurrentSelection.AboutBookHtmlPath))
                    {
                        _splitContainerForPreviewAndAboutBrowsers.Panel2Collapsed = false;
                        _readmeBrowser.Navigate(_bookSelection.CurrentSelection.AboutBookHtmlPath, false);
                        _readmeBrowser.Visible = true;
                    }
                    else if (RobustFile.Exists(_bookSelection.CurrentSelection.AboutBookMdPath))
                    {
                        _splitContainerForPreviewAndAboutBrowsers.Panel2Collapsed = false;
                        var md       = new Markdown();
                        var contents = RobustFile.ReadAllText(_bookSelection.CurrentSelection.AboutBookMdPath);
                        _readmeBrowser.NavigateRawHtml(string.Format("<html><head><meta charset=\"utf-8\"/></head><body>{0}</body></html>", md.Transform(contents)));
                        _readmeBrowser.Visible = true;
                    }
                }
                _reshowPending = false;
            }
        }
예제 #27
0
        /// <summary>
        /// All we do at this point is make a file with a ".doc" extension and open it.
        /// </summary>
        /// <remarks>
        /// The .doc extension allows the operating system to recognize which program
        /// should open the file, and the program (whether Microsoft Word or LibreOffice
        /// or OpenOffice) seems to handle HTML content just fine.
        /// </remarks>
        public void ExportDocFormat(string path)
        {
            string sourcePath = _bookSelection.CurrentSelection.GetPathHtmlFile();

            if (RobustFile.Exists(path))
            {
                RobustFile.Delete(path);
            }
            // Linux (Trusty) LibreOffice requires slightly different metadata at the beginning
            // of the file in order to recognize it as HTML.  Otherwise it opens the file as raw
            // HTML (See https://silbloom.myjetbrains.com/youtrack/issue/BL-2276 if you don't
            // believe me.)  I don't know any perfect way to add this information to the file,
            // but a simple string replace should be safe.  This change works okay for both
            // Windows and Linux and for all three programs (Word, OpenOffice and Libre Office).
            string content      = RobustFile.ReadAllText(sourcePath);
            string fixedContent = content.Replace("<meta charset=\"UTF-8\">", "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">");

            RobustFile.WriteAllText(path, fixedContent);
        }
예제 #28
0
        public static bool IsPathInDropboxFolder(string path)
        {
            try
            {
                var searchPath = Platform.IsLinux ? path : path.ToLowerInvariant();
                foreach (var jsonPath in s_jsonPaths)
                {
                    var fixedPath = Environment.ExpandEnvironmentVariables(jsonPath);
                    if (RobustFile.Exists(fixedPath))
                    {
                        var json = RobustFile.ReadAllText(fixedPath, Encoding.UTF8);
                        // It's a bit of a toss-up whether to use a Regex or a JSON parser here. The documentation at the
                        // URL above has several mistakes. There are at least a couple of paths to navigate through the
                        // JSON to possible dropbox folder paths (personal.path and business.path) and one of these is not
                        // documented for Linux; could there be others they have not mentioned? Then we'd also have to handle
                        // the file possibly not parsing. This Regex simply looks for any occurrence of "path": "wherever".
                        foreach (var match in new Regex(s_pathMatchPattern).Matches(json).Cast <Match>())
                        {
                            var dropboxRoot = match.Groups[1].Value;
                            if (!Platform.IsLinux)
                            {
                                dropboxRoot = dropboxRoot.ToLowerInvariant().Replace(@"\\", @"\");
                            }

                            if (searchPath.StartsWith(dropboxRoot))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // If something goes wrong trying to figure out whether it's a Dropbox folder,
                // just assume it isn't. Nothing crucial currently depends on knowing this, just
                // some more helpful error reporting if there's a problem.
                NonFatalProblem.ReportSentryOnly(ex);
            }

            return(false);
        }
예제 #29
0
        public string GetDescription()
        {
            const string desc = "description";

            try
            {
                // try to read English XMatter pack description first
                // we need version number at least
                var pathEnglish = Path.Combine(PathToFolder, desc + "-en.txt");
                if (!RobustFile.Exists(pathEnglish))
                {
                    return(string.Empty);
                }

                var englishDescription = RobustFile.ReadAllText(pathEnglish);
                if (!englishDescription.StartsWith("[V"))
                {
                    return(englishDescription);
                }

                // Once we put [V1] in the english description we could have translations
                // for other UI languages.
                var uiLangId  = LocalizationManager.UILanguageId;
                var enVersion = GetVersionNumberString(englishDescription);
                englishDescription = StripVersionOff(englishDescription);
                var pathUiLang = Path.Combine(PathToFolder, desc + "-" + uiLangId + ".txt");
                if (uiLangId == "en" || !RobustFile.Exists(pathUiLang))
                {
                    return(englishDescription);
                }

                var uiLangDescription = RobustFile.ReadAllText(pathUiLang);
                var uiVersion         = GetVersionNumberString(uiLangDescription);
                uiLangDescription = StripVersionOff(uiLangDescription);
                return(enVersion > uiVersion || uiVersion == 0 || uiLangDescription.Length < 2 ? englishDescription : uiLangDescription);
            }
            catch (Exception error)
            {
                return(error.Message);
            }
        }
        private void SetupEpubControlContent()
        {
            _model.EpubMaker.StageEpub();

            var fileLocator = _model.BookSelection.CurrentSelection.GetFileLocator();
            var root        = fileLocator.LocateDirectoryWithThrow("Readium");
            var tempFolder  = Path.GetDirectoryName(_model.StagingDirectory);

            // This is kludge. I hope it can be improved. To make a preview we currently need all the Readium
            // files in a folder that is a parent of the staging folder containing the book content.
            // This allows us to tell Readium about the book by passing the name of the folder using the ?ePUB=
            // URL parameter. It doesn't work to use the original Readium file and make the parameter a full path.
            // It's possible that there is some variation that would work, e.g., make the param a full file:/// url
            // to the book folder. It's also possible we could get away with only copying the HTML file itself,
            // if we modified it to have localhost: links to the JS and CSS. Haven't tried this yet. The current
            // approach at least works.
            DirectoryUtilities.CopyDirectoryContents(root, tempFolder);

            var englishTemplatePath   = fileLocator.LocateFileWithThrow("ePUB" + Path.DirectorySeparatorChar + "bloomEpubPreview-en.html");
            var localizedTemplatePath = BloomFileLocator.GetBestLocalizedFile(englishTemplatePath);

            var audioSituationClass = "noAudioAvailable";

            if (_model.EpubMaker.PublishWithoutAudio)
            {
                audioSituationClass = "haveAudioButNotMakingTalkingBook";
            }
            else if (_model.BookHasAudio)
            {
                audioSituationClass = "isTalkingBook";
            }

            var htmlContents = RobustFile.ReadAllText(localizedTemplatePath)
                               .Replace("{EPUBFOLDER}", Path.GetFileName(_model.StagingDirectory))
                               .Replace("_AudioSituationClass_", audioSituationClass);

            var previewHtmlInstancePath = Path.Combine(tempFolder, "bloomEpubPreview.htm");

            RobustFile.WriteAllText(previewHtmlInstancePath, htmlContents);
            _epubPreviewBrowser.Navigate(previewHtmlInstancePath.ToLocalhost(), false);
        }