mirror of
https://github.com/QL-Win/QuickLook.git
synced 2025-09-23 10:34:51 +00:00
Code reformat and UI tweaks
This commit is contained in:
@@ -1,8 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
// Copyright © 2018 Marco Gavelli and Paddy Xu
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using VersOne.Epub.Schema;
|
||||
|
||||
namespace VersOne.Epub.Internal
|
||||
{
|
||||
@@ -10,31 +25,23 @@ namespace VersOne.Epub.Internal
|
||||
{
|
||||
public static async Task<byte[]> ReadBookCoverAsync(EpubBookRef bookRef)
|
||||
{
|
||||
List<EpubMetadataMeta> metaItems = bookRef.Schema.Package.Metadata.MetaItems;
|
||||
if (metaItems == null || !metaItems.Any())
|
||||
{
|
||||
return null;
|
||||
}
|
||||
EpubMetadataMeta coverMetaItem = metaItems.FirstOrDefault(metaItem => String.Compare(metaItem.Name, "cover", StringComparison.OrdinalIgnoreCase) == 0);
|
||||
if (coverMetaItem == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
if (String.IsNullOrEmpty(coverMetaItem.Content))
|
||||
{
|
||||
var metaItems = bookRef.Schema.Package.Metadata.MetaItems;
|
||||
if (metaItems == null || !metaItems.Any()) return null;
|
||||
var coverMetaItem = metaItems.FirstOrDefault(metaItem =>
|
||||
string.Compare(metaItem.Name, "cover", StringComparison.OrdinalIgnoreCase) == 0);
|
||||
if (coverMetaItem == null) return null;
|
||||
if (string.IsNullOrEmpty(coverMetaItem.Content))
|
||||
throw new Exception("Incorrect EPUB metadata: cover item content is missing.");
|
||||
}
|
||||
EpubManifestItem coverManifestItem = bookRef.Schema.Package.Manifest.FirstOrDefault(manifestItem => String.Compare(manifestItem.Id, coverMetaItem.Content, StringComparison.OrdinalIgnoreCase) == 0);
|
||||
var coverManifestItem = bookRef.Schema.Package.Manifest.FirstOrDefault(manifestItem =>
|
||||
string.Compare(manifestItem.Id, coverMetaItem.Content, StringComparison.OrdinalIgnoreCase) == 0);
|
||||
if (coverManifestItem == null)
|
||||
{
|
||||
throw new Exception(String.Format("Incorrect EPUB manifest: item with ID = \"{0}\" is missing.", coverMetaItem.Content));
|
||||
}
|
||||
if (!bookRef.Content.Images.TryGetValue(coverManifestItem.Href, out EpubByteContentFileRef coverImageContentFileRef))
|
||||
{
|
||||
throw new Exception(String.Format("Incorrect EPUB manifest: item with href = \"{0}\" is missing.", coverManifestItem.Href));
|
||||
}
|
||||
byte[] coverImageContent = await coverImageContentFileRef.ReadContentAsBytesAsync().ConfigureAwait(false);
|
||||
throw new Exception(string.Format("Incorrect EPUB manifest: item with ID = \"{0}\" is missing.",
|
||||
coverMetaItem.Content));
|
||||
if (!bookRef.Content.Images.TryGetValue(coverManifestItem.Href, out var coverImageContentFileRef))
|
||||
throw new Exception(string.Format("Incorrect EPUB manifest: item with href = \"{0}\" is missing.",
|
||||
coverManifestItem.Href));
|
||||
var coverImageContent = await coverImageContentFileRef.ReadContentAsBytesAsync().ConfigureAwait(false);
|
||||
return coverImageContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,4 +1,21 @@
|
||||
using System;
|
||||
// Copyright © 2018 Marco Gavelli and Paddy Xu
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
@@ -13,37 +30,38 @@ namespace VersOne.Epub.Internal
|
||||
return GetChapters(bookRef, bookRef.Schema.Package.Spine, bookRef.Schema.Navigation.NavMap);
|
||||
}
|
||||
|
||||
public static List<EpubChapterRef> GetChapters(EpubBookRef bookRef, EpubSpine spine, List<EpubNavigationPoint> navigationPoints)
|
||||
public static List<EpubChapterRef> GetChapters(EpubBookRef bookRef, EpubSpine spine,
|
||||
List<EpubNavigationPoint> navigationPoints)
|
||||
{
|
||||
List<EpubChapterRef> result = new List<EpubChapterRef>();
|
||||
for (int s = 0; s < spine.Count; s++)
|
||||
var result = new List<EpubChapterRef>();
|
||||
for (var s = 0; s < spine.Count; s++)
|
||||
{
|
||||
EpubSpineItemRef itemRef = spine[s];
|
||||
var itemRef = spine[s];
|
||||
string contentFileName;
|
||||
string anchor;
|
||||
contentFileName = WebUtility.UrlDecode(bookRef.Schema.Package.Manifest.FirstOrDefault(e => e.Id == itemRef.IdRef)?.Href);
|
||||
contentFileName = WebUtility.UrlDecode(bookRef.Schema.Package.Manifest
|
||||
.FirstOrDefault(e => e.Id == itemRef.IdRef)?.Href);
|
||||
anchor = null;
|
||||
if (!bookRef.Content.Html.TryGetValue(contentFileName, out EpubTextContentFileRef htmlContentFileRef))
|
||||
{
|
||||
throw new Exception(String.Format("Incorrect EPUB manifest: item with href = \"{0}\" is missing.", contentFileName));
|
||||
}
|
||||
EpubChapterRef chapterRef = new EpubChapterRef(htmlContentFileRef);
|
||||
if (!bookRef.Content.Html.TryGetValue(contentFileName, out var htmlContentFileRef))
|
||||
throw new Exception(string.Format("Incorrect EPUB manifest: item with href = \"{0}\" is missing.",
|
||||
contentFileName));
|
||||
var chapterRef = new EpubChapterRef(htmlContentFileRef);
|
||||
chapterRef.ContentFileName = contentFileName;
|
||||
chapterRef.Anchor = anchor;
|
||||
chapterRef.Parent = null;
|
||||
var navPoint = navigationPoints.LastOrDefault(nav => spine.Take(s + 1).Select(sp => bookRef.Schema.Package.Manifest.FirstOrDefault(e => e.Id == sp.IdRef)?.Href).Contains(nav.Content.Source.Split('#')[0]));
|
||||
var navPoint = navigationPoints.LastOrDefault(nav =>
|
||||
spine.Take(s + 1)
|
||||
.Select(sp => bookRef.Schema.Package.Manifest.FirstOrDefault(e => e.Id == sp.IdRef)?.Href)
|
||||
.Contains(nav.Content.Source.Split('#')[0]));
|
||||
if (navPoint != null)
|
||||
{
|
||||
chapterRef.Title = navPoint.NavigationLabels.First().Text;
|
||||
}
|
||||
else
|
||||
{
|
||||
chapterRef.Title = $"Chapter {s + 1}";
|
||||
}
|
||||
chapterRef.SubChapters = new List<EpubChapterRef>();
|
||||
result.Add(chapterRef);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using VersOne.Epub.Schema;
|
||||
// Copyright © 2018 Marco Gavelli and Paddy Xu
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace VersOne.Epub.Internal
|
||||
{
|
||||
@@ -7,7 +23,7 @@ namespace VersOne.Epub.Internal
|
||||
{
|
||||
public static EpubContentRef ParseContentMap(EpubBookRef bookRef)
|
||||
{
|
||||
EpubContentRef result = new EpubContentRef
|
||||
var result = new EpubContentRef
|
||||
{
|
||||
Html = new Dictionary<string, EpubTextContentFileRef>(),
|
||||
Css = new Dictionary<string, EpubTextContentFileRef>(),
|
||||
@@ -15,11 +31,11 @@ namespace VersOne.Epub.Internal
|
||||
Fonts = new Dictionary<string, EpubByteContentFileRef>(),
|
||||
AllFiles = new Dictionary<string, EpubContentFileRef>()
|
||||
};
|
||||
foreach (EpubManifestItem manifestItem in bookRef.Schema.Package.Manifest)
|
||||
foreach (var manifestItem in bookRef.Schema.Package.Manifest)
|
||||
{
|
||||
string fileName = manifestItem.Href;
|
||||
string contentMimeType = manifestItem.MediaType;
|
||||
EpubContentType contentType = GetContentTypeByContentMimeType(contentMimeType);
|
||||
var fileName = manifestItem.Href;
|
||||
var contentMimeType = manifestItem.MediaType;
|
||||
var contentType = GetContentTypeByContentMimeType(contentMimeType);
|
||||
switch (contentType)
|
||||
{
|
||||
case EpubContentType.XHTML_1_1:
|
||||
@@ -29,7 +45,7 @@ namespace VersOne.Epub.Internal
|
||||
case EpubContentType.XML:
|
||||
case EpubContentType.DTBOOK:
|
||||
case EpubContentType.DTBOOK_NCX:
|
||||
EpubTextContentFileRef epubTextContentFile = new EpubTextContentFileRef(bookRef)
|
||||
var epubTextContentFile = new EpubTextContentFileRef(bookRef)
|
||||
{
|
||||
FileName = fileName,
|
||||
ContentMimeType = contentMimeType,
|
||||
@@ -44,10 +60,11 @@ namespace VersOne.Epub.Internal
|
||||
result.Css[fileName] = epubTextContentFile;
|
||||
break;
|
||||
}
|
||||
|
||||
result.AllFiles[fileName] = epubTextContentFile;
|
||||
break;
|
||||
default:
|
||||
EpubByteContentFileRef epubByteContentFile = new EpubByteContentFileRef(bookRef)
|
||||
var epubByteContentFile = new EpubByteContentFileRef(bookRef)
|
||||
{
|
||||
FileName = fileName,
|
||||
ContentMimeType = contentMimeType,
|
||||
@@ -66,10 +83,12 @@ namespace VersOne.Epub.Internal
|
||||
result.Fonts[fileName] = epubByteContentFile;
|
||||
break;
|
||||
}
|
||||
|
||||
result.AllFiles[fileName] = epubByteContentFile;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -110,4 +129,4 @@ namespace VersOne.Epub.Internal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,22 @@
|
||||
using System;
|
||||
// Copyright © 2018 Marco Gavelli and Paddy Xu
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -11,93 +27,82 @@ namespace VersOne.Epub.Internal
|
||||
{
|
||||
internal static class NavigationReader
|
||||
{
|
||||
public static async Task<EpubNavigation> ReadNavigationAsync(ZipArchive epubArchive, string contentDirectoryPath, EpubPackage package)
|
||||
public static async Task<EpubNavigation> ReadNavigationAsync(ZipArchive epubArchive,
|
||||
string contentDirectoryPath, EpubPackage package)
|
||||
{
|
||||
EpubNavigation result = new EpubNavigation();
|
||||
string tocId = package.Spine.Toc;
|
||||
if (String.IsNullOrEmpty(tocId))
|
||||
{
|
||||
throw new Exception("EPUB parsing error: TOC ID is empty.");
|
||||
}
|
||||
EpubManifestItem tocManifestItem = package.Manifest.FirstOrDefault(item => String.Compare(item.Id, tocId, StringComparison.OrdinalIgnoreCase) == 0);
|
||||
var result = new EpubNavigation();
|
||||
var tocId = package.Spine.Toc;
|
||||
if (string.IsNullOrEmpty(tocId)) throw new Exception("EPUB parsing error: TOC ID is empty.");
|
||||
var tocManifestItem = package.Manifest.FirstOrDefault(item =>
|
||||
string.Compare(item.Id, tocId, StringComparison.OrdinalIgnoreCase) == 0);
|
||||
if (tocManifestItem == null)
|
||||
{
|
||||
throw new Exception(String.Format("EPUB parsing error: TOC item {0} not found in EPUB manifest.", tocId));
|
||||
}
|
||||
string tocFileEntryPath = ZipPathUtils.Combine(contentDirectoryPath, tocManifestItem.Href);
|
||||
ZipArchiveEntry tocFileEntry = epubArchive.GetEntry(tocFileEntryPath);
|
||||
throw new Exception(
|
||||
string.Format("EPUB parsing error: TOC item {0} not found in EPUB manifest.", tocId));
|
||||
var tocFileEntryPath = ZipPathUtils.Combine(contentDirectoryPath, tocManifestItem.Href);
|
||||
var tocFileEntry = epubArchive.GetEntry(tocFileEntryPath);
|
||||
if (tocFileEntry == null)
|
||||
{
|
||||
throw new Exception(String.Format("EPUB parsing error: TOC file {0} not found in archive.", tocFileEntryPath));
|
||||
}
|
||||
if (tocFileEntry.Length > Int32.MaxValue)
|
||||
{
|
||||
throw new Exception(String.Format("EPUB parsing error: TOC file {0} is larger than 2 Gb.", tocFileEntryPath));
|
||||
}
|
||||
throw new Exception(string.Format("EPUB parsing error: TOC file {0} not found in archive.",
|
||||
tocFileEntryPath));
|
||||
if (tocFileEntry.Length > int.MaxValue)
|
||||
throw new Exception(string.Format("EPUB parsing error: TOC file {0} is larger than 2 Gb.",
|
||||
tocFileEntryPath));
|
||||
XDocument containerDocument;
|
||||
using (Stream containerStream = tocFileEntry.Open())
|
||||
using (var containerStream = tocFileEntry.Open())
|
||||
{
|
||||
containerDocument = await XmlUtils.LoadDocumentAsync(containerStream).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
XNamespace ncxNamespace = "http://www.daisy.org/z3986/2005/ncx/";
|
||||
XElement ncxNode = containerDocument.Element(ncxNamespace + "ncx");
|
||||
if (ncxNode == null)
|
||||
{
|
||||
throw new Exception("EPUB parsing error: TOC file does not contain ncx element.");
|
||||
}
|
||||
XElement headNode = ncxNode.Element(ncxNamespace + "head");
|
||||
if (headNode == null)
|
||||
{
|
||||
throw new Exception("EPUB parsing error: TOC file does not contain head element.");
|
||||
}
|
||||
EpubNavigationHead navigationHead = ReadNavigationHead(headNode);
|
||||
var ncxNode = containerDocument.Element(ncxNamespace + "ncx");
|
||||
if (ncxNode == null) throw new Exception("EPUB parsing error: TOC file does not contain ncx element.");
|
||||
var headNode = ncxNode.Element(ncxNamespace + "head");
|
||||
if (headNode == null) throw new Exception("EPUB parsing error: TOC file does not contain head element.");
|
||||
var navigationHead = ReadNavigationHead(headNode);
|
||||
result.Head = navigationHead;
|
||||
XElement docTitleNode = ncxNode.Element(ncxNamespace + "docTitle");
|
||||
var docTitleNode = ncxNode.Element(ncxNamespace + "docTitle");
|
||||
if (docTitleNode == null)
|
||||
{
|
||||
throw new Exception("EPUB parsing error: TOC file does not contain docTitle element.");
|
||||
}
|
||||
EpubNavigationDocTitle navigationDocTitle = ReadNavigationDocTitle(docTitleNode);
|
||||
var navigationDocTitle = ReadNavigationDocTitle(docTitleNode);
|
||||
result.DocTitle = navigationDocTitle;
|
||||
result.DocAuthors = new List<EpubNavigationDocAuthor>();
|
||||
foreach (XElement docAuthorNode in ncxNode.Elements(ncxNamespace + "docAuthor"))
|
||||
foreach (var docAuthorNode in ncxNode.Elements(ncxNamespace + "docAuthor"))
|
||||
{
|
||||
EpubNavigationDocAuthor navigationDocAuthor = ReadNavigationDocAuthor(docAuthorNode);
|
||||
var navigationDocAuthor = ReadNavigationDocAuthor(docAuthorNode);
|
||||
result.DocAuthors.Add(navigationDocAuthor);
|
||||
}
|
||||
XElement navMapNode = ncxNode.Element(ncxNamespace + "navMap");
|
||||
|
||||
var navMapNode = ncxNode.Element(ncxNamespace + "navMap");
|
||||
if (navMapNode == null)
|
||||
{
|
||||
throw new Exception("EPUB parsing error: TOC file does not contain navMap element.");
|
||||
}
|
||||
EpubNavigationMap navMap = ReadNavigationMap(navMapNode);
|
||||
var navMap = ReadNavigationMap(navMapNode);
|
||||
result.NavMap = navMap;
|
||||
XElement pageListNode = ncxNode.Element(ncxNamespace + "pageList");
|
||||
var pageListNode = ncxNode.Element(ncxNamespace + "pageList");
|
||||
if (pageListNode != null)
|
||||
{
|
||||
EpubNavigationPageList pageList = ReadNavigationPageList(pageListNode);
|
||||
var pageList = ReadNavigationPageList(pageListNode);
|
||||
result.PageList = pageList;
|
||||
}
|
||||
|
||||
result.NavLists = new List<EpubNavigationList>();
|
||||
foreach (XElement navigationListNode in ncxNode.Elements(ncxNamespace + "navList"))
|
||||
foreach (var navigationListNode in ncxNode.Elements(ncxNamespace + "navList"))
|
||||
{
|
||||
EpubNavigationList navigationList = ReadNavigationList(navigationListNode);
|
||||
var navigationList = ReadNavigationList(navigationListNode);
|
||||
result.NavLists.Add(navigationList);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationHead ReadNavigationHead(XElement headNode)
|
||||
{
|
||||
EpubNavigationHead result = new EpubNavigationHead();
|
||||
foreach (XElement metaNode in headNode.Elements())
|
||||
{
|
||||
if (String.Compare(metaNode.Name.LocalName, "meta", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
var result = new EpubNavigationHead();
|
||||
foreach (var metaNode in headNode.Elements())
|
||||
if (string.Compare(metaNode.Name.LocalName, "meta", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
EpubNavigationHeadMeta meta = new EpubNavigationHeadMeta();
|
||||
foreach (XAttribute metaNodeAttribute in metaNode.Attributes())
|
||||
var meta = new EpubNavigationHeadMeta();
|
||||
foreach (var metaNodeAttribute in metaNode.Attributes())
|
||||
{
|
||||
string attributeValue = metaNodeAttribute.Value;
|
||||
var attributeValue = metaNodeAttribute.Value;
|
||||
switch (metaNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "name":
|
||||
@@ -111,66 +116,55 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(meta.Name))
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(meta.Name))
|
||||
throw new Exception("Incorrect EPUB navigation meta: meta name is missing.");
|
||||
}
|
||||
if (meta.Content == null)
|
||||
{
|
||||
throw new Exception("Incorrect EPUB navigation meta: meta content is missing.");
|
||||
}
|
||||
result.Add(meta);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationDocTitle ReadNavigationDocTitle(XElement docTitleNode)
|
||||
{
|
||||
EpubNavigationDocTitle result = new EpubNavigationDocTitle();
|
||||
foreach (XElement textNode in docTitleNode.Elements())
|
||||
{
|
||||
if (String.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
var result = new EpubNavigationDocTitle();
|
||||
foreach (var textNode in docTitleNode.Elements())
|
||||
if (string.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
result.Add(textNode.Value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationDocAuthor ReadNavigationDocAuthor(XElement docAuthorNode)
|
||||
{
|
||||
EpubNavigationDocAuthor result = new EpubNavigationDocAuthor();
|
||||
foreach (XElement textNode in docAuthorNode.Elements())
|
||||
{
|
||||
if (String.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
var result = new EpubNavigationDocAuthor();
|
||||
foreach (var textNode in docAuthorNode.Elements())
|
||||
if (string.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
result.Add(textNode.Value);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationMap ReadNavigationMap(XElement navigationMapNode)
|
||||
{
|
||||
EpubNavigationMap result = new EpubNavigationMap();
|
||||
foreach (XElement navigationPointNode in navigationMapNode.Elements())
|
||||
{
|
||||
if (String.Compare(navigationPointNode.Name.LocalName, "navPoint", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
var result = new EpubNavigationMap();
|
||||
foreach (var navigationPointNode in navigationMapNode.Elements())
|
||||
if (string.Compare(navigationPointNode.Name.LocalName, "navPoint",
|
||||
StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
EpubNavigationPoint navigationPoint = ReadNavigationPoint(navigationPointNode);
|
||||
var navigationPoint = ReadNavigationPoint(navigationPointNode);
|
||||
result.Add(navigationPoint);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationPoint ReadNavigationPoint(XElement navigationPointNode)
|
||||
{
|
||||
EpubNavigationPoint result = new EpubNavigationPoint();
|
||||
foreach (XAttribute navigationPointNodeAttribute in navigationPointNode.Attributes())
|
||||
var result = new EpubNavigationPoint();
|
||||
foreach (var navigationPointNodeAttribute in navigationPointNode.Attributes())
|
||||
{
|
||||
string attributeValue = navigationPointNodeAttribute.Value;
|
||||
var attributeValue = navigationPointNodeAttribute.Value;
|
||||
switch (navigationPointNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "id":
|
||||
@@ -184,59 +178,53 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(result.Id))
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(result.Id))
|
||||
throw new Exception("Incorrect EPUB navigation point: point ID is missing.");
|
||||
}
|
||||
result.NavigationLabels = new List<EpubNavigationLabel>();
|
||||
result.ChildNavigationPoints = new List<EpubNavigationPoint>();
|
||||
foreach (XElement navigationPointChildNode in navigationPointNode.Elements())
|
||||
{
|
||||
foreach (var navigationPointChildNode in navigationPointNode.Elements())
|
||||
switch (navigationPointChildNode.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "navlabel":
|
||||
EpubNavigationLabel navigationLabel = ReadNavigationLabel(navigationPointChildNode);
|
||||
var navigationLabel = ReadNavigationLabel(navigationPointChildNode);
|
||||
result.NavigationLabels.Add(navigationLabel);
|
||||
break;
|
||||
case "content":
|
||||
EpubNavigationContent content = ReadNavigationContent(navigationPointChildNode);
|
||||
var content = ReadNavigationContent(navigationPointChildNode);
|
||||
result.Content = content;
|
||||
break;
|
||||
case "navpoint":
|
||||
EpubNavigationPoint childNavigationPoint = ReadNavigationPoint(navigationPointChildNode);
|
||||
var childNavigationPoint = ReadNavigationPoint(navigationPointChildNode);
|
||||
result.ChildNavigationPoints.Add(childNavigationPoint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result.NavigationLabels.Any())
|
||||
{
|
||||
throw new Exception(String.Format("EPUB parsing error: navigation point {0} should contain at least one navigation label.", result.Id));
|
||||
}
|
||||
throw new Exception(string.Format(
|
||||
"EPUB parsing error: navigation point {0} should contain at least one navigation label.",
|
||||
result.Id));
|
||||
if (result.Content == null)
|
||||
{
|
||||
throw new Exception(String.Format("EPUB parsing error: navigation point {0} should contain content.", result.Id));
|
||||
}
|
||||
throw new Exception(string.Format("EPUB parsing error: navigation point {0} should contain content.",
|
||||
result.Id));
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationLabel ReadNavigationLabel(XElement navigationLabelNode)
|
||||
{
|
||||
EpubNavigationLabel result = new EpubNavigationLabel();
|
||||
XElement navigationLabelTextNode = navigationLabelNode.Element(navigationLabelNode.Name.Namespace + "text");
|
||||
var result = new EpubNavigationLabel();
|
||||
var navigationLabelTextNode = navigationLabelNode.Element(navigationLabelNode.Name.Namespace + "text");
|
||||
if (navigationLabelTextNode == null)
|
||||
{
|
||||
throw new Exception("Incorrect EPUB navigation label: label text element is missing.");
|
||||
}
|
||||
result.Text = navigationLabelTextNode.Value;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationContent ReadNavigationContent(XElement navigationContentNode)
|
||||
{
|
||||
EpubNavigationContent result = new EpubNavigationContent();
|
||||
foreach (XAttribute navigationContentNodeAttribute in navigationContentNode.Attributes())
|
||||
var result = new EpubNavigationContent();
|
||||
foreach (var navigationContentNodeAttribute in navigationContentNode.Attributes())
|
||||
{
|
||||
string attributeValue = navigationContentNodeAttribute.Value;
|
||||
var attributeValue = navigationContentNodeAttribute.Value;
|
||||
switch (navigationContentNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "id":
|
||||
@@ -247,33 +235,32 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(result.Source))
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(result.Source))
|
||||
throw new Exception("Incorrect EPUB navigation content: content source is missing.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationPageList ReadNavigationPageList(XElement navigationPageListNode)
|
||||
{
|
||||
EpubNavigationPageList result = new EpubNavigationPageList();
|
||||
foreach (XElement pageTargetNode in navigationPageListNode.Elements())
|
||||
{
|
||||
if (String.Compare(pageTargetNode.Name.LocalName, "pageTarget", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
var result = new EpubNavigationPageList();
|
||||
foreach (var pageTargetNode in navigationPageListNode.Elements())
|
||||
if (string.Compare(pageTargetNode.Name.LocalName, "pageTarget", StringComparison.OrdinalIgnoreCase) ==
|
||||
0)
|
||||
{
|
||||
EpubNavigationPageTarget pageTarget = ReadNavigationPageTarget(pageTargetNode);
|
||||
var pageTarget = ReadNavigationPageTarget(pageTargetNode);
|
||||
result.Add(pageTarget);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationPageTarget ReadNavigationPageTarget(XElement navigationPageTargetNode)
|
||||
{
|
||||
EpubNavigationPageTarget result = new EpubNavigationPageTarget();
|
||||
foreach (XAttribute navigationPageTargetNodeAttribute in navigationPageTargetNode.Attributes())
|
||||
var result = new EpubNavigationPageTarget();
|
||||
foreach (var navigationPageTargetNodeAttribute in navigationPageTargetNode.Attributes())
|
||||
{
|
||||
string attributeValue = navigationPageTargetNodeAttribute.Value;
|
||||
var attributeValue = navigationPageTargetNodeAttribute.Value;
|
||||
switch (navigationPageTargetNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "id":
|
||||
@@ -285,9 +272,9 @@ namespace VersOne.Epub.Internal
|
||||
case "type":
|
||||
EpubNavigationPageTargetType type;
|
||||
if (!Enum.TryParse(attributeValue, out type))
|
||||
{
|
||||
throw new Exception(String.Format("Incorrect EPUB navigation page target: {0} is incorrect value for page target type.", attributeValue));
|
||||
}
|
||||
throw new Exception(string.Format(
|
||||
"Incorrect EPUB navigation page target: {0} is incorrect value for page target type.",
|
||||
attributeValue));
|
||||
result.Type = type;
|
||||
break;
|
||||
case "class":
|
||||
@@ -298,35 +285,33 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (result.Type == default(EpubNavigationPageTargetType))
|
||||
{
|
||||
throw new Exception("Incorrect EPUB navigation page target: page target type is missing.");
|
||||
}
|
||||
foreach (XElement navigationPageTargetChildNode in navigationPageTargetNode.Elements())
|
||||
foreach (var navigationPageTargetChildNode in navigationPageTargetNode.Elements())
|
||||
switch (navigationPageTargetChildNode.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "navlabel":
|
||||
EpubNavigationLabel navigationLabel = ReadNavigationLabel(navigationPageTargetChildNode);
|
||||
var navigationLabel = ReadNavigationLabel(navigationPageTargetChildNode);
|
||||
result.NavigationLabels.Add(navigationLabel);
|
||||
break;
|
||||
case "content":
|
||||
EpubNavigationContent content = ReadNavigationContent(navigationPageTargetChildNode);
|
||||
var content = ReadNavigationContent(navigationPageTargetChildNode);
|
||||
result.Content = content;
|
||||
break;
|
||||
}
|
||||
if (!result.NavigationLabels.Any())
|
||||
{
|
||||
throw new Exception("Incorrect EPUB navigation page target: at least one navLabel element is required.");
|
||||
}
|
||||
throw new Exception(
|
||||
"Incorrect EPUB navigation page target: at least one navLabel element is required.");
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationList ReadNavigationList(XElement navigationListNode)
|
||||
{
|
||||
EpubNavigationList result = new EpubNavigationList();
|
||||
foreach (XAttribute navigationListNodeAttribute in navigationListNode.Attributes())
|
||||
var result = new EpubNavigationList();
|
||||
foreach (var navigationListNodeAttribute in navigationListNode.Attributes())
|
||||
{
|
||||
string attributeValue = navigationListNodeAttribute.Value;
|
||||
var attributeValue = navigationListNodeAttribute.Value;
|
||||
switch (navigationListNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "id":
|
||||
@@ -337,33 +322,31 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
foreach (XElement navigationListChildNode in navigationListNode.Elements())
|
||||
{
|
||||
|
||||
foreach (var navigationListChildNode in navigationListNode.Elements())
|
||||
switch (navigationListChildNode.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "navlabel":
|
||||
EpubNavigationLabel navigationLabel = ReadNavigationLabel(navigationListChildNode);
|
||||
var navigationLabel = ReadNavigationLabel(navigationListChildNode);
|
||||
result.NavigationLabels.Add(navigationLabel);
|
||||
break;
|
||||
case "navTarget":
|
||||
EpubNavigationTarget navigationTarget = ReadNavigationTarget(navigationListChildNode);
|
||||
var navigationTarget = ReadNavigationTarget(navigationListChildNode);
|
||||
result.NavigationTargets.Add(navigationTarget);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result.NavigationLabels.Any())
|
||||
{
|
||||
throw new Exception("Incorrect EPUB navigation page target: at least one navLabel element is required.");
|
||||
}
|
||||
throw new Exception(
|
||||
"Incorrect EPUB navigation page target: at least one navLabel element is required.");
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubNavigationTarget ReadNavigationTarget(XElement navigationTargetNode)
|
||||
{
|
||||
EpubNavigationTarget result = new EpubNavigationTarget();
|
||||
foreach (XAttribute navigationPageTargetNodeAttribute in navigationTargetNode.Attributes())
|
||||
var result = new EpubNavigationTarget();
|
||||
foreach (var navigationPageTargetNodeAttribute in navigationTargetNode.Attributes())
|
||||
{
|
||||
string attributeValue = navigationPageTargetNodeAttribute.Value;
|
||||
var attributeValue = navigationPageTargetNodeAttribute.Value;
|
||||
switch (navigationPageTargetNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "id":
|
||||
@@ -380,29 +363,24 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(result.Id))
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(result.Id))
|
||||
throw new Exception("Incorrect EPUB navigation target: navigation target ID is missing.");
|
||||
}
|
||||
foreach (XElement navigationTargetChildNode in navigationTargetNode.Elements())
|
||||
{
|
||||
foreach (var navigationTargetChildNode in navigationTargetNode.Elements())
|
||||
switch (navigationTargetChildNode.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "navlabel":
|
||||
EpubNavigationLabel navigationLabel = ReadNavigationLabel(navigationTargetChildNode);
|
||||
var navigationLabel = ReadNavigationLabel(navigationTargetChildNode);
|
||||
result.NavigationLabels.Add(navigationLabel);
|
||||
break;
|
||||
case "content":
|
||||
EpubNavigationContent content = ReadNavigationContent(navigationTargetChildNode);
|
||||
var content = ReadNavigationContent(navigationTargetChildNode);
|
||||
result.Content = content;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!result.NavigationLabels.Any())
|
||||
{
|
||||
throw new Exception("Incorrect EPUB navigation target: at least one navLabel element is required.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,22 @@
|
||||
using System;
|
||||
// Copyright © 2018 Marco Gavelli and Paddy Xu
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
@@ -12,65 +28,49 @@ namespace VersOne.Epub.Internal
|
||||
{
|
||||
public static async Task<EpubPackage> ReadPackageAsync(ZipArchive epubArchive, string rootFilePath)
|
||||
{
|
||||
ZipArchiveEntry rootFileEntry = epubArchive.GetEntry(rootFilePath);
|
||||
if (rootFileEntry == null)
|
||||
{
|
||||
throw new Exception("EPUB parsing error: root file not found in archive.");
|
||||
}
|
||||
var rootFileEntry = epubArchive.GetEntry(rootFilePath);
|
||||
if (rootFileEntry == null) throw new Exception("EPUB parsing error: root file not found in archive.");
|
||||
XDocument containerDocument;
|
||||
using (Stream containerStream = rootFileEntry.Open())
|
||||
using (var containerStream = rootFileEntry.Open())
|
||||
{
|
||||
containerDocument = await XmlUtils.LoadDocumentAsync(containerStream).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
XNamespace opfNamespace = "http://www.idpf.org/2007/opf";
|
||||
XElement packageNode = containerDocument.Element(opfNamespace + "package");
|
||||
EpubPackage result = new EpubPackage();
|
||||
string epubVersionValue = packageNode.Attribute("version").Value;
|
||||
var packageNode = containerDocument.Element(opfNamespace + "package");
|
||||
var result = new EpubPackage();
|
||||
var epubVersionValue = packageNode.Attribute("version").Value;
|
||||
if (epubVersionValue == "2.0")
|
||||
{
|
||||
result.EpubVersion = EpubVersion.EPUB_2;
|
||||
}
|
||||
else if (epubVersionValue == "3.0")
|
||||
{
|
||||
result.EpubVersion = EpubVersion.EPUB_3;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception(String.Format("Unsupported EPUB version: {0}.", epubVersionValue));
|
||||
}
|
||||
XElement metadataNode = packageNode.Element(opfNamespace + "metadata");
|
||||
if (metadataNode == null)
|
||||
{
|
||||
throw new Exception("EPUB parsing error: metadata not found in the package.");
|
||||
}
|
||||
EpubMetadata metadata = ReadMetadata(metadataNode, result.EpubVersion);
|
||||
throw new Exception(string.Format("Unsupported EPUB version: {0}.", epubVersionValue));
|
||||
var metadataNode = packageNode.Element(opfNamespace + "metadata");
|
||||
if (metadataNode == null) throw new Exception("EPUB parsing error: metadata not found in the package.");
|
||||
var metadata = ReadMetadata(metadataNode, result.EpubVersion);
|
||||
result.Metadata = metadata;
|
||||
XElement manifestNode = packageNode.Element(opfNamespace + "manifest");
|
||||
if (manifestNode == null)
|
||||
{
|
||||
throw new Exception("EPUB parsing error: manifest not found in the package.");
|
||||
}
|
||||
EpubManifest manifest = ReadManifest(manifestNode);
|
||||
var manifestNode = packageNode.Element(opfNamespace + "manifest");
|
||||
if (manifestNode == null) throw new Exception("EPUB parsing error: manifest not found in the package.");
|
||||
var manifest = ReadManifest(manifestNode);
|
||||
result.Manifest = manifest;
|
||||
XElement spineNode = packageNode.Element(opfNamespace + "spine");
|
||||
if (spineNode == null)
|
||||
{
|
||||
throw new Exception("EPUB parsing error: spine not found in the package.");
|
||||
}
|
||||
EpubSpine spine = ReadSpine(spineNode);
|
||||
var spineNode = packageNode.Element(opfNamespace + "spine");
|
||||
if (spineNode == null) throw new Exception("EPUB parsing error: spine not found in the package.");
|
||||
var spine = ReadSpine(spineNode);
|
||||
result.Spine = spine;
|
||||
XElement guideNode = packageNode.Element(opfNamespace + "guide");
|
||||
var guideNode = packageNode.Element(opfNamespace + "guide");
|
||||
if (guideNode != null)
|
||||
{
|
||||
EpubGuide guide = ReadGuide(guideNode);
|
||||
var guide = ReadGuide(guideNode);
|
||||
result.Guide = guide;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubMetadata ReadMetadata(XElement metadataNode, EpubVersion epubVersion)
|
||||
{
|
||||
EpubMetadata result = new EpubMetadata
|
||||
var result = new EpubMetadata
|
||||
{
|
||||
Titles = new List<string>(),
|
||||
Creators = new List<EpubMetadataCreator>(),
|
||||
@@ -88,16 +88,16 @@ namespace VersOne.Epub.Internal
|
||||
Rights = new List<string>(),
|
||||
MetaItems = new List<EpubMetadataMeta>()
|
||||
};
|
||||
foreach (XElement metadataItemNode in metadataNode.Elements())
|
||||
foreach (var metadataItemNode in metadataNode.Elements())
|
||||
{
|
||||
string innerText = metadataItemNode.Value;
|
||||
var innerText = metadataItemNode.Value;
|
||||
switch (metadataItemNode.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "title":
|
||||
result.Titles.Add(innerText);
|
||||
break;
|
||||
case "creator":
|
||||
EpubMetadataCreator creator = ReadMetadataCreator(metadataItemNode);
|
||||
var creator = ReadMetadataCreator(metadataItemNode);
|
||||
result.Creators.Add(creator);
|
||||
break;
|
||||
case "subject":
|
||||
@@ -110,11 +110,11 @@ namespace VersOne.Epub.Internal
|
||||
result.Publishers.Add(innerText);
|
||||
break;
|
||||
case "contributor":
|
||||
EpubMetadataContributor contributor = ReadMetadataContributor(metadataItemNode);
|
||||
var contributor = ReadMetadataContributor(metadataItemNode);
|
||||
result.Contributors.Add(contributor);
|
||||
break;
|
||||
case "date":
|
||||
EpubMetadataDate date = ReadMetadataDate(metadataItemNode);
|
||||
var date = ReadMetadataDate(metadataItemNode);
|
||||
result.Dates.Add(date);
|
||||
break;
|
||||
case "type":
|
||||
@@ -124,7 +124,7 @@ namespace VersOne.Epub.Internal
|
||||
result.Formats.Add(innerText);
|
||||
break;
|
||||
case "identifier":
|
||||
EpubMetadataIdentifier identifier = ReadMetadataIdentifier(metadataItemNode);
|
||||
var identifier = ReadMetadataIdentifier(metadataItemNode);
|
||||
result.Identifiers.Add(identifier);
|
||||
break;
|
||||
case "source":
|
||||
@@ -145,26 +145,28 @@ namespace VersOne.Epub.Internal
|
||||
case "meta":
|
||||
if (epubVersion == EpubVersion.EPUB_2)
|
||||
{
|
||||
EpubMetadataMeta meta = ReadMetadataMetaVersion2(metadataItemNode);
|
||||
var meta = ReadMetadataMetaVersion2(metadataItemNode);
|
||||
result.MetaItems.Add(meta);
|
||||
}
|
||||
else if (epubVersion == EpubVersion.EPUB_3)
|
||||
{
|
||||
EpubMetadataMeta meta = ReadMetadataMetaVersion3(metadataItemNode);
|
||||
var meta = ReadMetadataMetaVersion3(metadataItemNode);
|
||||
result.MetaItems.Add(meta);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubMetadataCreator ReadMetadataCreator(XElement metadataCreatorNode)
|
||||
{
|
||||
EpubMetadataCreator result = new EpubMetadataCreator();
|
||||
foreach (XAttribute metadataCreatorNodeAttribute in metadataCreatorNode.Attributes())
|
||||
var result = new EpubMetadataCreator();
|
||||
foreach (var metadataCreatorNodeAttribute in metadataCreatorNode.Attributes())
|
||||
{
|
||||
string attributeValue = metadataCreatorNodeAttribute.Value;
|
||||
var attributeValue = metadataCreatorNodeAttribute.Value;
|
||||
switch (metadataCreatorNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "role":
|
||||
@@ -175,16 +177,17 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.Creator = metadataCreatorNode.Value;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubMetadataContributor ReadMetadataContributor(XElement metadataContributorNode)
|
||||
{
|
||||
EpubMetadataContributor result = new EpubMetadataContributor();
|
||||
foreach (XAttribute metadataContributorNodeAttribute in metadataContributorNode.Attributes())
|
||||
var result = new EpubMetadataContributor();
|
||||
foreach (var metadataContributorNodeAttribute in metadataContributorNode.Attributes())
|
||||
{
|
||||
string attributeValue = metadataContributorNodeAttribute.Value;
|
||||
var attributeValue = metadataContributorNodeAttribute.Value;
|
||||
switch (metadataContributorNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "role":
|
||||
@@ -195,28 +198,26 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.Contributor = metadataContributorNode.Value;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubMetadataDate ReadMetadataDate(XElement metadataDateNode)
|
||||
{
|
||||
EpubMetadataDate result = new EpubMetadataDate();
|
||||
XAttribute eventAttribute = metadataDateNode.Attribute(metadataDateNode.Name.Namespace + "event");
|
||||
if (eventAttribute != null)
|
||||
{
|
||||
result.Event = eventAttribute.Value;
|
||||
}
|
||||
var result = new EpubMetadataDate();
|
||||
var eventAttribute = metadataDateNode.Attribute(metadataDateNode.Name.Namespace + "event");
|
||||
if (eventAttribute != null) result.Event = eventAttribute.Value;
|
||||
result.Date = metadataDateNode.Value;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubMetadataIdentifier ReadMetadataIdentifier(XElement metadataIdentifierNode)
|
||||
{
|
||||
EpubMetadataIdentifier result = new EpubMetadataIdentifier();
|
||||
foreach (XAttribute metadataIdentifierNodeAttribute in metadataIdentifierNode.Attributes())
|
||||
var result = new EpubMetadataIdentifier();
|
||||
foreach (var metadataIdentifierNodeAttribute in metadataIdentifierNode.Attributes())
|
||||
{
|
||||
string attributeValue = metadataIdentifierNodeAttribute.Value;
|
||||
var attributeValue = metadataIdentifierNodeAttribute.Value;
|
||||
switch (metadataIdentifierNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "id":
|
||||
@@ -227,16 +228,17 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.Identifier = metadataIdentifierNode.Value;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubMetadataMeta ReadMetadataMetaVersion2(XElement metadataMetaNode)
|
||||
{
|
||||
EpubMetadataMeta result = new EpubMetadataMeta();
|
||||
foreach (XAttribute metadataMetaNodeAttribute in metadataMetaNode.Attributes())
|
||||
var result = new EpubMetadataMeta();
|
||||
foreach (var metadataMetaNodeAttribute in metadataMetaNode.Attributes())
|
||||
{
|
||||
string attributeValue = metadataMetaNodeAttribute.Value;
|
||||
var attributeValue = metadataMetaNodeAttribute.Value;
|
||||
switch (metadataMetaNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "name":
|
||||
@@ -247,15 +249,16 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubMetadataMeta ReadMetadataMetaVersion3(XElement metadataMetaNode)
|
||||
{
|
||||
EpubMetadataMeta result = new EpubMetadataMeta();
|
||||
foreach (XAttribute metadataMetaNodeAttribute in metadataMetaNode.Attributes())
|
||||
var result = new EpubMetadataMeta();
|
||||
foreach (var metadataMetaNodeAttribute in metadataMetaNode.Attributes())
|
||||
{
|
||||
string attributeValue = metadataMetaNodeAttribute.Value;
|
||||
var attributeValue = metadataMetaNodeAttribute.Value;
|
||||
switch (metadataMetaNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "id":
|
||||
@@ -272,21 +275,21 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
result.Content = metadataMetaNode.Value;
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubManifest ReadManifest(XElement manifestNode)
|
||||
{
|
||||
EpubManifest result = new EpubManifest();
|
||||
foreach (XElement manifestItemNode in manifestNode.Elements())
|
||||
{
|
||||
if (String.Compare(manifestItemNode.Name.LocalName, "item", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
var result = new EpubManifest();
|
||||
foreach (var manifestItemNode in manifestNode.Elements())
|
||||
if (string.Compare(manifestItemNode.Name.LocalName, "item", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
EpubManifestItem manifestItem = new EpubManifestItem();
|
||||
foreach (XAttribute manifestItemNodeAttribute in manifestItemNode.Attributes())
|
||||
var manifestItem = new EpubManifestItem();
|
||||
foreach (var manifestItemNodeAttribute in manifestItemNode.Attributes())
|
||||
{
|
||||
string attributeValue = manifestItemNodeAttribute.Value;
|
||||
var attributeValue = manifestItemNodeAttribute.Value;
|
||||
switch (manifestItemNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "id":
|
||||
@@ -312,63 +315,55 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(manifestItem.Id))
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(manifestItem.Id))
|
||||
throw new Exception("Incorrect EPUB manifest: item ID is missing");
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(manifestItem.Href))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(manifestItem.Href))
|
||||
throw new Exception("Incorrect EPUB manifest: item href is missing");
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(manifestItem.MediaType))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(manifestItem.MediaType))
|
||||
throw new Exception("Incorrect EPUB manifest: item media type is missing");
|
||||
}
|
||||
result.Add(manifestItem);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubSpine ReadSpine(XElement spineNode)
|
||||
{
|
||||
EpubSpine result = new EpubSpine();
|
||||
XAttribute tocAttribute = spineNode.Attribute("toc");
|
||||
if (tocAttribute == null || String.IsNullOrWhiteSpace(tocAttribute.Value))
|
||||
{
|
||||
var result = new EpubSpine();
|
||||
var tocAttribute = spineNode.Attribute("toc");
|
||||
if (tocAttribute == null || string.IsNullOrWhiteSpace(tocAttribute.Value))
|
||||
throw new Exception("Incorrect EPUB spine: TOC is missing");
|
||||
}
|
||||
result.Toc = tocAttribute.Value;
|
||||
foreach (XElement spineItemNode in spineNode.Elements())
|
||||
{
|
||||
if (String.Compare(spineItemNode.Name.LocalName, "itemref", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
foreach (var spineItemNode in spineNode.Elements())
|
||||
if (string.Compare(spineItemNode.Name.LocalName, "itemref", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
EpubSpineItemRef spineItemRef = new EpubSpineItemRef();
|
||||
XAttribute idRefAttribute = spineItemNode.Attribute("idref");
|
||||
if (idRefAttribute == null || String.IsNullOrWhiteSpace(idRefAttribute.Value))
|
||||
{
|
||||
var spineItemRef = new EpubSpineItemRef();
|
||||
var idRefAttribute = spineItemNode.Attribute("idref");
|
||||
if (idRefAttribute == null || string.IsNullOrWhiteSpace(idRefAttribute.Value))
|
||||
throw new Exception("Incorrect EPUB spine: item ID ref is missing");
|
||||
}
|
||||
spineItemRef.IdRef = idRefAttribute.Value;
|
||||
XAttribute linearAttribute = spineItemNode.Attribute("linear");
|
||||
spineItemRef.IsLinear = linearAttribute == null || String.Compare(linearAttribute.Value, "no", StringComparison.OrdinalIgnoreCase) != 0;
|
||||
var linearAttribute = spineItemNode.Attribute("linear");
|
||||
spineItemRef.IsLinear = linearAttribute == null ||
|
||||
string.Compare(linearAttribute.Value, "no",
|
||||
StringComparison.OrdinalIgnoreCase) != 0;
|
||||
result.Add(spineItemRef);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static EpubGuide ReadGuide(XElement guideNode)
|
||||
{
|
||||
EpubGuide result = new EpubGuide();
|
||||
foreach (XElement guideReferenceNode in guideNode.Elements())
|
||||
{
|
||||
if (String.Compare(guideReferenceNode.Name.LocalName, "reference", StringComparison.OrdinalIgnoreCase) == 0)
|
||||
var result = new EpubGuide();
|
||||
foreach (var guideReferenceNode in guideNode.Elements())
|
||||
if (string.Compare(guideReferenceNode.Name.LocalName, "reference",
|
||||
StringComparison.OrdinalIgnoreCase) == 0)
|
||||
{
|
||||
EpubGuideReference guideReference = new EpubGuideReference();
|
||||
foreach (XAttribute guideReferenceNodeAttribute in guideReferenceNode.Attributes())
|
||||
var guideReference = new EpubGuideReference();
|
||||
foreach (var guideReferenceNodeAttribute in guideReferenceNode.Attributes())
|
||||
{
|
||||
string attributeValue = guideReferenceNodeAttribute.Value;
|
||||
var attributeValue = guideReferenceNodeAttribute.Value;
|
||||
switch (guideReferenceNodeAttribute.Name.LocalName.ToLowerInvariant())
|
||||
{
|
||||
case "type":
|
||||
@@ -382,18 +377,15 @@ namespace VersOne.Epub.Internal
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(guideReference.Type))
|
||||
{
|
||||
|
||||
if (string.IsNullOrWhiteSpace(guideReference.Type))
|
||||
throw new Exception("Incorrect EPUB guide: item type is missing");
|
||||
}
|
||||
if (String.IsNullOrWhiteSpace(guideReference.Href))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(guideReference.Href))
|
||||
throw new Exception("Incorrect EPUB guide: item href is missing");
|
||||
}
|
||||
result.Add(guideReference);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,21 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
// Copyright © 2018 Marco Gavelli and Paddy Xu
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
@@ -11,23 +27,22 @@ namespace VersOne.Epub.Internal
|
||||
public static async Task<string> GetRootFilePathAsync(ZipArchive epubArchive)
|
||||
{
|
||||
const string EPUB_CONTAINER_FILE_PATH = "META-INF/container.xml";
|
||||
ZipArchiveEntry containerFileEntry = epubArchive.GetEntry(EPUB_CONTAINER_FILE_PATH);
|
||||
var containerFileEntry = epubArchive.GetEntry(EPUB_CONTAINER_FILE_PATH);
|
||||
if (containerFileEntry == null)
|
||||
{
|
||||
throw new Exception(String.Format("EPUB parsing error: {0} file not found in archive.", EPUB_CONTAINER_FILE_PATH));
|
||||
}
|
||||
throw new Exception(string.Format("EPUB parsing error: {0} file not found in archive.",
|
||||
EPUB_CONTAINER_FILE_PATH));
|
||||
XDocument containerDocument;
|
||||
using (Stream containerStream = containerFileEntry.Open())
|
||||
using (var containerStream = containerFileEntry.Open())
|
||||
{
|
||||
containerDocument = await XmlUtils.LoadDocumentAsync(containerStream).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
XNamespace cnsNamespace = "urn:oasis:names:tc:opendocument:xmlns:container";
|
||||
XAttribute fullPathAttribute = containerDocument.Element(cnsNamespace + "container")?.Element(cnsNamespace + "rootfiles")?.Element(cnsNamespace + "rootfile")?.Attribute("full-path");
|
||||
var fullPathAttribute = containerDocument.Element(cnsNamespace + "container")
|
||||
?.Element(cnsNamespace + "rootfiles")?.Element(cnsNamespace + "rootfile")?.Attribute("full-path");
|
||||
if (fullPathAttribute == null)
|
||||
{
|
||||
throw new Exception("EPUB parsing error: root file path not found in the EPUB container.");
|
||||
}
|
||||
return fullPathAttribute.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,22 @@
|
||||
using System.IO.Compression;
|
||||
// Copyright © 2018 Marco Gavelli and Paddy Xu
|
||||
//
|
||||
// This file is part of QuickLook program.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System.IO.Compression;
|
||||
using System.Threading.Tasks;
|
||||
using VersOne.Epub.Schema;
|
||||
|
||||
namespace VersOne.Epub.Internal
|
||||
{
|
||||
@@ -8,15 +24,16 @@ namespace VersOne.Epub.Internal
|
||||
{
|
||||
public static async Task<EpubSchema> ReadSchemaAsync(ZipArchive epubArchive)
|
||||
{
|
||||
EpubSchema result = new EpubSchema();
|
||||
string rootFilePath = await RootFilePathReader.GetRootFilePathAsync(epubArchive).ConfigureAwait(false);
|
||||
string contentDirectoryPath = ZipPathUtils.GetDirectoryPath(rootFilePath);
|
||||
var result = new EpubSchema();
|
||||
var rootFilePath = await RootFilePathReader.GetRootFilePathAsync(epubArchive).ConfigureAwait(false);
|
||||
var contentDirectoryPath = ZipPathUtils.GetDirectoryPath(rootFilePath);
|
||||
result.ContentDirectoryPath = contentDirectoryPath;
|
||||
EpubPackage package = await PackageReader.ReadPackageAsync(epubArchive, rootFilePath).ConfigureAwait(false);
|
||||
var package = await PackageReader.ReadPackageAsync(epubArchive, rootFilePath).ConfigureAwait(false);
|
||||
result.Package = package;
|
||||
EpubNavigation navigation = await NavigationReader.ReadNavigationAsync(epubArchive, contentDirectoryPath, package).ConfigureAwait(false);
|
||||
var navigation = await NavigationReader.ReadNavigationAsync(epubArchive, contentDirectoryPath, package)
|
||||
.ConfigureAwait(false);
|
||||
result.Navigation = navigation;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user