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(""); } }
/// <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); }
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); }
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); } }
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); }
/// <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)); }
private static string GetMetaJsonModfiedForTemplate(string path) { var meta = BookMetaData.FromString(RobustFile.ReadAllText(path)); meta.IsSuitableForMakingShells = true; return(meta.Json); }
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); }
/// <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); } } }
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); }
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)); }
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") }); }
internal bool CheckAgainstLocalHashfile(string currentHashes, string uploadInfoPath) { if (RobustFile.Exists(uploadInfoPath)) { var previousHashes = RobustFile.ReadAllText(uploadInfoPath); return(currentHashes == previousHashes); } return(false); }
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)); } } }
/// <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); } } }
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")); }
/// <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; }
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 + "}"); }
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); } }
/// <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); }
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; }
/// <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); }
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; } }
/// <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); }
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); }
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); }