/// <summary> /// This method is called when a book opf file has been asynchronously opened. Then we can begin to create a Package for /// the loaded book. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The EventArgs containing the book opf and the parent directory path.</param> private void file_OpenAsyncComplete(object sender, DownloadCompleteEventArgs e) { //Remove the event //This prevents a file from getting opened twice causing an exception when trying to read //the stream of the document since the file has already been opened and is currently stored //in memory. ((IFile)sender).OpenAsyncComplete -= file_OpenAsyncComplete; // TODO: Proper regex or other types of path handling to get the parent directory // Cheat, currently just grab the url given in the query string till the last '/' and use that // as the parent directory string opfParentDirectory = e.UserState.ToString().Substring(0, e.UserState.ToString().LastIndexOf('/')); IPackage package = new Package300(e.Result); package.BookFolder = opfParentDirectory; SetCurrentBook(package); }
/// <summary> /// Gets package information for a book. /// </summary> /// <param name="bookId"></param> /// <returns></returns> public IPackage GetPackage(string bookId) { // TODO: Create a Dictionary for each bookid to cache the results and prevent // recalculating each time. IPackage package = null; IDirectory bookDirectory = GetBookFolder(bookId); if (bookDirectory != null && bookDirectory.Exists) { // TODO: cater for OPF (upper case) IList<IFile> files = bookDirectory.GetFiles("*.opf"); if (files.Count == 1) { // TODO: Determine whether v2 or v3 and instantiate the appropriate IPackage Stream opfStream = files[0].Open(FileMode.Open, FileAccess.Read, FileShare.Read); package = new Package300(opfStream); } else if (files.Count == 0) { throw new Exception("OPF file not found in root directory, " + bookDirectory.FullName); } else if (files.Count > 1) { // It is not legal to have more than one OPF throw new Exception("More than 1 OPF file"); } } // If no book directory is found, then do nothing, a null Package will be returned. return package; }
// Public Methods (1) /// <summary> /// Derives information about the zip package and verifies it is valid. The zip file /// must contain all the files required to process the book according to the DAISY 3.0 /// standard. /// </summary> /// <remarks> /// This method will raise ProgressChanged events as it parses the zip package. Users /// should subscribe to this event before calling this method. /// /// This method must be called before the other methods are accessed. /// </remarks> /// <param name="zipStream">Stream of the zip file.</param> /// <returns></returns> public void ProcessPackage(Stream zipStream) { if (zipStream == null || zipStream.Length == 0) { throw new InvalidPackageException("Stream is null or empty"); } // Initial progress DoProgressChanged(50.00, PROGRESS_MESSAGE); // Obtain a zip reader implementation ZipFileReader zipReader = ZipFileReaderFactory.GetZipFileReader(zipStream); // Note, current implementation of CopyToDictionary always returns filenames in lower case PackageFiles = zipReader.CopyToDictionary; // Check whether this is a version 2.* package var q = from f in PackageFiles where f.Key.EndsWith("ncc.html") select f; if (q.Count() != 0) { Package = new Package202(PackageFiles); } else { q = from f in PackageFiles where f.Key.EndsWith(".opf") select f; if (q.Count() != 0) { // Instantiate a DAISY 3.0 Package with the OPF Stream // All other information is derived from this file. Stream opfStream = q.First().Value; Package = new Package300(opfStream); } else { // Unknown package type. throw new InvalidPackageException("We can't determine the version of the DAISY files. Either there is no OPF file (for version 3.0) or no NCC.HTML (for version 2.02)."); } } DoProgressChanged(100.00, "Inspecting Package Files..."); // Successfully processed zip package Processed = true; }