コード例 #1
0
        private static TestFolderTeamCollection MakeAndRenameBook(TemporaryFolder collectionFolder,
                                                                  TemporaryFolder repoFolder,
                                                                  out string bookPath, out string newBookFolderPath)
        {
            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);
            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 newBookPath = Path.Combine(bookFolderPath, "Renamed book");

            RobustFile.Move(bookPath, newBookPath);
            newBookFolderPath = Path.Combine(collectionFolder.FolderPath, "Renamed book");
            Directory.Move(bookFolderPath, newBookFolderPath);
            tc.HandleBookRename("My book", "Renamed book");
            return(tc);
        }
コード例 #2
0
 public void CopyBiggerThanBuffer()
 {
     using (var temp = new TempFile())
     {
         var bldr = new StringBuilder();
         for (int i = 0; i < 512; i++)
         {
             bldr.AppendLine("This is a test");
         }
         var input = bldr.ToString();
         Assert.That(input.Length > 4096);
         var oldBufSize = RobustFile.BufferSize;
         RobustFile.BufferSize = 4096;                 // To avoid writing a large file in a unit test
         RobustFile.WriteAllText(temp.Path, input);
         using (var output = new TempFile())
         {
             RobustFile.Delete(output.Path);                     // apparently we can encounter a left-over temp file
             RobustFile.Copy(temp.Path, output.Path);
             Assert.That(File.ReadAllText(output.Path), Is.EqualTo(input));
         }
         RobustFile.BufferSize = oldBufSize;
     }
 }
コード例 #3
0
        public void NewBook_RaisesNewBookEvent()
        {
            var newBookPath = Path.Combine(_repoFolder.FolderPath, "Books", "A new book.bloom");
            var newBookName = "";

            _collection.StartMonitoring();
            // used to wait for the OS notification to raise the event
            ManualResetEvent newbookRaised = new ManualResetEvent(false);

            _collection.NewBook += (sender, args) =>
            {
                newBookName = args.BookFileName;
                newbookRaised.Set();
            };
            RobustFile.WriteAllText(newBookPath, @"Newly added book");             // no, not a zip at all
            var waitSucceeded = newbookRaised.WaitOne(1000);

            _collection.StopMonitoring();
            RobustFile.Delete(newBookPath);

            Assert.IsTrue(waitSucceeded, "New book was not raised");
            Assert.That(newBookName, Is.EqualTo("A new book.bloom"));
        }
コード例 #4
0
ファイル: ReadersApi.cs プロジェクト: sujeffreyl/BloomDesktop
        /// <summary>Gets the contents of a Text file</summary>
        /// <param name="fileName"></param>
        /// <param name="wordFileType"></param>
        private string GetTextFileContents(string fileName, WordFileType wordFileType)
        {
            var path = Path.Combine(Path.GetDirectoryName(CurrentBook.CollectionSettings.SettingsFilePath),
                                    wordFileType == WordFileType.AllowedWordsFile ? "Allowed Words" : "Sample Texts");

            path = Path.Combine(path, fileName);

            if (!RobustFile.Exists(path))
            {
                return(String.Empty);
            }

            // first try utf-8/ascii encoding (the .Net default)
            var text = RobustFile.ReadAllText(path);

            // If the "unknown" character (65533) is present, C# did not sucessfully decode the file. Try the system default encoding and codepage.
            if (text.Contains((char)65533))
            {
                text = RobustFile.ReadAllText(path, Encoding.Default);
            }

            return(text);
        }
コード例 #5
0
 private void ForceDocumentCompleted()
 {
     Cleanup();
     while (_pending.Count > 0)
     {
         var task = _pending[0];
         _pending.RemoveAt(0);
         // If the file doesn't exist, calling _current.Browser.Navigate() results in the program
         // silently stopping on Linux.  This should never happen with the check made above for
         // superceded navigation requests before posting a pending navigation, but a race could
         // occur between the old file being deleted, the next pending request being handled, and
         // the new file being sent as a navigation requesting.  So we have this check as a backstop.
         // (I always believe in both belts and suspenders, don't you?)  This is part of the fix
         // for https://jira.sil.org/browse/BL-863.
         if (!task.Url.StartsWith("http://") && !RobustFile.Exists(task.Url))
         {
             Debug.Assert(false, String.Format(@"DEBUG: NavigationIsolator.ForceDocumentCompleted(): new file to display (""{0}"") does not exist!??", task.Url));
             continue;
         }
         StartTask(task);
         return;
     }
 }
コード例 #6
0
        public void ForgetChanges_HtmlChangeAndRename_UndoesBoth()
        {
            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);

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

                    Assert.That(changedFolders.Count, Is.EqualTo(2));
                    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[1], Is.EqualTo(newBookFolderPath));
                    Assert.That(changedFolders[0], Is.EqualTo(Path.GetDirectoryName(bookPath)));
                }
            }
        }
コード例 #7
0
        private static void RemoveUnwantedVideoFiles(string destDirName, IEnumerable <string> videoFilesToInclude)
        {
            // If videoFilesToInclude is null or empty, ALL video files in the video subdirectory will be deleted.
            // This likely means that they aren't referenced in the Book's .htm file, although someday there could be
            // other reasons to not include them.
            var videoDir = BookStorage.GetVideoFolderPath(destDirName);

            if (!Directory.Exists(videoDir))
            {
                return;
            }

            foreach (var videoFilePath in Directory.EnumerateFiles(videoDir))
            {
                // videoFilesToInclude strings do not include timings, but do include "video/" prefix,
                // so include the prefix in our Contains() test.
                var fileName = BookStorage.GetNormalizedPathForOS(Path.GetFileName(videoFilePath));
                if (videoFilesToInclude == null || !videoFilesToInclude.Contains(BookStorage.GetVideoFolderName + fileName))
                {
                    RobustFile.Delete(videoFilePath);
                }
            }
        }
コード例 #8
0
                  new[] { "another-image.svg", "another-image.png" })]                                                               // use default svg if no landscape
        public void InjectXMatter_BrandingApi_SelectsRightOrientationImage(string orientation, string expectedFileName,
                                                                           string expectedImageContent, string[] imageFilesToCreate)
        {
            using (var tempFolder = new TemporaryFolder("InjectXMatter_Landscape_PrefersLandscapeImage" + new Random().Next()))
            {
                var bookFolder = Path.Combine(tempFolder.FolderPath, "book");
                Directory.CreateDirectory(bookFolder);
                var srcFolder = Path.Combine(tempFolder.FolderPath, "source");
                Directory.CreateDirectory(srcFolder);
                foreach (var fileName in imageFilesToCreate)
                {
                    var srcImagePath = Path.Combine(srcFolder, fileName);
                    // yes, write the file name as its content, so we can identify which file was copied.
                    File.WriteAllText(srcImagePath, fileName);
                }

                var frontMatterDom = new XmlDocument();
                frontMatterDom.LoadXml(@"<html><head> <link href='file://blahblah\\a5portrait.css' type='text/css' /></head><body>
						 <div class='bloom-page cover coverColor bloom-frontMatter' data-page='required'>
							<img class='branding' src='/bloom/api/branding/image?id="                             + Path.Combine(srcFolder, expectedFileName) +
                                       @"' type='image/svg'/>
						</div></body></html>"                        );
                var helper = CreatePaperSaverHelper();
                helper.XMatterDom = frontMatterDom;

                var layout = new Layout()
                {
                    SizeAndOrientation = SizeAndOrientation.FromString(orientation)
                };

                helper.InjectXMatter(_dataSet.WritingSystemAliases, layout, "Default", bookFolder);
                AssertThatXmlIn.Dom(_dom.RawDom).HasSpecifiedNumberOfMatchesForXpath("//img[@src='" + expectedFileName + "']", 1);
                var outputImagePath = Path.Combine(bookFolder, expectedFileName);
                Assert.That(File.Exists(outputImagePath));
                Assert.That(RobustFile.ReadAllText(outputImagePath), Is.EqualTo(expectedImageContent));
            }
        }
コード例 #9
0
ファイル: XMatterHelper.cs プロジェクト: gmartin7/myBloomFork
        public static string GetBestDeviceXMatterAvailable(string xmatterName, IFileLocator fileLocator)
        {
            if (xmatterName.EndsWith("Device"))
            {
                return(xmatterName);
            }

            // Look to see if there is a special Device version of this xmatter
            var deviceXmatterName = $"{xmatterName}-Device";
            var directoryPath     = GetXMatterDirectory(deviceXmatterName, fileLocator, null, false, true);

            if (directoryPath != null)
            {
                return(deviceXmatterName);
            }

            // Look in the stylesheet and see if it already handles device layout
            try
            {
                var plainXmatterDirectory = GetXMatterDirectory(xmatterName, fileLocator, null, false, true);
                if (plainXmatterDirectory != null)
                {
                    var cssPath = Path.Combine(plainXmatterDirectory, GetStyleSheetFileName(xmatterName));
                    if (RobustFile.ReadAllText(cssPath).Contains(".Device16x9"))
                    {
                        return(xmatterName);
                    }
                }
            }
            catch (Exception)
            {
                // swallow and fall back to dedicated device xmatter
            }

            // use the default Device xmatter which is just named "Device"
            return("Device");
        }
コード例 #10
0
 public static void WriteSpreadsheet(InternalSpreadsheet spreadsheet, string path)
 {
     using (var package = new ExcelPackage())
     {
         var worksheet = package.Workbook.Worksheets.Add("BloomBook");
         int r         = 0;
         foreach (var row in spreadsheet.AllRows())
         {
             r++;
             for (var c = 0; c < row.Count; c++)
             {
                 // Enhance: Excel complains about cells that contain pure numbers
                 // but are created as strings. We could possibly tell it that cells
                 // that contain simple numbers can be treated accordingly.
                 // It might be helpful for some uses of the group-on-page-index
                 // if Excel knew to treat them as numbers.
                 worksheet.Cells[r, c + 1].Value = row.GetCell(c).Content;
             }
         }
         // Review: is this helpful? Excel typically makes very small cells, so almost
         // nothing of a cell's content can be seen, and that only markup. But it also
         // starts out with very narrow cells, so WrapText makes them almost unmanageably tall.
         worksheet.Cells[1, 1, r, spreadsheet.ColumnCount].Style.WrapText = true;
         try
         {
             RobustFile.Delete(path);
             var xlFile = new FileInfo(path);
             package.SaveAs(xlFile);
         }
         catch (Exception ex)
         {
             Console.WriteLine("Writing Spreadsheet failed. Do you have it open in Excel?");
             Console.WriteLine(ex.Message);
             Console.WriteLine(ex.StackTrace);
         }
     }
 }
コード例 #11
0
        /// <summary>
        /// Fix the standard CSS files to replace any fonts listed in badFonts with the defaultFont value.
        /// </summary>
        public static void FixCssReferencesForBadFonts(string cssFolderPath, string defaultFont, HashSet <string> badFonts)
        {
            // Note that the font may be referred to in defaultLangStyles.css, in customCollectionStyles.css, or in a style defined in the HTML.
            // This method handles the .css files.
            var defaultLangStyles = Path.Combine(cssFolderPath, "defaultLangStyles.css");

            if (RobustFile.Exists(defaultLangStyles))
            {
                var cssTextOrig = RobustFile.ReadAllText(defaultLangStyles);
                var cssText     = cssTextOrig;
                foreach (var font in badFonts)
                {
                    var cssRegex = new System.Text.RegularExpressions.Regex($"font-family:\\s*'?{font}'?;");
                    cssText = cssRegex.Replace(cssText, $"font-family: '{defaultFont}';");
                }
                if (cssText != cssTextOrig)
                {
                    RobustFile.WriteAllText(defaultLangStyles, cssText);
                }
            }
            var customCollectionStyles = Path.Combine(cssFolderPath, "customCollectionStyles.css");

            if (RobustFile.Exists(customCollectionStyles))
            {
                var cssTextOrig = RobustFile.ReadAllText(customCollectionStyles);
                var cssText     = cssTextOrig;
                foreach (var font in badFonts)
                {
                    var cssRegex = new System.Text.RegularExpressions.Regex($"font-family:\\s*'?{font}'?;");
                    cssText = cssRegex.Replace(cssText, $"font-family: '{defaultFont}';");
                }
                if (cssText != cssTextOrig)
                {
                    RobustFile.WriteAllText(customCollectionStyles, cssText);
                }
            }
        }
コード例 #12
0
 public static string GetDropboxFolderPath()
 {
     try
     {
         // Prefer a "business" dropbox to a "personal" dropbox if one exists.
         var pathPrefixes = new[] { "\"business\":\\s*{[^{}]*", "\"personal\":\\s*{[^{}]*" };
         foreach (var jsonPath in s_jsonPaths)
         {
             var fixedPath = Environment.ExpandEnvironmentVariables(jsonPath);
             if (RobustFile.Exists(fixedPath))
             {
                 var json = RobustFile.ReadAllText(fixedPath, Encoding.UTF8);
                 foreach (var prefix in pathPrefixes)
                 {
                     var pathMatch = prefix + s_pathMatchPattern;
                     foreach (var match in new Regex(pathMatch).Matches(json).Cast <Match>())
                     {
                         var dropboxRoot = match.Groups[1].Value;
                         if (!Platform.IsLinux)
                         {
                             dropboxRoot = dropboxRoot.Replace(@"\\", @"\");
                         }
                         if (System.IO.Directory.Exists(dropboxRoot))
                         {
                             return(dropboxRoot);
                         }
                     }
                 }
             }
         }
     }
     catch (Exception ex)
     {
         NonFatalProblem.ReportSentryOnly(ex);
     }
     return(null);
 }
コード例 #13
0
        private void SetupCssTests()
        {
            // create collection directory
            Directory.CreateDirectory(_collectionPath);

            // customCollectionStyles.css
            var cssFile = Path.Combine(_collectionPath, "customCollectionStyles.css");

            RobustFile.WriteAllText(cssFile, @".customCollectionStylesCssTest{}");

            // create book directory
            var bookPath = Path.Combine(_collectionPath, "TestBook");

            Directory.CreateDirectory(bookPath);

            // defaultLangStyles.css
            cssFile = Path.Combine(bookPath, "defaultLangStyles.css");
            RobustFile.WriteAllText(cssFile, @".defaultLangStylesCssTest{}");

            cssFile = Path.Combine(bookPath, "customCollectionStyles.css");
            RobustFile.WriteAllText(cssFile, @".customCollectionStylesCssTest{}");

            cssFile = Path.Combine(bookPath, "ForUnitTest-XMatter.css");
            RobustFile.WriteAllText(cssFile, @"This is the one in the book");

            // Factory-XMatter.css
            cssFile = Path.Combine(bookPath, "Factory-XMatter.css");
            RobustFile.WriteAllText(cssFile, @".factoryXmatterCssTest{}");

            // customBookStyles.css
            cssFile = Path.Combine(bookPath, "customBookStyles.css");
            RobustFile.WriteAllText(cssFile, @".customBookStylesCssTest{}");

            // miscStyles.css - a file name not distributed with or created by Bloom
            cssFile = Path.Combine(bookPath, "miscStyles.css");
            RobustFile.WriteAllText(cssFile, @".miscStylesCssTest{}");
        }
コード例 #14
0
        private void HandleVideoStatisticsRequest(ApiRequest request)
        {
            if (request.HttpMethod != HttpMethods.Get)
            {
                throw new ApplicationException(request.LocalPath() + " only implements 'get'");
            }
            lock (request)
            {
                string    videoFilePath;
                decimal[] timings;
                if (!GetVideoDetailsFromRequest(request, false, out videoFilePath, out timings))
                {
                    return;                     // request.Failed was called inside the above method
                }
                if (!RobustFile.Exists(videoFilePath))
                {
                    request.Failed("Cannot find video file (" + videoFilePath + ")");
                    return;
                }

                if (string.IsNullOrEmpty(FfmpegProgram))
                {
                    request.Failed("Cannot find ffmpeg program");
                    return;
                }

                var fileInfo    = new FileInfo(videoFilePath);
                var sizeInBytes = fileInfo.Length;

                var output = RunFfmpegOnVideoToGetStatistics(request, videoFilePath);

                var statistics = ParseFfmpegStatistics(output, sizeInBytes);
                statistics.Add("startSeconds", timings[0].ToString("F1"));
                statistics.Add("endSeconds", timings[1].ToString("F1"));
                request.ReplyWithJson(statistics);
            }
        }
コード例 #15
0
        public void CreateZipFile_NonAsciiEntryNames()
        {
            // this test is to make sure non-ascii file names are being stored and retrieved correctly

            const string fileName     = "मराठी मैथिली संस्कृत हिन्.htm";
            const string fileContents = @"File contents.";

            using (var tempFile = TempFile.WithFilenameInTempFolder(fileName))
            {
                RobustFile.WriteAllText(tempFile.Path, fileContents);

                using (var bookZip = TempFile.WithExtension(".zip"))
                {
                    var zip = new BloomZipFile(bookZip.Path);
                    zip.AddTopLevelFile(tempFile.Path);
                    zip.Save();

                    using (var zip2 = new ZipFile(bookZip.Path))
                    {
                        foreach (ZipEntry zipEntry in zip2)
                        {
                            Console.Out.WriteLine(zipEntry.Name);
                            Assert.That(zipEntry.Name, Is.EqualTo(fileName));

                            using (var inStream = zip2.GetInputStream(zipEntry))
                            {
                                byte[] buffer = new byte[zipEntry.Size];
                                ICSharpCode.SharpZipLib.Core.StreamUtils.ReadFully(inStream, buffer);

                                var testStr = Encoding.Default.GetString(buffer);
                                Assert.That(testStr, Is.EqualTo(fileContents));
                            }
                        }
                    }
                }
            }
        }
コード例 #16
0
ファイル: RobustIO.cs プロジェクト: gmartin7/myBloomFork
 /// <summary>
 /// Get the image metadata from the file as reliably as possible.
 /// </summary>
 public static Metadata MetadataFromFile(string path)
 {
     // Books sometimes use image files that are mislabeled.  JPEG files sometimes have been given
     // .png extensions, and it's likely that PNG files have been given .jpg extensions.  TagLib crashes
     // trying to read the metadata in such cases, so we prevent that particular crash in this method.
     if (Path.GetExtension(path).ToLowerInvariant() == ".png" && ImageUtils.IsJpegFile(path))
     {
         using (var jpegFile = TempFile.WithExtension(".jpg"))
         {
             RobustFile.Copy(path, jpegFile.Path, true);
             return(MetadataFromFileInternal(jpegFile.Path));
         }
     }
     if (ImageUtils.HasJpegExtension(path) && ImageUtils.IsPngFile(path))
     {
         using (var pngFile = TempFile.WithExtension(".png"))
         {
             RobustFile.Copy(path, pngFile.Path, true);
             return(MetadataFromFileInternal(pngFile.Path));
         }
     }
     // Assume everything is okay.
     return(MetadataFromFileInternal(path));
 }
コード例 #17
0
        public void Setup()
        {
            var locations = new List <string>();

            locations.Add(BloomFileLocator.GetFactoryXMatterDirectory());
            _xMatterParentFolder = new TemporaryFolder("UserCollection");
            _xMatterFolder       = new TemporaryFolder(_xMatterParentFolder, "User-XMatter");
            locations.Add(_xMatterParentFolder.Path);
            RobustFile.WriteAllText(Path.Combine(_xMatterFolder.Path, "SomeRandomXYZABCStyles.css"), "Some arbitrary test data");
            RobustFile.WriteAllText(Path.Combine(_xMatterFolder.Path, "Decodable Reader.css"), "Fake DR test data");
            //locations.Add(XMatterAppDataFolder);
            //locations.Add(XMatterCommonDataFolder);
            _xMatterFinder = new XMatterPackFinder(locations);

            _otherFilesForTestingFolder = new TemporaryFolder("BloomFileLocatorTests");
            var userInstalledSearchPaths = new List <string>(ProjectContext.GetFoundFileLocations());

            userInstalledSearchPaths.Add(_otherFilesForTestingFolder.Path);
            _fileLocator = new BloomFileLocator(new CollectionSettings(), _xMatterFinder, ProjectContext.GetFactoryFileLocations(), userInstalledSearchPaths,
                                                ProjectContext.GetAfterXMatterFileLocations());

            //Without this, tests can interact with one another, leaving the language set as something unexpected.
            LocalizationManager.SetUILanguage("en", false);
        }
コード例 #18
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 ignore not being able to get the version.
            }

            return("unknown", true);
        }
コード例 #19
0
 /// <summary>
 /// branding folders can optionally contain a settings.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
     {
         var settingsPath = BloomFileLocator.GetOptionalBrandingFile(brandingNameOrFolderPath, "settings.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",
                                        "settings.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);
 }
コード例 #20
0
        public void CopyAllBooksFromSharedToLocalFolder_RetrievesExpectedBooks_AndChecksums()
        {
            using (var destFolder = new TemporaryFolder("GetBooks_Retrieves"))
            {
                _collection.CopyAllBooksFromRepoToLocalFolder(destFolder.FolderPath);
                var destBookFolder = Path.Combine(destFolder.FolderPath, "My book");
                var destBookPath   = Path.Combine(destBookFolder, "My book.htm");
                Assert.That(RobustFile.ReadAllText(destBookPath), Is.EqualTo("This is just a dummy"));
                var destCssPath = Path.Combine(destBookFolder, "BasicLayout.css");
                Assert.That(RobustFile.ReadAllText(destCssPath), Is.EqualTo("This is another dummy"));
                var destAudioDirectory = Path.Combine(destBookFolder, "audio");
                var destMp3Path        = Path.Combine(destAudioDirectory, "rubbish.mp3");
                Assert.That(RobustFile.ReadAllText(destMp3Path), Is.EqualTo("Fake mp3"));

                var anotherDestBookFolder = Path.Combine(destFolder.FolderPath, kAnotherBook);
                var anotherDestBookPath   = Path.Combine(anotherDestBookFolder, kAnotherBook + ".htm");
                Assert.That(RobustFile.ReadAllText(anotherDestBookPath), Is.EqualTo("This is just a dummy for another book"));

                Assert.That(Directory.EnumerateDirectories(destFolder.FolderPath).Count(), Is.EqualTo(2));

                AssertStatusMatch(destFolder.FolderPath, "My book");
                AssertStatusMatch(destFolder.FolderPath, kAnotherBook);
            }
        }
コード例 #21
0
        private void Recorder_Stopped(IAudioRecorder arg1, ErrorEventArgs arg2)
        {
            Recorder.Stopped -= Recorder_Stopped;
            Directory.CreateDirectory(System.IO.Path.GetDirectoryName(PathToRecordableAudioForCurrentSegment));             // make sure audio directory exists
            try
            {
                var minimum = TimeSpan.FromMilliseconds(300);           // this is arbitrary
                AudioRecorder.TrimWavFile(PathToTemporaryWav, PathToRecordableAudioForCurrentSegment, new TimeSpan(), TimeSpan.FromMilliseconds(_collectionAudioTrimEndMilliseconds), minimum);
                RobustFile.Delete(PathToTemporaryWav);                  // Otherwise, these continue to clutter up the temp directory.
            }
            catch (Exception error)
            {
                Logger.WriteEvent(error.Message);
                RobustFile.Copy(PathToTemporaryWav, PathToRecordableAudioForCurrentSegment, true);
            }

            //We could put this off entirely until we make the ePUB.
            //I'm just gating this for now because maybe the thought was that it's better to do it a little at a time?
            //That's fine so long as it doesn't make the UI unresponsive on slow machines.
            var mp3Path = _mp3Encoder.Encode(PathToRecordableAudioForCurrentSegment);

            // Got a good new recording, can safely clean up all backups related to old one.
            foreach (var path in Directory.EnumerateFiles(
                         Path.GetDirectoryName(PathToRecordableAudioForCurrentSegment),
                         Path.GetFileNameWithoutExtension(PathToRecordableAudioForCurrentSegment) + "*" + ".bak"))
            {
                RobustFile.Delete(path);
            }

            // BL-7617 Don't keep .wav file after .mp3 is created successfully.
            if (!string.IsNullOrEmpty(mp3Path) && File.Exists(mp3Path))
            {
                RobustFile.Delete(PathToRecordableAudioForCurrentSegment);
            }
            _completingRecording.Set();             // will release HandleAudioFileRequest if it is waiting.
        }
コード例 #22
0
        private void RestartBloom(string newInstallDir)
        {
            Control ancestor = Parent;

            while (ancestor != null && !(ancestor is Shell))
            {
                ancestor = ancestor.Parent;
            }
            if (ancestor == null)
            {
                return;
            }
            var shell        = (Shell)ancestor;
            var pathToNewExe = Path.Combine(newInstallDir, Path.ChangeExtension(Application.ProductName, ".exe"));

            if (!RobustFile.Exists(pathToNewExe))
            {
                return;                 // aargh!
            }
            shell.QuitForVersionUpdate = true;
            Process.Start(pathToNewExe);
            Thread.Sleep(2000);
            shell.Close();
        }
コード例 #23
0
        /// <summary>
        /// Delete a recording segment, as requested by the Clear button in the talking book tool.
        /// The corresponding mp3 should also be deleted.
        /// </summary>
        /// <param name="fileUrl"></param>
        private void HandleDeleteSegment(ApiRequest request)
        {
            var path    = GetPathToSegment(request.RequiredParam("id"));
            var mp3Path = Path.ChangeExtension(path, "mp3");
            var success = true;

            if (RobustFile.Exists(path))
            {
                success = DeleteFileReportingAnyProblem(path);
            }
            if (RobustFile.Exists(mp3Path))
            {
                success &= DeleteFileReportingAnyProblem(mp3Path);
            }

            if (success)
            {
                request.PostSucceeded();
            }
            else
            {
                request.Failed("could not delete at least one file");
            }
        }
コード例 #24
0
        /// <summary>
        /// Delete a file (typically a recording, as requested by the Clear button in the talking book tool)
        /// </summary>
        /// <param name="fileUrl"></param>
        private void HandleDeleteSegment(ApiRequest request)
        {
            var path = GetPathToSegment(request.RequiredParam("id"));

            if (!RobustFile.Exists(path))
            {
                request.Succeeded();
            }
            else
            {
                try
                {
                    RobustFile.Delete(path);
                    request.Succeeded();
                }
                catch (IOException e)
                {
                    var msg =
                        string.Format(
                            LocalizationManager.GetString("Errors.ProblemDeletingFile", "Bloom had a problem deleting this file: {0}"), path);
                    ErrorReport.NotifyUserOfProblem(e, msg + Environment.NewLine + e.Message);
                }
            }
        }
コード例 #25
0
        private static string GetLocalPathWithoutQuery(string localPath)
        {
            if (localPath.StartsWith(BloomUrlPrefix))
            {
                localPath = localPath.Substring(BloomUrlPrefix.Length);
#if __MonoCS__
                if (localPath.StartsWith("tmp/ePUB"))
                {
                    localPath = "/" + localPath;                        // restore leading slash for full path
                }
#endif
            }
            // and if the file is using localhost:1234/foo.js, at this point it will say "/foo.js", so let's strip off that leading slash
            else if (localPath.StartsWith("/"))
            {
                localPath = localPath.Substring(1);
            }
            if (localPath.Contains("?") && !RobustFile.Exists(localPath))
            {
                var idx = localPath.LastIndexOf("?", StringComparison.Ordinal);
                return(localPath.Substring(0, idx));
            }
            return(localPath);
        }
コード例 #26
0
        // We want to move the file specified in the first path to a new location to use
        // as a backup while we typically replace it.
        // A previous backup, possibly of the same or another file, is no longer needed (if it exists)
        // and should be deleted, if possible, on a background thread.
        // The path to the backup will be updated to the new backup.
        // Typically the new name matches the original with the extension changed to .bak.
        // If necessary (because the desired backup file already exists), we will add a counter
        // to get the a name that is not in use.
        // A goal is (for performance reasons) not to have to wait while a file is deleted
        // (and definitely not while one is copied).
        private static bool PrepareBackupFile(string path, ref string backupPath, ApiRequest request)
        {
            int counter = 0;

            backupPath = path + ".bak";
            var originalExtension   = Path.GetExtension(path);
            var pathWithNoExtension = Path.GetFileNameWithoutExtension(path);

            while (File.Exists(backupPath))
            {
                counter++;
                backupPath = pathWithNoExtension + counter + originalExtension + ".bak";
            }
            // An earlier version copied the file to a temp file. We can't MOVE to a file in the system temp
            // directory, though, because we're not sure it is on the same volume. And sometimes the time
            // required to copy the file was noticeable and resulted in the user starting to speak before
            // the system started recording. So we pay the price of a small chance of backups being left
            // around the book directory to avoid that danger.
            if (RobustFile.Exists(path))
            {
                try
                {
                    RobustFile.Move(path, backupPath);
                }
                catch (Exception err)
                {
                    ErrorReport.NotifyUserOfProblem(err,
                                                    "The old copy of the recording at " + path +
                                                    " is locked up, so Bloom can't record over it at the moment. If it remains stuck, you may need to restart your computer.");
                    request.Failed("Audio file locked");
                    return(false);
                }
            }

            return(true);
        }
コード例 #27
0
        private void SaveSettingsCollectionStylesCss()
        {
            string path = FolderPath.CombineForPath("settingsCollectionStyles.css");

            try
            {
                var sb = new StringBuilder();
                sb.AppendLine("/* These styles are controlled by the Settings dialog box in Bloom. */");
                sb.AppendLine("/* They many be over-ridden by rules in customCollectionStyles.css or customBookStyles.css */");
                AddFontCssRule(sb, "BODY", GetDefaultFontName(), 0);
                AddFontCssRule(sb, "[lang='" + Language1Iso639Code + "']", DefaultLanguage1FontName, Language1LineHeight);
                AddFontCssRule(sb, "[lang='" + Language2Iso639Code + "']", DefaultLanguage2FontName, Language2LineHeight);
                if (!string.IsNullOrEmpty(Language3Iso639Code))
                {
                    AddFontCssRule(sb, "[lang='" + Language3Iso639Code + "']", DefaultLanguage3FontName, Language3LineHeight);
                }
                AddNumberingStyleCssRule(sb, PageNumberStyle);
                RobustFile.WriteAllText(path, sb.ToString());
            }
            catch (Exception error)
            {
                SIL.Reporting.ErrorReport.NotifyUserOfProblem(error, "Bloom was unable to update this file: {0}", path);
            }
        }
コード例 #28
0
        static PublishSettings MigrateSettings(string bookFolderPath)
        {
            // See if we can migrate data from an old metaData.

            var metaDataPath = BookMetaData.MetaDataPath(bookFolderPath);
            var settings     = new PublishSettings();

            try
            {
                if (!RobustFile.Exists(metaDataPath))
                {
                    return(settings);
                }
                var metaDataString = RobustFile.ReadAllText(metaDataPath, Encoding.UTF8);

                // I chose to do this using DynamicJson, rather than just BloomMetaData.FromString() and
                // reading the obsolete properties, in hopes that we can eventually retire the obsolete
                // properties. However, that may not be possible without breaking things when we attempt
                // to load an old meta.json with JsonConvert. Still, at least this approach makes for
                // fewer warnings about use of obsolete methods.
                var metaDataJson = DynamicJson.Parse(metaDataString) as DynamicJson;
                if (metaDataJson.IsDefined("features"))
                {
                    if (metaDataJson.TryGet("features", out string[] features))
コード例 #29
0
        /// <summary>
        /// Causes the specified book contents to be created on disk.
        /// </summary>
        /// <returns>A string containing the path to the book folder</returns>
        /// <remarks>This is a little different than a normal DataBuilder Build(), because we're not really
        /// returning a "book" object like we normally would (we don't have a book object),
        /// but instead we're causing the book to be written to disk.
        /// </remarks>
        public BookFolderBuilder Build()
        {
            Debug.Assert(_containingFolder != null, "_containingFolder is required! Set it via InFolder(...)");
            Debug.Assert(_bookTitle != null, "BookTitle is required. Set it either via WithTitle() or via WithDefaultValues()");

            var bookFolderPath = Path.Combine(_containingFolder, _bookFolderName ?? _bookTitle);

            Directory.CreateDirectory(bookFolderPath);
            BuiltBookFolderPath = bookFolderPath;

            if (_htmContents != null)
            {
                var htmPath = Path.Combine(bookFolderPath, $"{_bookTitle}.htm");
                RobustFile.WriteAllText(htmPath, _htmContents);
                BuiltBookHtmPath = htmPath;
            }

            var meta = new BookMetaData();

            meta.WriteToFolder(bookFolderPath);

            // Returns the builder object again so that callers can call post-build properties
            return(this);
        }
コード例 #30
0
ファイル: TempFiles.cs プロジェクト: gmartin7/myBloomFork
        public static void DeleteFolderThatMayBeInUseAndIfNotFailSilently(string folder)
        {
            if (Directory.Exists(folder))
            {
                try
                {
                    RobustIO.DeleteDirectory(folder, true);
                }
                catch (Exception e)
                {
                    try
                    {
                        Debug.WriteLine(e.Message);
                        //maybe we can at least clear it out a bit
                        string[] files = Directory.GetFiles(folder, "*.*", SearchOption.AllDirectories);
                        foreach (string s in files)
                        {
                            try
                            {
                                RobustFile.Delete(s);
                            }
                            catch (Exception)
                            {
                            }
                        }

                        //sleep and try again (in case some other thread will  let go of them)
                        Thread.Sleep(1000);
                        RobustIO.DeleteDirectory(folder, true);
                    }
                    catch (Exception)
                    {
                    }
                }
            }
        }