├── .gitignore ├── .gitmodules ├── BookHtmlContent.cs ├── EpubReader ├── Entities │ ├── EpubBook.cs │ ├── EpubByteContentFile.cs │ ├── EpubChapter.cs │ ├── EpubContent.cs │ ├── EpubContentFile.cs │ ├── EpubContentType.cs │ ├── EpubSchema.cs │ └── EpubTextContentFile.cs ├── EpubReader.cs ├── Readers │ ├── BookCoverReader.cs │ ├── ChapterReader.cs │ ├── ContentReader.cs │ ├── NavigationReader.cs │ ├── PackageReader.cs │ ├── RootFilePathReader.cs │ └── SchemaReader.cs ├── RefEntities │ ├── EpubBookRef.cs │ ├── EpubByteContentFileRef.cs │ ├── EpubChapterRef.cs │ ├── EpubContentFileRef.cs │ ├── EpubContentRef.cs │ └── EpubTextContentFileRef.cs ├── Schema │ ├── Navigation │ │ ├── EpubNavigation.cs │ │ ├── EpubNavigationContent.cs │ │ ├── EpubNavigationDocAuthor.cs │ │ ├── EpubNavigationDocTitle.cs │ │ ├── EpubNavigationHead.cs │ │ ├── EpubNavigationHeadMeta.cs │ │ ├── EpubNavigationLabel.cs │ │ ├── EpubNavigationList.cs │ │ ├── EpubNavigationMap.cs │ │ ├── EpubNavigationPageList.cs │ │ ├── EpubNavigationPageTarget.cs │ │ ├── EpubNavigationPageTargetType.cs │ │ ├── EpubNavigationPoint.cs │ │ └── EpubNavigationTarget.cs │ └── Opf │ │ ├── EpubGuide.cs │ │ ├── EpubGuideReference.cs │ │ ├── EpubManifest.cs │ │ ├── EpubManifestItem.cs │ │ ├── EpubMetadata.cs │ │ ├── EpubMetadataContributor.cs │ │ ├── EpubMetadataCreator.cs │ │ ├── EpubMetadataDate.cs │ │ ├── EpubMetadataIdentifier.cs │ │ ├── EpubMetadataMeta.cs │ │ ├── EpubPackage.cs │ │ ├── EpubSpine.cs │ │ ├── EpubSpineItemRef.cs │ │ └── EpubVersion.cs └── Utils │ ├── XmlUtils.cs │ └── ZipPathUtils.cs ├── EpubViewerControl.xaml ├── EpubViewerControl.xaml.cs ├── LICENSE ├── Plugin.cs ├── Properties └── AssemblyInfo.cs ├── QuickLook.Plugin.EpubViewer.csproj ├── QuickLook.Plugin.EpubViewer.sln ├── QuickLook.Plugin.Metadata.Base.config ├── README.md ├── Scripts ├── pack-zip.ps1 └── update-version.ps1 └── packages.config /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015/2017 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # Visual Studio 2017 auto generated files 33 | Generated\ Files/ 34 | 35 | # MSTest test Results 36 | [Tt]est[Rr]esult*/ 37 | [Bb]uild[Ll]og.* 38 | 39 | # NUNIT 40 | *.VisualState.xml 41 | TestResult.xml 42 | 43 | # Build Results of an ATL Project 44 | [Dd]ebugPS/ 45 | [Rr]eleasePS/ 46 | dlldata.c 47 | 48 | # Benchmark Results 49 | BenchmarkDotNet.Artifacts/ 50 | 51 | # .NET Core 52 | project.lock.json 53 | project.fragment.lock.json 54 | artifacts/ 55 | **/Properties/launchSettings.json 56 | 57 | # StyleCop 58 | StyleCopReport.xml 59 | 60 | # Files built by Visual Studio 61 | *_i.c 62 | *_p.c 63 | *_i.h 64 | *.ilk 65 | *.meta 66 | *.obj 67 | *.iobj 68 | *.pch 69 | *.pdb 70 | *.ipdb 71 | *.pgc 72 | *.pgd 73 | *.rsp 74 | *.sbr 75 | *.tlb 76 | *.tli 77 | *.tlh 78 | *.tmp 79 | *.tmp_proj 80 | *.log 81 | *.vspscc 82 | *.vssscc 83 | .builds 84 | *.pidb 85 | *.svclog 86 | *.scc 87 | 88 | # Chutzpah Test files 89 | _Chutzpah* 90 | 91 | # Visual C++ cache files 92 | ipch/ 93 | *.aps 94 | *.ncb 95 | *.opendb 96 | *.opensdf 97 | *.sdf 98 | *.cachefile 99 | *.VC.db 100 | *.VC.VC.opendb 101 | 102 | # Visual Studio profiler 103 | *.psess 104 | *.vsp 105 | *.vspx 106 | *.sap 107 | 108 | # Visual Studio Trace Files 109 | *.e2e 110 | 111 | # TFS 2012 Local Workspace 112 | $tf/ 113 | 114 | # Guidance Automation Toolkit 115 | *.gpState 116 | 117 | # ReSharper is a .NET coding add-in 118 | _ReSharper*/ 119 | *.[Rr]e[Ss]harper 120 | *.DotSettings.user 121 | 122 | # JustCode is a .NET coding add-in 123 | .JustCode 124 | 125 | # TeamCity is a build add-in 126 | _TeamCity* 127 | 128 | # DotCover is a Code Coverage Tool 129 | *.dotCover 130 | 131 | # AxoCover is a Code Coverage Tool 132 | .axoCover/* 133 | !.axoCover/settings.json 134 | 135 | # Visual Studio code coverage results 136 | *.coverage 137 | *.coveragexml 138 | 139 | # NCrunch 140 | _NCrunch_* 141 | .*crunch*.local.xml 142 | nCrunchTemp_* 143 | 144 | # MightyMoose 145 | *.mm.* 146 | AutoTest.Net/ 147 | 148 | # Web workbench (sass) 149 | .sass-cache/ 150 | 151 | # Installshield output folder 152 | [Ee]xpress/ 153 | 154 | # DocProject is a documentation generator add-in 155 | DocProject/buildhelp/ 156 | DocProject/Help/*.HxT 157 | DocProject/Help/*.HxC 158 | DocProject/Help/*.hhc 159 | DocProject/Help/*.hhk 160 | DocProject/Help/*.hhp 161 | DocProject/Help/Html2 162 | DocProject/Help/html 163 | 164 | # Click-Once directory 165 | publish/ 166 | 167 | # Publish Web Output 168 | *.[Pp]ublish.xml 169 | *.azurePubxml 170 | # Note: Comment the next line if you want to checkin your web deploy settings, 171 | # but database connection strings (with potential passwords) will be unencrypted 172 | *.pubxml 173 | *.publishproj 174 | 175 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 176 | # checkin your Azure Web App publish settings, but sensitive information contained 177 | # in these scripts will be unencrypted 178 | PublishScripts/ 179 | 180 | # NuGet Packages 181 | *.nupkg 182 | # The packages folder can be ignored because of Package Restore 183 | **/[Pp]ackages/* 184 | # except build/, which is used as an MSBuild target. 185 | !**/[Pp]ackages/build/ 186 | # Uncomment if necessary however generally it will be regenerated when needed 187 | #!**/[Pp]ackages/repositories.config 188 | # NuGet v3's project.json files produces more ignorable files 189 | *.nuget.props 190 | *.nuget.targets 191 | 192 | # Microsoft Azure Build Output 193 | csx/ 194 | *.build.csdef 195 | 196 | # Microsoft Azure Emulator 197 | ecf/ 198 | rcf/ 199 | 200 | # Windows Store app package directories and files 201 | AppPackages/ 202 | BundleArtifacts/ 203 | Package.StoreAssociation.xml 204 | _pkginfo.txt 205 | *.appx 206 | 207 | # Visual Studio cache files 208 | # files ending in .cache can be ignored 209 | *.[Cc]ache 210 | # but keep track of directories ending in .cache 211 | !*.[Cc]ache/ 212 | 213 | # Others 214 | ClientBin/ 215 | ~$* 216 | *~ 217 | *.dbmdl 218 | *.dbproj.schemaview 219 | *.jfm 220 | *.pfx 221 | *.publishsettings 222 | orleans.codegen.cs 223 | 224 | # Including strong name files can present a security risk 225 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 226 | #*.snk 227 | 228 | # Since there are multiple workflows, uncomment next line to ignore bower_components 229 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 230 | #bower_components/ 231 | 232 | # RIA/Silverlight projects 233 | Generated_Code/ 234 | 235 | # Backup & report files from converting an old project file 236 | # to a newer Visual Studio version. Backup files are not needed, 237 | # because we have git ;-) 238 | _UpgradeReport_Files/ 239 | Backup*/ 240 | UpgradeLog*.XML 241 | UpgradeLog*.htm 242 | ServiceFabricBackup/ 243 | *.rptproj.bak 244 | 245 | # SQL Server files 246 | *.mdf 247 | *.ldf 248 | *.ndf 249 | 250 | # Business Intelligence projects 251 | *.rdl.data 252 | *.bim.layout 253 | *.bim_*.settings 254 | *.rptproj.rsuser 255 | 256 | # Microsoft Fakes 257 | FakesAssemblies/ 258 | 259 | # GhostDoc plugin setting file 260 | *.GhostDoc.xml 261 | 262 | # Node.js Tools for Visual Studio 263 | .ntvs_analysis.dat 264 | node_modules/ 265 | 266 | # Visual Studio 6 build log 267 | *.plg 268 | 269 | # Visual Studio 6 workspace options file 270 | *.opt 271 | 272 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 273 | *.vbw 274 | 275 | # Visual Studio LightSwitch build output 276 | **/*.HTMLClient/GeneratedArtifacts 277 | **/*.DesktopClient/GeneratedArtifacts 278 | **/*.DesktopClient/ModelManifest.xml 279 | **/*.Server/GeneratedArtifacts 280 | **/*.Server/ModelManifest.xml 281 | _Pvt_Extensions 282 | 283 | # Paket dependency manager 284 | .paket/paket.exe 285 | paket-files/ 286 | 287 | # FAKE - F# Make 288 | .fake/ 289 | 290 | # JetBrains Rider 291 | .idea/ 292 | *.sln.iml 293 | 294 | # CodeRush 295 | .cr/ 296 | 297 | # Python Tools for Visual Studio (PTVS) 298 | __pycache__/ 299 | *.pyc 300 | 301 | # Cake - Uncomment if you are using it 302 | # tools/** 303 | # !tools/packages.config 304 | 305 | # Tabs Studio 306 | *.tss 307 | 308 | # Telerik's JustMock configuration file 309 | *.jmconfig 310 | 311 | # BizTalk build output 312 | *.btp.cs 313 | *.btm.cs 314 | *.odx.cs 315 | *.xsd.cs 316 | 317 | # OpenCover UI analysis results 318 | OpenCover/ 319 | 320 | # Azure Stream Analytics local run output 321 | ASALocalRun/ 322 | 323 | # MSBuild Binary and Structured Log 324 | *.binlog 325 | 326 | # NVidia Nsight GPU debugger configuration file 327 | *.nvuser 328 | 329 | # MFractors (Xamarin productivity tool) working folder 330 | .mfractor/ 331 | /*.qlplugin 332 | /GitVersion.cs 333 | /QuickLook.Plugin.Metadata.config 334 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "QuickLook.Common"] 2 | path = QuickLook.Common 3 | url = https://github.com/QL-Win/QuickLook.Common.git 4 | -------------------------------------------------------------------------------- /BookHtmlContent.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Diagnostics; 19 | using System.IO; 20 | using System.Windows; 21 | using System.Windows.Media.Imaging; 22 | using TheArtOfDev.HtmlRenderer.Core.Entities; 23 | using TheArtOfDev.HtmlRenderer.WPF; 24 | using VersOne.Epub; 25 | 26 | namespace QuickLook.Plugin.EpubViewer 27 | { 28 | public class BookHtmlContent : HtmlPanel 29 | { 30 | public static readonly DependencyProperty ChapterRefProperty = DependencyProperty.Register("ChapterRef", 31 | typeof(EpubChapterRef), typeof(BookHtmlContent), new PropertyMetadata(OnChapterRefChanged)); 32 | 33 | public static readonly DependencyProperty EpubBookProperty = DependencyProperty.Register("EpubBook", 34 | typeof(EpubBookRef), typeof(BookHtmlContent), new PropertyMetadata(null)); 35 | 36 | public EpubChapterRef ChapterRef 37 | { 38 | get => (EpubChapterRef) GetValue(ChapterRefProperty); 39 | set => SetValue(ChapterRefProperty, value); 40 | } 41 | 42 | public EpubBookRef EpubBook 43 | { 44 | get => (EpubBookRef) GetValue(EpubBookProperty); 45 | set => SetValue(EpubBookProperty, value); 46 | } 47 | 48 | protected override void OnStylesheetLoad(HtmlStylesheetLoadEventArgs args) 49 | { 50 | var styleSheetFilePath = GetFullPath(ChapterRef.ContentFileName, args.Src); 51 | if (EpubBook.Content.Css.TryGetValue(styleSheetFilePath, out var styleSheetContent)) 52 | args.SetStyleSheet = styleSheetContent.ReadContentAsText(); 53 | } 54 | 55 | protected override async void OnImageLoad(HtmlImageLoadEventArgs args) 56 | { 57 | var imageFilePath = ChapterRef != null ? GetFullPath(ChapterRef.ContentFileName, args.Src) : null; 58 | byte[] imageBytes = null; 59 | if (args.Src == "COVER") 60 | imageBytes = await EpubBook.ReadCoverAsync(); 61 | else if (EpubBook.Content.Images.TryGetValue(imageFilePath, out var imageContent)) 62 | imageBytes = await imageContent.ReadContentAsBytesAsync(); 63 | 64 | if (imageBytes != null) 65 | using (var imageStream = new MemoryStream(imageBytes)) 66 | { 67 | try 68 | { 69 | var bitmapImage = new BitmapImage(); 70 | bitmapImage.BeginInit(); 71 | bitmapImage.StreamSource = imageStream; 72 | bitmapImage.CacheOption = BitmapCacheOption.OnLoad; 73 | bitmapImage.EndInit(); 74 | bitmapImage.Freeze(); 75 | args.Callback(bitmapImage); 76 | args.Handled = true; 77 | } 78 | catch 79 | { 80 | Debug.WriteLine($"Failed to load image: {args.Src}"); 81 | } 82 | } 83 | } 84 | 85 | private string GetFullPath(string htmlFilePath, string relativePath) 86 | { 87 | if (relativePath.StartsWith("/")) return relativePath.Length > 1 ? relativePath.Substring(1) : string.Empty; 88 | var basePath = Path.GetDirectoryName(htmlFilePath); 89 | while (relativePath.StartsWith("../")) 90 | { 91 | relativePath = relativePath.Length > 3 ? relativePath.Substring(3) : string.Empty; 92 | basePath = Path.GetDirectoryName(basePath); 93 | } 94 | 95 | var fullPath = string.Concat(basePath.Replace('\\', '/'), '/', relativePath); 96 | return fullPath.StartsWith("/") ? fullPath.Length > 1 ? fullPath.Substring(1) : string.Empty : fullPath; 97 | } 98 | 99 | private static async void OnChapterRefChanged(DependencyObject dependencyObject, 100 | DependencyPropertyChangedEventArgs e) 101 | { 102 | if (!(dependencyObject is BookHtmlContent bookHtmlContent) || bookHtmlContent.ChapterRef == null) 103 | return; 104 | bookHtmlContent.Text = await bookHtmlContent.ChapterRef.ReadHtmlContentAsync(); 105 | } 106 | } 107 | } -------------------------------------------------------------------------------- /EpubReader/Entities/EpubBook.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub 21 | { 22 | public class EpubBook 23 | { 24 | public string FilePath { get; set; } 25 | public string Title { get; set; } 26 | public string Author { get; set; } 27 | public List AuthorList { get; set; } 28 | public EpubSchema Schema { get; set; } 29 | public EpubContent Content { get; set; } 30 | public byte[] CoverImage { get; set; } 31 | public List Chapters { get; set; } 32 | } 33 | } -------------------------------------------------------------------------------- /EpubReader/Entities/EpubByteContentFile.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub 19 | { 20 | public class EpubByteContentFile : EpubContentFile 21 | { 22 | public byte[] Content { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /EpubReader/Entities/EpubChapter.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub 21 | { 22 | public class EpubChapter 23 | { 24 | public string Title { get; set; } 25 | public string ContentFileName { get; set; } 26 | public string Anchor { get; set; } 27 | public string HtmlContent { get; set; } 28 | public List SubChapters { get; set; } 29 | 30 | public override string ToString() 31 | { 32 | return string.Format("Title: {0}, Subchapter count: {1}", Title, SubChapters.Count); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /EpubReader/Entities/EpubContent.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub 21 | { 22 | public class EpubContent 23 | { 24 | public Dictionary Html { get; set; } 25 | public Dictionary Css { get; set; } 26 | public Dictionary Images { get; set; } 27 | public Dictionary Fonts { get; set; } 28 | public Dictionary AllFiles { get; set; } 29 | } 30 | } -------------------------------------------------------------------------------- /EpubReader/Entities/EpubContentFile.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub 19 | { 20 | public abstract class EpubContentFile 21 | { 22 | public string FileName { get; set; } 23 | public EpubContentType ContentType { get; set; } 24 | public string ContentMimeType { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /EpubReader/Entities/EpubContentType.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub 19 | { 20 | public enum EpubContentType 21 | { 22 | XHTML_1_1 = 1, 23 | DTBOOK, 24 | DTBOOK_NCX, 25 | OEB1_DOCUMENT, 26 | XML, 27 | CSS, 28 | OEB1_CSS, 29 | IMAGE_GIF, 30 | IMAGE_JPEG, 31 | IMAGE_PNG, 32 | IMAGE_SVG, 33 | FONT_TRUETYPE, 34 | FONT_OPENTYPE, 35 | OTHER 36 | } 37 | } -------------------------------------------------------------------------------- /EpubReader/Entities/EpubSchema.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using VersOne.Epub.Schema; 19 | 20 | namespace VersOne.Epub 21 | { 22 | public class EpubSchema 23 | { 24 | public EpubPackage Package { get; set; } 25 | public EpubNavigation Navigation { get; set; } 26 | public string ContentDirectoryPath { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /EpubReader/Entities/EpubTextContentFile.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub 19 | { 20 | public class EpubTextContentFile : EpubContentFile 21 | { 22 | public string Content { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /EpubReader/EpubReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | using System.IO; 20 | using System.IO.Compression; 21 | using System.Linq; 22 | using System.Threading.Tasks; 23 | using VersOne.Epub.Internal; 24 | 25 | namespace VersOne.Epub 26 | { 27 | public static class EpubReader 28 | { 29 | /// 30 | /// Opens the book synchronously without reading its whole content. Holds the handle to the EPUB file. 31 | /// 32 | /// path to the EPUB file 33 | /// 34 | public static EpubBookRef OpenBook(string filePath) 35 | { 36 | return OpenBookAsync(filePath).Result; 37 | } 38 | 39 | /// 40 | /// Opens the book synchronously without reading its whole content. 41 | /// 42 | /// path to the EPUB file 43 | /// 44 | public static EpubBookRef OpenBook(Stream stream) 45 | { 46 | return OpenBookAsync(stream).Result; 47 | } 48 | 49 | /// 50 | /// Opens the book asynchronously without reading its whole content. Holds the handle to the EPUB file. 51 | /// 52 | /// path to the EPUB file 53 | /// 54 | public static Task OpenBookAsync(string filePath) 55 | { 56 | if (!File.Exists(filePath)) throw new FileNotFoundException("Specified epub file not found.", filePath); 57 | return OpenBookAsync(GetZipArchive(filePath)); 58 | } 59 | 60 | /// 61 | /// Opens the book asynchronously without reading its whole content. 62 | /// 63 | /// path to the EPUB file 64 | /// 65 | public static Task OpenBookAsync(Stream stream) 66 | { 67 | return OpenBookAsync(GetZipArchive(stream)); 68 | } 69 | 70 | /// 71 | /// Opens the book synchronously and reads all of its content into the memory. Does not hold the handle to the EPUB 72 | /// file. 73 | /// 74 | /// path to the EPUB file 75 | /// 76 | public static EpubBook ReadBook(string filePath) 77 | { 78 | return ReadBookAsync(filePath).Result; 79 | } 80 | 81 | /// 82 | /// Opens the book synchronously and reads all of its content into the memory. Does not hold the handle to the EPUB 83 | /// file. 84 | /// 85 | /// path to the EPUB file 86 | /// 87 | public static EpubBook ReadBook(Stream stream) 88 | { 89 | return ReadBookAsync(stream).Result; 90 | } 91 | 92 | /// 93 | /// Opens the book asynchronously and reads all of its content into the memory. Does not hold the handle to the EPUB 94 | /// file. 95 | /// 96 | /// path to the EPUB file 97 | /// 98 | public static async Task ReadBookAsync(string filePath) 99 | { 100 | var epubBookRef = await OpenBookAsync(filePath).ConfigureAwait(false); 101 | return await ReadBookAsync(epubBookRef).ConfigureAwait(false); 102 | } 103 | 104 | /// 105 | /// Opens the book asynchronously and reads all of its content into the memory. 106 | /// 107 | /// path to the EPUB file 108 | /// 109 | public static async Task ReadBookAsync(Stream stream) 110 | { 111 | var epubBookRef = await OpenBookAsync(stream).ConfigureAwait(false); 112 | return await ReadBookAsync(epubBookRef).ConfigureAwait(false); 113 | } 114 | 115 | private static async Task OpenBookAsync(ZipArchive zipArchive, string filePath = null) 116 | { 117 | EpubBookRef result = null; 118 | try 119 | { 120 | result = new EpubBookRef(zipArchive); 121 | result.FilePath = filePath; 122 | result.Schema = await SchemaReader.ReadSchemaAsync(zipArchive).ConfigureAwait(false); 123 | result.Title = result.Schema.Package.Metadata.Titles.FirstOrDefault() ?? string.Empty; 124 | result.AuthorList = result.Schema.Package.Metadata.Creators.Select(creator => creator.Creator).ToList(); 125 | result.Author = string.Join(", ", result.AuthorList); 126 | result.Content = await Task.Run(() => ContentReader.ParseContentMap(result)).ConfigureAwait(false); 127 | return result; 128 | } 129 | catch 130 | { 131 | result?.Dispose(); 132 | throw; 133 | } 134 | } 135 | 136 | private static async Task ReadBookAsync(EpubBookRef epubBookRef) 137 | { 138 | var result = new EpubBook(); 139 | using (epubBookRef) 140 | { 141 | result.FilePath = epubBookRef.FilePath; 142 | result.Schema = epubBookRef.Schema; 143 | result.Title = epubBookRef.Title; 144 | result.AuthorList = epubBookRef.AuthorList; 145 | result.Author = epubBookRef.Author; 146 | result.Content = await ReadContent(epubBookRef.Content).ConfigureAwait(false); 147 | result.CoverImage = await epubBookRef.ReadCoverAsync().ConfigureAwait(false); 148 | var chapterRefs = await epubBookRef.GetChaptersAsync().ConfigureAwait(false); 149 | result.Chapters = await ReadChapters(chapterRefs).ConfigureAwait(false); 150 | } 151 | 152 | return result; 153 | } 154 | 155 | private static ZipArchive GetZipArchive(string filePath) 156 | { 157 | return ZipFile.OpenRead(filePath); 158 | } 159 | 160 | private static ZipArchive GetZipArchive(Stream stream) 161 | { 162 | return new ZipArchive(stream, ZipArchiveMode.Read); 163 | } 164 | 165 | private static async Task ReadContent(EpubContentRef contentRef) 166 | { 167 | var result = new EpubContent(); 168 | result.Html = await ReadTextContentFiles(contentRef.Html).ConfigureAwait(false); 169 | result.Css = await ReadTextContentFiles(contentRef.Css).ConfigureAwait(false); 170 | result.Images = await ReadByteContentFiles(contentRef.Images).ConfigureAwait(false); 171 | result.Fonts = await ReadByteContentFiles(contentRef.Fonts).ConfigureAwait(false); 172 | result.AllFiles = new Dictionary(); 173 | foreach (var textContentFile in result.Html.Concat(result.Css)) 174 | result.AllFiles.Add(textContentFile.Key, textContentFile.Value); 175 | foreach (var byteContentFile in result.Images.Concat(result.Fonts)) 176 | result.AllFiles.Add(byteContentFile.Key, byteContentFile.Value); 177 | foreach (var contentFileRef in contentRef.AllFiles) 178 | if (!result.AllFiles.ContainsKey(contentFileRef.Key)) 179 | result.AllFiles.Add(contentFileRef.Key, 180 | await ReadByteContentFile(contentFileRef.Value).ConfigureAwait(false)); 181 | return result; 182 | } 183 | 184 | private static async Task> ReadTextContentFiles( 185 | Dictionary textContentFileRefs) 186 | { 187 | var result = new Dictionary(); 188 | foreach (var textContentFileRef in textContentFileRefs) 189 | { 190 | var textContentFile = new EpubTextContentFile 191 | { 192 | FileName = textContentFileRef.Value.FileName, 193 | ContentType = textContentFileRef.Value.ContentType, 194 | ContentMimeType = textContentFileRef.Value.ContentMimeType 195 | }; 196 | textContentFile.Content = await textContentFileRef.Value.ReadContentAsTextAsync().ConfigureAwait(false); 197 | result.Add(textContentFileRef.Key, textContentFile); 198 | } 199 | 200 | return result; 201 | } 202 | 203 | private static async Task> ReadByteContentFiles( 204 | Dictionary byteContentFileRefs) 205 | { 206 | var result = new Dictionary(); 207 | foreach (var byteContentFileRef in byteContentFileRefs) 208 | result.Add(byteContentFileRef.Key, 209 | await ReadByteContentFile(byteContentFileRef.Value).ConfigureAwait(false)); 210 | return result; 211 | } 212 | 213 | private static async Task ReadByteContentFile(EpubContentFileRef contentFileRef) 214 | { 215 | var result = new EpubByteContentFile 216 | { 217 | FileName = contentFileRef.FileName, 218 | ContentType = contentFileRef.ContentType, 219 | ContentMimeType = contentFileRef.ContentMimeType 220 | }; 221 | result.Content = await contentFileRef.ReadContentAsBytesAsync().ConfigureAwait(false); 222 | return result; 223 | } 224 | 225 | private static async Task> ReadChapters(List chapterRefs) 226 | { 227 | var result = new List(); 228 | foreach (var chapterRef in chapterRefs) 229 | { 230 | var chapter = new EpubChapter 231 | { 232 | Title = chapterRef.Title, 233 | ContentFileName = chapterRef.ContentFileName, 234 | Anchor = chapterRef.Anchor 235 | }; 236 | chapter.HtmlContent = await chapterRef.ReadHtmlContentAsync().ConfigureAwait(false); 237 | chapter.SubChapters = await ReadChapters(chapterRef.SubChapters).ConfigureAwait(false); 238 | result.Add(chapter); 239 | } 240 | 241 | return result; 242 | } 243 | } 244 | } -------------------------------------------------------------------------------- /EpubReader/Readers/BookCoverReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System; 19 | using System.Linq; 20 | using System.Threading.Tasks; 21 | 22 | namespace VersOne.Epub.Internal 23 | { 24 | internal static class BookCoverReader 25 | { 26 | public static async Task ReadBookCoverAsync(EpubBookRef bookRef) 27 | { 28 | var metaItems = bookRef.Schema.Package.Metadata.MetaItems; 29 | if (metaItems == null || !metaItems.Any()) return null; 30 | var coverMetaItem = metaItems.FirstOrDefault(metaItem => 31 | string.Compare(metaItem.Name, "cover", StringComparison.OrdinalIgnoreCase) == 0); 32 | if (coverMetaItem == null) return null; 33 | if (string.IsNullOrEmpty(coverMetaItem.Content)) 34 | throw new Exception("Incorrect EPUB metadata: cover item content is missing."); 35 | var coverManifestItem = bookRef.Schema.Package.Manifest.FirstOrDefault(manifestItem => 36 | string.Compare(manifestItem.Id, coverMetaItem.Content, StringComparison.OrdinalIgnoreCase) == 0); 37 | if (coverManifestItem == null) 38 | throw new Exception(string.Format("Incorrect EPUB manifest: item with ID = \"{0}\" is missing.", 39 | coverMetaItem.Content)); 40 | if (!bookRef.Content.Images.TryGetValue(coverManifestItem.Href, out var coverImageContentFileRef)) 41 | throw new Exception(string.Format("Incorrect EPUB manifest: item with href = \"{0}\" is missing.", 42 | coverManifestItem.Href)); 43 | var coverImageContent = await coverImageContentFileRef.ReadContentAsBytesAsync().ConfigureAwait(false); 44 | return coverImageContent; 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /EpubReader/Readers/ChapterReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.Linq; 21 | using System.Net; 22 | using VersOne.Epub.Schema; 23 | 24 | namespace VersOne.Epub.Internal 25 | { 26 | internal static class ChapterReader 27 | { 28 | public static List GetChapters(EpubBookRef bookRef) 29 | { 30 | return GetChapters(bookRef, bookRef.Schema.Package.Spine, bookRef.Schema.Navigation.NavMap); 31 | } 32 | 33 | public static List GetChapters(EpubBookRef bookRef, EpubSpine spine, 34 | List navigationPoints) 35 | { 36 | var result = new List(); 37 | for (var s = 0; s < spine.Count; s++) 38 | { 39 | var itemRef = spine[s]; 40 | string contentFileName; 41 | string anchor; 42 | contentFileName = WebUtility.UrlDecode(bookRef.Schema.Package.Manifest 43 | .FirstOrDefault(e => e.Id == itemRef.IdRef)?.Href); 44 | anchor = null; 45 | if (!bookRef.Content.Html.TryGetValue(contentFileName, out var htmlContentFileRef)) 46 | throw new Exception(string.Format("Incorrect EPUB manifest: item with href = \"{0}\" is missing.", 47 | contentFileName)); 48 | var chapterRef = new EpubChapterRef(htmlContentFileRef); 49 | chapterRef.ContentFileName = contentFileName; 50 | chapterRef.Anchor = anchor; 51 | chapterRef.Parent = null; 52 | var navPoint = navigationPoints.LastOrDefault(nav => 53 | spine.Take(s + 1) 54 | .Select(sp => bookRef.Schema.Package.Manifest.FirstOrDefault(e => e.Id == sp.IdRef)?.Href) 55 | .Contains(nav.Content.Source.Split('#')[0])); 56 | if (navPoint != null) 57 | chapterRef.Title = navPoint.NavigationLabels.First().Text; 58 | else 59 | chapterRef.Title = $"Chapter {s + 1}"; 60 | chapterRef.SubChapters = new List(); 61 | result.Add(chapterRef); 62 | } 63 | 64 | return result; 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /EpubReader/Readers/ContentReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Internal 21 | { 22 | internal static class ContentReader 23 | { 24 | public static EpubContentRef ParseContentMap(EpubBookRef bookRef) 25 | { 26 | var result = new EpubContentRef 27 | { 28 | Html = new Dictionary(), 29 | Css = new Dictionary(), 30 | Images = new Dictionary(), 31 | Fonts = new Dictionary(), 32 | AllFiles = new Dictionary() 33 | }; 34 | foreach (var manifestItem in bookRef.Schema.Package.Manifest) 35 | { 36 | var fileName = manifestItem.Href; 37 | var contentMimeType = manifestItem.MediaType; 38 | var contentType = GetContentTypeByContentMimeType(contentMimeType); 39 | switch (contentType) 40 | { 41 | case EpubContentType.XHTML_1_1: 42 | case EpubContentType.CSS: 43 | case EpubContentType.OEB1_DOCUMENT: 44 | case EpubContentType.OEB1_CSS: 45 | case EpubContentType.XML: 46 | case EpubContentType.DTBOOK: 47 | case EpubContentType.DTBOOK_NCX: 48 | var epubTextContentFile = new EpubTextContentFileRef(bookRef) 49 | { 50 | FileName = fileName, 51 | ContentMimeType = contentMimeType, 52 | ContentType = contentType 53 | }; 54 | switch (contentType) 55 | { 56 | case EpubContentType.XHTML_1_1: 57 | result.Html[fileName] = epubTextContentFile; 58 | break; 59 | case EpubContentType.CSS: 60 | result.Css[fileName] = epubTextContentFile; 61 | break; 62 | } 63 | 64 | result.AllFiles[fileName] = epubTextContentFile; 65 | break; 66 | default: 67 | var epubByteContentFile = new EpubByteContentFileRef(bookRef) 68 | { 69 | FileName = fileName, 70 | ContentMimeType = contentMimeType, 71 | ContentType = contentType 72 | }; 73 | switch (contentType) 74 | { 75 | case EpubContentType.IMAGE_GIF: 76 | case EpubContentType.IMAGE_JPEG: 77 | case EpubContentType.IMAGE_PNG: 78 | case EpubContentType.IMAGE_SVG: 79 | result.Images[fileName] = epubByteContentFile; 80 | break; 81 | case EpubContentType.FONT_TRUETYPE: 82 | case EpubContentType.FONT_OPENTYPE: 83 | result.Fonts[fileName] = epubByteContentFile; 84 | break; 85 | } 86 | 87 | result.AllFiles[fileName] = epubByteContentFile; 88 | break; 89 | } 90 | } 91 | 92 | return result; 93 | } 94 | 95 | private static EpubContentType GetContentTypeByContentMimeType(string contentMimeType) 96 | { 97 | switch (contentMimeType.ToLowerInvariant()) 98 | { 99 | case "application/xhtml+xml": 100 | return EpubContentType.XHTML_1_1; 101 | case "application/x-dtbook+xml": 102 | return EpubContentType.DTBOOK; 103 | case "application/x-dtbncx+xml": 104 | return EpubContentType.DTBOOK_NCX; 105 | case "text/x-oeb1-document": 106 | return EpubContentType.OEB1_DOCUMENT; 107 | case "application/xml": 108 | return EpubContentType.XML; 109 | case "text/css": 110 | return EpubContentType.CSS; 111 | case "text/x-oeb1-css": 112 | return EpubContentType.OEB1_CSS; 113 | case "image/gif": 114 | return EpubContentType.IMAGE_GIF; 115 | case "image/jpeg": 116 | return EpubContentType.IMAGE_JPEG; 117 | case "image/png": 118 | return EpubContentType.IMAGE_PNG; 119 | case "image/svg+xml": 120 | return EpubContentType.IMAGE_SVG; 121 | case "font/truetype": 122 | return EpubContentType.FONT_TRUETYPE; 123 | case "font/opentype": 124 | return EpubContentType.FONT_OPENTYPE; 125 | case "application/vnd.ms-opentype": 126 | return EpubContentType.FONT_OPENTYPE; 127 | default: 128 | return EpubContentType.OTHER; 129 | } 130 | } 131 | } 132 | } -------------------------------------------------------------------------------- /EpubReader/Readers/NavigationReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO.Compression; 21 | using System.Linq; 22 | using System.Threading.Tasks; 23 | using System.Xml.Linq; 24 | using VersOne.Epub.Schema; 25 | 26 | namespace VersOne.Epub.Internal 27 | { 28 | internal static class NavigationReader 29 | { 30 | public static async Task ReadNavigationAsync(ZipArchive epubArchive, 31 | string contentDirectoryPath, EpubPackage package) 32 | { 33 | var result = new EpubNavigation(); 34 | var tocId = package.Spine.Toc; 35 | if (string.IsNullOrEmpty(tocId)) throw new Exception("EPUB parsing error: TOC ID is empty."); 36 | var tocManifestItem = package.Manifest.FirstOrDefault(item => 37 | string.Compare(item.Id, tocId, StringComparison.OrdinalIgnoreCase) == 0); 38 | if (tocManifestItem == null) 39 | throw new Exception( 40 | string.Format("EPUB parsing error: TOC item {0} not found in EPUB manifest.", tocId)); 41 | var tocFileEntryPath = ZipPathUtils.Combine(contentDirectoryPath, tocManifestItem.Href); 42 | var tocFileEntry = epubArchive.GetEntry(tocFileEntryPath); 43 | if (tocFileEntry == null) 44 | throw new Exception(string.Format("EPUB parsing error: TOC file {0} not found in archive.", 45 | tocFileEntryPath)); 46 | if (tocFileEntry.Length > int.MaxValue) 47 | throw new Exception(string.Format("EPUB parsing error: TOC file {0} is larger than 2 Gb.", 48 | tocFileEntryPath)); 49 | XDocument containerDocument; 50 | using (var containerStream = tocFileEntry.Open()) 51 | { 52 | containerDocument = await XmlUtils.LoadDocumentAsync(containerStream).ConfigureAwait(false); 53 | } 54 | 55 | XNamespace ncxNamespace = "http://www.daisy.org/z3986/2005/ncx/"; 56 | var ncxNode = containerDocument.Element(ncxNamespace + "ncx"); 57 | if (ncxNode == null) throw new Exception("EPUB parsing error: TOC file does not contain ncx element."); 58 | var headNode = ncxNode.Element(ncxNamespace + "head"); 59 | if (headNode == null) throw new Exception("EPUB parsing error: TOC file does not contain head element."); 60 | var navigationHead = ReadNavigationHead(headNode); 61 | result.Head = navigationHead; 62 | var docTitleNode = ncxNode.Element(ncxNamespace + "docTitle"); 63 | if (docTitleNode == null) 64 | throw new Exception("EPUB parsing error: TOC file does not contain docTitle element."); 65 | var navigationDocTitle = ReadNavigationDocTitle(docTitleNode); 66 | result.DocTitle = navigationDocTitle; 67 | result.DocAuthors = new List(); 68 | foreach (var docAuthorNode in ncxNode.Elements(ncxNamespace + "docAuthor")) 69 | { 70 | var navigationDocAuthor = ReadNavigationDocAuthor(docAuthorNode); 71 | result.DocAuthors.Add(navigationDocAuthor); 72 | } 73 | 74 | var navMapNode = ncxNode.Element(ncxNamespace + "navMap"); 75 | if (navMapNode == null) 76 | throw new Exception("EPUB parsing error: TOC file does not contain navMap element."); 77 | var navMap = ReadNavigationMap(navMapNode); 78 | result.NavMap = navMap; 79 | var pageListNode = ncxNode.Element(ncxNamespace + "pageList"); 80 | if (pageListNode != null) 81 | { 82 | var pageList = ReadNavigationPageList(pageListNode); 83 | result.PageList = pageList; 84 | } 85 | 86 | result.NavLists = new List(); 87 | foreach (var navigationListNode in ncxNode.Elements(ncxNamespace + "navList")) 88 | { 89 | var navigationList = ReadNavigationList(navigationListNode); 90 | result.NavLists.Add(navigationList); 91 | } 92 | 93 | return result; 94 | } 95 | 96 | private static EpubNavigationHead ReadNavigationHead(XElement headNode) 97 | { 98 | var result = new EpubNavigationHead(); 99 | foreach (var metaNode in headNode.Elements()) 100 | if (string.Compare(metaNode.Name.LocalName, "meta", StringComparison.OrdinalIgnoreCase) == 0) 101 | { 102 | var meta = new EpubNavigationHeadMeta(); 103 | foreach (var metaNodeAttribute in metaNode.Attributes()) 104 | { 105 | var attributeValue = metaNodeAttribute.Value; 106 | switch (metaNodeAttribute.Name.LocalName.ToLowerInvariant()) 107 | { 108 | case "name": 109 | meta.Name = attributeValue; 110 | break; 111 | case "content": 112 | meta.Content = attributeValue; 113 | break; 114 | case "scheme": 115 | meta.Scheme = attributeValue; 116 | break; 117 | } 118 | } 119 | 120 | if (string.IsNullOrWhiteSpace(meta.Name)) 121 | throw new Exception("Incorrect EPUB navigation meta: meta name is missing."); 122 | if (meta.Content == null) 123 | throw new Exception("Incorrect EPUB navigation meta: meta content is missing."); 124 | result.Add(meta); 125 | } 126 | 127 | return result; 128 | } 129 | 130 | private static EpubNavigationDocTitle ReadNavigationDocTitle(XElement docTitleNode) 131 | { 132 | var result = new EpubNavigationDocTitle(); 133 | foreach (var textNode in docTitleNode.Elements()) 134 | if (string.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0) 135 | result.Add(textNode.Value); 136 | return result; 137 | } 138 | 139 | private static EpubNavigationDocAuthor ReadNavigationDocAuthor(XElement docAuthorNode) 140 | { 141 | var result = new EpubNavigationDocAuthor(); 142 | foreach (var textNode in docAuthorNode.Elements()) 143 | if (string.Compare(textNode.Name.LocalName, "text", StringComparison.OrdinalIgnoreCase) == 0) 144 | result.Add(textNode.Value); 145 | return result; 146 | } 147 | 148 | private static EpubNavigationMap ReadNavigationMap(XElement navigationMapNode) 149 | { 150 | var result = new EpubNavigationMap(); 151 | foreach (var navigationPointNode in navigationMapNode.Elements()) 152 | if (string.Compare(navigationPointNode.Name.LocalName, "navPoint", 153 | StringComparison.OrdinalIgnoreCase) == 0) 154 | { 155 | var navigationPoint = ReadNavigationPoint(navigationPointNode); 156 | result.Add(navigationPoint); 157 | } 158 | 159 | return result; 160 | } 161 | 162 | private static EpubNavigationPoint ReadNavigationPoint(XElement navigationPointNode) 163 | { 164 | var result = new EpubNavigationPoint(); 165 | foreach (var navigationPointNodeAttribute in navigationPointNode.Attributes()) 166 | { 167 | var attributeValue = navigationPointNodeAttribute.Value; 168 | switch (navigationPointNodeAttribute.Name.LocalName.ToLowerInvariant()) 169 | { 170 | case "id": 171 | result.Id = attributeValue; 172 | break; 173 | case "class": 174 | result.Class = attributeValue; 175 | break; 176 | case "playOrder": 177 | result.PlayOrder = attributeValue; 178 | break; 179 | } 180 | } 181 | 182 | if (string.IsNullOrWhiteSpace(result.Id)) 183 | throw new Exception("Incorrect EPUB navigation point: point ID is missing."); 184 | result.NavigationLabels = new List(); 185 | result.ChildNavigationPoints = new List(); 186 | foreach (var navigationPointChildNode in navigationPointNode.Elements()) 187 | switch (navigationPointChildNode.Name.LocalName.ToLowerInvariant()) 188 | { 189 | case "navlabel": 190 | var navigationLabel = ReadNavigationLabel(navigationPointChildNode); 191 | result.NavigationLabels.Add(navigationLabel); 192 | break; 193 | case "content": 194 | var content = ReadNavigationContent(navigationPointChildNode); 195 | result.Content = content; 196 | break; 197 | case "navpoint": 198 | var childNavigationPoint = ReadNavigationPoint(navigationPointChildNode); 199 | result.ChildNavigationPoints.Add(childNavigationPoint); 200 | break; 201 | } 202 | if (!result.NavigationLabels.Any()) 203 | throw new Exception(string.Format( 204 | "EPUB parsing error: navigation point {0} should contain at least one navigation label.", 205 | result.Id)); 206 | if (result.Content == null) 207 | throw new Exception(string.Format("EPUB parsing error: navigation point {0} should contain content.", 208 | result.Id)); 209 | return result; 210 | } 211 | 212 | private static EpubNavigationLabel ReadNavigationLabel(XElement navigationLabelNode) 213 | { 214 | var result = new EpubNavigationLabel(); 215 | var navigationLabelTextNode = navigationLabelNode.Element(navigationLabelNode.Name.Namespace + "text"); 216 | if (navigationLabelTextNode == null) 217 | throw new Exception("Incorrect EPUB navigation label: label text element is missing."); 218 | result.Text = navigationLabelTextNode.Value; 219 | return result; 220 | } 221 | 222 | private static EpubNavigationContent ReadNavigationContent(XElement navigationContentNode) 223 | { 224 | var result = new EpubNavigationContent(); 225 | foreach (var navigationContentNodeAttribute in navigationContentNode.Attributes()) 226 | { 227 | var attributeValue = navigationContentNodeAttribute.Value; 228 | switch (navigationContentNodeAttribute.Name.LocalName.ToLowerInvariant()) 229 | { 230 | case "id": 231 | result.Id = attributeValue; 232 | break; 233 | case "src": 234 | result.Source = attributeValue; 235 | break; 236 | } 237 | } 238 | 239 | if (string.IsNullOrWhiteSpace(result.Source)) 240 | throw new Exception("Incorrect EPUB navigation content: content source is missing."); 241 | return result; 242 | } 243 | 244 | private static EpubNavigationPageList ReadNavigationPageList(XElement navigationPageListNode) 245 | { 246 | var result = new EpubNavigationPageList(); 247 | foreach (var pageTargetNode in navigationPageListNode.Elements()) 248 | if (string.Compare(pageTargetNode.Name.LocalName, "pageTarget", StringComparison.OrdinalIgnoreCase) == 249 | 0) 250 | { 251 | var pageTarget = ReadNavigationPageTarget(pageTargetNode); 252 | result.Add(pageTarget); 253 | } 254 | 255 | return result; 256 | } 257 | 258 | private static EpubNavigationPageTarget ReadNavigationPageTarget(XElement navigationPageTargetNode) 259 | { 260 | var result = new EpubNavigationPageTarget(); 261 | foreach (var navigationPageTargetNodeAttribute in navigationPageTargetNode.Attributes()) 262 | { 263 | var attributeValue = navigationPageTargetNodeAttribute.Value; 264 | switch (navigationPageTargetNodeAttribute.Name.LocalName.ToLowerInvariant()) 265 | { 266 | case "id": 267 | result.Id = attributeValue; 268 | break; 269 | case "value": 270 | result.Value = attributeValue; 271 | break; 272 | case "type": 273 | EpubNavigationPageTargetType type; 274 | if (!Enum.TryParse(attributeValue, out type)) 275 | throw new Exception(string.Format( 276 | "Incorrect EPUB navigation page target: {0} is incorrect value for page target type.", 277 | attributeValue)); 278 | result.Type = type; 279 | break; 280 | case "class": 281 | result.Class = attributeValue; 282 | break; 283 | case "playOrder": 284 | result.PlayOrder = attributeValue; 285 | break; 286 | } 287 | } 288 | 289 | if (result.Type == default(EpubNavigationPageTargetType)) 290 | throw new Exception("Incorrect EPUB navigation page target: page target type is missing."); 291 | foreach (var navigationPageTargetChildNode in navigationPageTargetNode.Elements()) 292 | switch (navigationPageTargetChildNode.Name.LocalName.ToLowerInvariant()) 293 | { 294 | case "navlabel": 295 | var navigationLabel = ReadNavigationLabel(navigationPageTargetChildNode); 296 | result.NavigationLabels.Add(navigationLabel); 297 | break; 298 | case "content": 299 | var content = ReadNavigationContent(navigationPageTargetChildNode); 300 | result.Content = content; 301 | break; 302 | } 303 | if (!result.NavigationLabels.Any()) 304 | throw new Exception( 305 | "Incorrect EPUB navigation page target: at least one navLabel element is required."); 306 | return result; 307 | } 308 | 309 | private static EpubNavigationList ReadNavigationList(XElement navigationListNode) 310 | { 311 | var result = new EpubNavigationList(); 312 | foreach (var navigationListNodeAttribute in navigationListNode.Attributes()) 313 | { 314 | var attributeValue = navigationListNodeAttribute.Value; 315 | switch (navigationListNodeAttribute.Name.LocalName.ToLowerInvariant()) 316 | { 317 | case "id": 318 | result.Id = attributeValue; 319 | break; 320 | case "class": 321 | result.Class = attributeValue; 322 | break; 323 | } 324 | } 325 | 326 | foreach (var navigationListChildNode in navigationListNode.Elements()) 327 | switch (navigationListChildNode.Name.LocalName.ToLowerInvariant()) 328 | { 329 | case "navlabel": 330 | var navigationLabel = ReadNavigationLabel(navigationListChildNode); 331 | result.NavigationLabels.Add(navigationLabel); 332 | break; 333 | case "navTarget": 334 | var navigationTarget = ReadNavigationTarget(navigationListChildNode); 335 | result.NavigationTargets.Add(navigationTarget); 336 | break; 337 | } 338 | if (!result.NavigationLabels.Any()) 339 | throw new Exception( 340 | "Incorrect EPUB navigation page target: at least one navLabel element is required."); 341 | return result; 342 | } 343 | 344 | private static EpubNavigationTarget ReadNavigationTarget(XElement navigationTargetNode) 345 | { 346 | var result = new EpubNavigationTarget(); 347 | foreach (var navigationPageTargetNodeAttribute in navigationTargetNode.Attributes()) 348 | { 349 | var attributeValue = navigationPageTargetNodeAttribute.Value; 350 | switch (navigationPageTargetNodeAttribute.Name.LocalName.ToLowerInvariant()) 351 | { 352 | case "id": 353 | result.Id = attributeValue; 354 | break; 355 | case "value": 356 | result.Value = attributeValue; 357 | break; 358 | case "class": 359 | result.Class = attributeValue; 360 | break; 361 | case "playOrder": 362 | result.PlayOrder = attributeValue; 363 | break; 364 | } 365 | } 366 | 367 | if (string.IsNullOrWhiteSpace(result.Id)) 368 | throw new Exception("Incorrect EPUB navigation target: navigation target ID is missing."); 369 | foreach (var navigationTargetChildNode in navigationTargetNode.Elements()) 370 | switch (navigationTargetChildNode.Name.LocalName.ToLowerInvariant()) 371 | { 372 | case "navlabel": 373 | var navigationLabel = ReadNavigationLabel(navigationTargetChildNode); 374 | result.NavigationLabels.Add(navigationLabel); 375 | break; 376 | case "content": 377 | var content = ReadNavigationContent(navigationTargetChildNode); 378 | result.Content = content; 379 | break; 380 | } 381 | if (!result.NavigationLabels.Any()) 382 | throw new Exception("Incorrect EPUB navigation target: at least one navLabel element is required."); 383 | return result; 384 | } 385 | } 386 | } -------------------------------------------------------------------------------- /EpubReader/Readers/PackageReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO.Compression; 21 | using System.Threading.Tasks; 22 | using System.Xml.Linq; 23 | using VersOne.Epub.Schema; 24 | 25 | namespace VersOne.Epub.Internal 26 | { 27 | internal static class PackageReader 28 | { 29 | public static async Task ReadPackageAsync(ZipArchive epubArchive, string rootFilePath) 30 | { 31 | var rootFileEntry = epubArchive.GetEntry(rootFilePath); 32 | if (rootFileEntry == null) throw new Exception("EPUB parsing error: root file not found in archive."); 33 | XDocument containerDocument; 34 | using (var containerStream = rootFileEntry.Open()) 35 | { 36 | containerDocument = await XmlUtils.LoadDocumentAsync(containerStream).ConfigureAwait(false); 37 | } 38 | 39 | XNamespace opfNamespace = "http://www.idpf.org/2007/opf"; 40 | var packageNode = containerDocument.Element(opfNamespace + "package"); 41 | var result = new EpubPackage(); 42 | var epubVersionValue = packageNode.Attribute("version").Value; 43 | if (epubVersionValue == "2.0") 44 | result.EpubVersion = EpubVersion.EPUB_2; 45 | else if (epubVersionValue == "3.0") 46 | result.EpubVersion = EpubVersion.EPUB_3; 47 | else 48 | throw new Exception(string.Format("Unsupported EPUB version: {0}.", epubVersionValue)); 49 | var metadataNode = packageNode.Element(opfNamespace + "metadata"); 50 | if (metadataNode == null) throw new Exception("EPUB parsing error: metadata not found in the package."); 51 | var metadata = ReadMetadata(metadataNode, result.EpubVersion); 52 | result.Metadata = metadata; 53 | var manifestNode = packageNode.Element(opfNamespace + "manifest"); 54 | if (manifestNode == null) throw new Exception("EPUB parsing error: manifest not found in the package."); 55 | var manifest = ReadManifest(manifestNode); 56 | result.Manifest = manifest; 57 | var spineNode = packageNode.Element(opfNamespace + "spine"); 58 | if (spineNode == null) throw new Exception("EPUB parsing error: spine not found in the package."); 59 | var spine = ReadSpine(spineNode); 60 | result.Spine = spine; 61 | var guideNode = packageNode.Element(opfNamespace + "guide"); 62 | if (guideNode != null) 63 | { 64 | var guide = ReadGuide(guideNode); 65 | result.Guide = guide; 66 | } 67 | 68 | return result; 69 | } 70 | 71 | private static EpubMetadata ReadMetadata(XElement metadataNode, EpubVersion epubVersion) 72 | { 73 | var result = new EpubMetadata 74 | { 75 | Titles = new List(), 76 | Creators = new List(), 77 | Subjects = new List(), 78 | Publishers = new List(), 79 | Contributors = new List(), 80 | Dates = new List(), 81 | Types = new List(), 82 | Formats = new List(), 83 | Identifiers = new List(), 84 | Sources = new List(), 85 | Languages = new List(), 86 | Relations = new List(), 87 | Coverages = new List(), 88 | Rights = new List(), 89 | MetaItems = new List() 90 | }; 91 | foreach (var metadataItemNode in metadataNode.Elements()) 92 | { 93 | var innerText = metadataItemNode.Value; 94 | switch (metadataItemNode.Name.LocalName.ToLowerInvariant()) 95 | { 96 | case "title": 97 | result.Titles.Add(innerText); 98 | break; 99 | case "creator": 100 | var creator = ReadMetadataCreator(metadataItemNode); 101 | result.Creators.Add(creator); 102 | break; 103 | case "subject": 104 | result.Subjects.Add(innerText); 105 | break; 106 | case "description": 107 | result.Description = innerText; 108 | break; 109 | case "publisher": 110 | result.Publishers.Add(innerText); 111 | break; 112 | case "contributor": 113 | var contributor = ReadMetadataContributor(metadataItemNode); 114 | result.Contributors.Add(contributor); 115 | break; 116 | case "date": 117 | var date = ReadMetadataDate(metadataItemNode); 118 | result.Dates.Add(date); 119 | break; 120 | case "type": 121 | result.Types.Add(innerText); 122 | break; 123 | case "format": 124 | result.Formats.Add(innerText); 125 | break; 126 | case "identifier": 127 | var identifier = ReadMetadataIdentifier(metadataItemNode); 128 | result.Identifiers.Add(identifier); 129 | break; 130 | case "source": 131 | result.Sources.Add(innerText); 132 | break; 133 | case "language": 134 | result.Languages.Add(innerText); 135 | break; 136 | case "relation": 137 | result.Relations.Add(innerText); 138 | break; 139 | case "coverage": 140 | result.Coverages.Add(innerText); 141 | break; 142 | case "rights": 143 | result.Rights.Add(innerText); 144 | break; 145 | case "meta": 146 | if (epubVersion == EpubVersion.EPUB_2) 147 | { 148 | var meta = ReadMetadataMetaVersion2(metadataItemNode); 149 | result.MetaItems.Add(meta); 150 | } 151 | else if (epubVersion == EpubVersion.EPUB_3) 152 | { 153 | var meta = ReadMetadataMetaVersion3(metadataItemNode); 154 | result.MetaItems.Add(meta); 155 | } 156 | 157 | break; 158 | } 159 | } 160 | 161 | return result; 162 | } 163 | 164 | private static EpubMetadataCreator ReadMetadataCreator(XElement metadataCreatorNode) 165 | { 166 | var result = new EpubMetadataCreator(); 167 | foreach (var metadataCreatorNodeAttribute in metadataCreatorNode.Attributes()) 168 | { 169 | var attributeValue = metadataCreatorNodeAttribute.Value; 170 | switch (metadataCreatorNodeAttribute.Name.LocalName.ToLowerInvariant()) 171 | { 172 | case "role": 173 | result.Role = attributeValue; 174 | break; 175 | case "file-as": 176 | result.FileAs = attributeValue; 177 | break; 178 | } 179 | } 180 | 181 | result.Creator = metadataCreatorNode.Value; 182 | return result; 183 | } 184 | 185 | private static EpubMetadataContributor ReadMetadataContributor(XElement metadataContributorNode) 186 | { 187 | var result = new EpubMetadataContributor(); 188 | foreach (var metadataContributorNodeAttribute in metadataContributorNode.Attributes()) 189 | { 190 | var attributeValue = metadataContributorNodeAttribute.Value; 191 | switch (metadataContributorNodeAttribute.Name.LocalName.ToLowerInvariant()) 192 | { 193 | case "role": 194 | result.Role = attributeValue; 195 | break; 196 | case "file-as": 197 | result.FileAs = attributeValue; 198 | break; 199 | } 200 | } 201 | 202 | result.Contributor = metadataContributorNode.Value; 203 | return result; 204 | } 205 | 206 | private static EpubMetadataDate ReadMetadataDate(XElement metadataDateNode) 207 | { 208 | var result = new EpubMetadataDate(); 209 | var eventAttribute = metadataDateNode.Attribute(metadataDateNode.Name.Namespace + "event"); 210 | if (eventAttribute != null) result.Event = eventAttribute.Value; 211 | result.Date = metadataDateNode.Value; 212 | return result; 213 | } 214 | 215 | private static EpubMetadataIdentifier ReadMetadataIdentifier(XElement metadataIdentifierNode) 216 | { 217 | var result = new EpubMetadataIdentifier(); 218 | foreach (var metadataIdentifierNodeAttribute in metadataIdentifierNode.Attributes()) 219 | { 220 | var attributeValue = metadataIdentifierNodeAttribute.Value; 221 | switch (metadataIdentifierNodeAttribute.Name.LocalName.ToLowerInvariant()) 222 | { 223 | case "id": 224 | result.Id = attributeValue; 225 | break; 226 | case "opf:scheme": 227 | result.Scheme = attributeValue; 228 | break; 229 | } 230 | } 231 | 232 | result.Identifier = metadataIdentifierNode.Value; 233 | return result; 234 | } 235 | 236 | private static EpubMetadataMeta ReadMetadataMetaVersion2(XElement metadataMetaNode) 237 | { 238 | var result = new EpubMetadataMeta(); 239 | foreach (var metadataMetaNodeAttribute in metadataMetaNode.Attributes()) 240 | { 241 | var attributeValue = metadataMetaNodeAttribute.Value; 242 | switch (metadataMetaNodeAttribute.Name.LocalName.ToLowerInvariant()) 243 | { 244 | case "name": 245 | result.Name = attributeValue; 246 | break; 247 | case "content": 248 | result.Content = attributeValue; 249 | break; 250 | } 251 | } 252 | 253 | return result; 254 | } 255 | 256 | private static EpubMetadataMeta ReadMetadataMetaVersion3(XElement metadataMetaNode) 257 | { 258 | var result = new EpubMetadataMeta(); 259 | foreach (var metadataMetaNodeAttribute in metadataMetaNode.Attributes()) 260 | { 261 | var attributeValue = metadataMetaNodeAttribute.Value; 262 | switch (metadataMetaNodeAttribute.Name.LocalName.ToLowerInvariant()) 263 | { 264 | case "id": 265 | result.Id = attributeValue; 266 | break; 267 | case "refines": 268 | result.Refines = attributeValue; 269 | break; 270 | case "property": 271 | result.Property = attributeValue; 272 | break; 273 | case "scheme": 274 | result.Scheme = attributeValue; 275 | break; 276 | } 277 | } 278 | 279 | result.Content = metadataMetaNode.Value; 280 | return result; 281 | } 282 | 283 | private static EpubManifest ReadManifest(XElement manifestNode) 284 | { 285 | var result = new EpubManifest(); 286 | foreach (var manifestItemNode in manifestNode.Elements()) 287 | if (string.Compare(manifestItemNode.Name.LocalName, "item", StringComparison.OrdinalIgnoreCase) == 0) 288 | { 289 | var manifestItem = new EpubManifestItem(); 290 | foreach (var manifestItemNodeAttribute in manifestItemNode.Attributes()) 291 | { 292 | var attributeValue = manifestItemNodeAttribute.Value; 293 | switch (manifestItemNodeAttribute.Name.LocalName.ToLowerInvariant()) 294 | { 295 | case "id": 296 | manifestItem.Id = attributeValue; 297 | break; 298 | case "href": 299 | manifestItem.Href = Uri.UnescapeDataString(attributeValue); 300 | break; 301 | case "media-type": 302 | manifestItem.MediaType = attributeValue; 303 | break; 304 | case "required-namespace": 305 | manifestItem.RequiredNamespace = attributeValue; 306 | break; 307 | case "required-modules": 308 | manifestItem.RequiredModules = attributeValue; 309 | break; 310 | case "fallback": 311 | manifestItem.Fallback = attributeValue; 312 | break; 313 | case "fallback-style": 314 | manifestItem.FallbackStyle = attributeValue; 315 | break; 316 | } 317 | } 318 | 319 | if (string.IsNullOrWhiteSpace(manifestItem.Id)) 320 | throw new Exception("Incorrect EPUB manifest: item ID is missing"); 321 | if (string.IsNullOrWhiteSpace(manifestItem.Href)) 322 | throw new Exception("Incorrect EPUB manifest: item href is missing"); 323 | if (string.IsNullOrWhiteSpace(manifestItem.MediaType)) 324 | throw new Exception("Incorrect EPUB manifest: item media type is missing"); 325 | result.Add(manifestItem); 326 | } 327 | 328 | return result; 329 | } 330 | 331 | private static EpubSpine ReadSpine(XElement spineNode) 332 | { 333 | var result = new EpubSpine(); 334 | var tocAttribute = spineNode.Attribute("toc"); 335 | if (tocAttribute == null || string.IsNullOrWhiteSpace(tocAttribute.Value)) 336 | throw new Exception("Incorrect EPUB spine: TOC is missing"); 337 | result.Toc = tocAttribute.Value; 338 | foreach (var spineItemNode in spineNode.Elements()) 339 | if (string.Compare(spineItemNode.Name.LocalName, "itemref", StringComparison.OrdinalIgnoreCase) == 0) 340 | { 341 | var spineItemRef = new EpubSpineItemRef(); 342 | var idRefAttribute = spineItemNode.Attribute("idref"); 343 | if (idRefAttribute == null || string.IsNullOrWhiteSpace(idRefAttribute.Value)) 344 | throw new Exception("Incorrect EPUB spine: item ID ref is missing"); 345 | spineItemRef.IdRef = idRefAttribute.Value; 346 | var linearAttribute = spineItemNode.Attribute("linear"); 347 | spineItemRef.IsLinear = linearAttribute == null || 348 | string.Compare(linearAttribute.Value, "no", 349 | StringComparison.OrdinalIgnoreCase) != 0; 350 | result.Add(spineItemRef); 351 | } 352 | 353 | return result; 354 | } 355 | 356 | private static EpubGuide ReadGuide(XElement guideNode) 357 | { 358 | var result = new EpubGuide(); 359 | foreach (var guideReferenceNode in guideNode.Elements()) 360 | if (string.Compare(guideReferenceNode.Name.LocalName, "reference", 361 | StringComparison.OrdinalIgnoreCase) == 0) 362 | { 363 | var guideReference = new EpubGuideReference(); 364 | foreach (var guideReferenceNodeAttribute in guideReferenceNode.Attributes()) 365 | { 366 | var attributeValue = guideReferenceNodeAttribute.Value; 367 | switch (guideReferenceNodeAttribute.Name.LocalName.ToLowerInvariant()) 368 | { 369 | case "type": 370 | guideReference.Type = attributeValue; 371 | break; 372 | case "title": 373 | guideReference.Title = attributeValue; 374 | break; 375 | case "href": 376 | guideReference.Href = Uri.UnescapeDataString(attributeValue); 377 | break; 378 | } 379 | } 380 | 381 | if (string.IsNullOrWhiteSpace(guideReference.Type)) 382 | throw new Exception("Incorrect EPUB guide: item type is missing"); 383 | if (string.IsNullOrWhiteSpace(guideReference.Href)) 384 | throw new Exception("Incorrect EPUB guide: item href is missing"); 385 | result.Add(guideReference); 386 | } 387 | 388 | return result; 389 | } 390 | } 391 | } -------------------------------------------------------------------------------- /EpubReader/Readers/RootFilePathReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System; 19 | using System.IO.Compression; 20 | using System.Threading.Tasks; 21 | using System.Xml.Linq; 22 | 23 | namespace VersOne.Epub.Internal 24 | { 25 | internal static class RootFilePathReader 26 | { 27 | public static async Task GetRootFilePathAsync(ZipArchive epubArchive) 28 | { 29 | const string EPUB_CONTAINER_FILE_PATH = "META-INF/container.xml"; 30 | var containerFileEntry = epubArchive.GetEntry(EPUB_CONTAINER_FILE_PATH); 31 | if (containerFileEntry == null) 32 | throw new Exception(string.Format("EPUB parsing error: {0} file not found in archive.", 33 | EPUB_CONTAINER_FILE_PATH)); 34 | XDocument containerDocument; 35 | using (var containerStream = containerFileEntry.Open()) 36 | { 37 | containerDocument = await XmlUtils.LoadDocumentAsync(containerStream).ConfigureAwait(false); 38 | } 39 | 40 | XNamespace cnsNamespace = "urn:oasis:names:tc:opendocument:xmlns:container"; 41 | var fullPathAttribute = containerDocument.Element(cnsNamespace + "container") 42 | ?.Element(cnsNamespace + "rootfiles")?.Element(cnsNamespace + "rootfile")?.Attribute("full-path"); 43 | if (fullPathAttribute == null) 44 | throw new Exception("EPUB parsing error: root file path not found in the EPUB container."); 45 | return fullPathAttribute.Value; 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /EpubReader/Readers/SchemaReader.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.IO.Compression; 19 | using System.Threading.Tasks; 20 | 21 | namespace VersOne.Epub.Internal 22 | { 23 | internal static class SchemaReader 24 | { 25 | public static async Task ReadSchemaAsync(ZipArchive epubArchive) 26 | { 27 | var result = new EpubSchema(); 28 | var rootFilePath = await RootFilePathReader.GetRootFilePathAsync(epubArchive).ConfigureAwait(false); 29 | var contentDirectoryPath = ZipPathUtils.GetDirectoryPath(rootFilePath); 30 | result.ContentDirectoryPath = contentDirectoryPath; 31 | var package = await PackageReader.ReadPackageAsync(epubArchive, rootFilePath).ConfigureAwait(false); 32 | result.Package = package; 33 | var navigation = await NavigationReader.ReadNavigationAsync(epubArchive, contentDirectoryPath, package) 34 | .ConfigureAwait(false); 35 | result.Navigation = navigation; 36 | return result; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /EpubReader/RefEntities/EpubBookRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System; 19 | using System.Collections.Generic; 20 | using System.IO.Compression; 21 | using System.Threading.Tasks; 22 | using VersOne.Epub.Internal; 23 | 24 | namespace VersOne.Epub 25 | { 26 | public class EpubBookRef : IDisposable 27 | { 28 | private bool isDisposed; 29 | 30 | public EpubBookRef(ZipArchive epubArchive) 31 | { 32 | EpubArchive = epubArchive; 33 | isDisposed = false; 34 | } 35 | 36 | public string FilePath { get; set; } 37 | public string Title { get; set; } 38 | public string Author { get; set; } 39 | public List AuthorList { get; set; } 40 | public EpubSchema Schema { get; set; } 41 | public EpubContentRef Content { get; set; } 42 | 43 | internal ZipArchive EpubArchive { get; } 44 | 45 | public void Dispose() 46 | { 47 | Dispose(true); 48 | GC.SuppressFinalize(this); 49 | } 50 | 51 | ~EpubBookRef() 52 | { 53 | Dispose(false); 54 | } 55 | 56 | public byte[] ReadCover() 57 | { 58 | return ReadCoverAsync().Result; 59 | } 60 | 61 | public async Task ReadCoverAsync() 62 | { 63 | return await BookCoverReader.ReadBookCoverAsync(this).ConfigureAwait(false); 64 | } 65 | 66 | public List GetChapters() 67 | { 68 | return GetChaptersAsync().Result; 69 | } 70 | 71 | public async Task> GetChaptersAsync() 72 | { 73 | return await Task.Run(() => ChapterReader.GetChapters(this)).ConfigureAwait(false); 74 | } 75 | 76 | protected virtual void Dispose(bool disposing) 77 | { 78 | if (!isDisposed) 79 | { 80 | if (disposing) EpubArchive?.Dispose(); 81 | isDisposed = true; 82 | } 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /EpubReader/RefEntities/EpubByteContentFileRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Threading.Tasks; 19 | 20 | namespace VersOne.Epub 21 | { 22 | public class EpubByteContentFileRef : EpubContentFileRef 23 | { 24 | public EpubByteContentFileRef(EpubBookRef epubBookRef) 25 | : base(epubBookRef) 26 | { 27 | } 28 | 29 | public byte[] ReadContent() 30 | { 31 | return ReadContentAsBytes(); 32 | } 33 | 34 | public Task ReadContentAsync() 35 | { 36 | return ReadContentAsBytesAsync(); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /EpubReader/RefEntities/EpubChapterRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | using System.Threading.Tasks; 20 | 21 | namespace VersOne.Epub 22 | { 23 | public class EpubChapterRef 24 | { 25 | private readonly EpubTextContentFileRef epubTextContentFileRef; 26 | 27 | public EpubChapterRef(EpubTextContentFileRef epubTextContentFileRef) 28 | { 29 | this.epubTextContentFileRef = epubTextContentFileRef; 30 | } 31 | 32 | public string Title { get; set; } 33 | public string ContentFileName { get; set; } 34 | public string Anchor { get; set; } 35 | public List SubChapters { get; set; } 36 | public EpubChapterRef Parent { get; set; } 37 | 38 | public string ReadHtmlContent() 39 | { 40 | return ReadHtmlContentAsync().Result; 41 | } 42 | 43 | public Task ReadHtmlContentAsync() 44 | { 45 | return epubTextContentFileRef.ReadContentAsTextAsync(); 46 | } 47 | 48 | public override string ToString() 49 | { 50 | return string.Format("Title: {0}, Subchapter count: {1}", Title, SubChapters.Count); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /EpubReader/RefEntities/EpubContentFileRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System; 19 | using System.IO; 20 | using System.IO.Compression; 21 | using System.Threading.Tasks; 22 | using VersOne.Epub.Internal; 23 | 24 | namespace VersOne.Epub 25 | { 26 | public abstract class EpubContentFileRef 27 | { 28 | private readonly EpubBookRef epubBookRef; 29 | 30 | public EpubContentFileRef(EpubBookRef epubBookRef) 31 | { 32 | this.epubBookRef = epubBookRef; 33 | } 34 | 35 | public string FileName { get; set; } 36 | public EpubContentType ContentType { get; set; } 37 | public string ContentMimeType { get; set; } 38 | 39 | public byte[] ReadContentAsBytes() 40 | { 41 | return ReadContentAsBytesAsync().Result; 42 | } 43 | 44 | public async Task ReadContentAsBytesAsync() 45 | { 46 | var contentFileEntry = GetContentFileEntry(); 47 | var content = new byte[(int) contentFileEntry.Length]; 48 | using (var contentStream = OpenContentStream(contentFileEntry)) 49 | using (var memoryStream = new MemoryStream(content)) 50 | { 51 | await contentStream.CopyToAsync(memoryStream).ConfigureAwait(false); 52 | } 53 | 54 | return content; 55 | } 56 | 57 | public string ReadContentAsText() 58 | { 59 | return ReadContentAsTextAsync().Result; 60 | } 61 | 62 | public async Task ReadContentAsTextAsync() 63 | { 64 | using (var contentStream = GetContentStream()) 65 | using (var streamReader = new StreamReader(contentStream)) 66 | { 67 | return await streamReader.ReadToEndAsync().ConfigureAwait(false); 68 | } 69 | } 70 | 71 | public Stream GetContentStream() 72 | { 73 | return OpenContentStream(GetContentFileEntry()); 74 | } 75 | 76 | private ZipArchiveEntry GetContentFileEntry() 77 | { 78 | var contentFilePath = ZipPathUtils.Combine(epubBookRef.Schema.ContentDirectoryPath, FileName); 79 | var contentFileEntry = epubBookRef.EpubArchive.GetEntry(contentFilePath); 80 | if (contentFileEntry == null) 81 | throw new Exception( 82 | string.Format("EPUB parsing error: file {0} not found in archive.", contentFilePath)); 83 | if (contentFileEntry.Length > int.MaxValue) 84 | throw new Exception(string.Format("EPUB parsing error: file {0} is bigger than 2 Gb.", 85 | contentFilePath)); 86 | return contentFileEntry; 87 | } 88 | 89 | private Stream OpenContentStream(ZipArchiveEntry contentFileEntry) 90 | { 91 | var contentStream = contentFileEntry.Open(); 92 | if (contentStream == null) 93 | throw new Exception(string.Format( 94 | "Incorrect EPUB file: content file \"{0}\" specified in manifest is not found.", FileName)); 95 | return contentStream; 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /EpubReader/RefEntities/EpubContentRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub 21 | { 22 | public class EpubContentRef 23 | { 24 | public Dictionary Html { get; set; } 25 | public Dictionary Css { get; set; } 26 | public Dictionary Images { get; set; } 27 | public Dictionary Fonts { get; set; } 28 | public Dictionary AllFiles { get; set; } 29 | } 30 | } -------------------------------------------------------------------------------- /EpubReader/RefEntities/EpubTextContentFileRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Threading.Tasks; 19 | 20 | namespace VersOne.Epub 21 | { 22 | public class EpubTextContentFileRef : EpubContentFileRef 23 | { 24 | public EpubTextContentFileRef(EpubBookRef epubBookRef) 25 | : base(epubBookRef) 26 | { 27 | } 28 | 29 | public string ReadContent() 30 | { 31 | return ReadContentAsText(); 32 | } 33 | 34 | public Task ReadContentAsync() 35 | { 36 | return ReadContentAsTextAsync(); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigation.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigation 23 | { 24 | public EpubNavigationHead Head { get; set; } 25 | public EpubNavigationDocTitle DocTitle { get; set; } 26 | public List DocAuthors { get; set; } 27 | public EpubNavigationMap NavMap { get; set; } 28 | public EpubNavigationPageList PageList { get; set; } 29 | public List NavLists { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationContent.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubNavigationContent 21 | { 22 | public string Id { get; set; } 23 | public string Source { get; set; } 24 | 25 | public override string ToString() 26 | { 27 | return string.Concat("Source: " + Source); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationDocAuthor.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigationDocAuthor : List 23 | { 24 | } 25 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationDocTitle.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigationDocTitle : List 23 | { 24 | } 25 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationHead.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigationHead : List 23 | { 24 | } 25 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationHeadMeta.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubNavigationHeadMeta 21 | { 22 | public string Name { get; set; } 23 | public string Content { get; set; } 24 | public string Scheme { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationLabel.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubNavigationLabel 21 | { 22 | public string Text { get; set; } 23 | 24 | public override string ToString() 25 | { 26 | return Text; 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationList.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigationList 23 | { 24 | public string Id { get; set; } 25 | public string Class { get; set; } 26 | public List NavigationLabels { get; set; } 27 | public List NavigationTargets { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationMap.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigationMap : List 23 | { 24 | } 25 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationPageList.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigationPageList : List 23 | { 24 | } 25 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationPageTarget.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigationPageTarget 23 | { 24 | public string Id { get; set; } 25 | public string Value { get; set; } 26 | public EpubNavigationPageTargetType Type { get; set; } 27 | public string Class { get; set; } 28 | public string PlayOrder { get; set; } 29 | public List NavigationLabels { get; set; } 30 | public EpubNavigationContent Content { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationPageTargetType.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public enum EpubNavigationPageTargetType 21 | { 22 | FRONT = 1, 23 | NORMAL, 24 | SPECIAL 25 | } 26 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationPoint.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigationPoint 23 | { 24 | public string Id { get; set; } 25 | public string Class { get; set; } 26 | public string PlayOrder { get; set; } 27 | public List NavigationLabels { get; set; } 28 | public EpubNavigationContent Content { get; set; } 29 | public List ChildNavigationPoints { get; set; } 30 | 31 | public override string ToString() 32 | { 33 | return string.Format("Id: {0}, Content.Source: {1}", Id, Content.Source); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Navigation/EpubNavigationTarget.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubNavigationTarget 23 | { 24 | public string Id { get; set; } 25 | public string Class { get; set; } 26 | public string Value { get; set; } 27 | public string PlayOrder { get; set; } 28 | public List NavigationLabels { get; set; } 29 | public EpubNavigationContent Content { get; set; } 30 | } 31 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubGuide.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubGuide : List 23 | { 24 | } 25 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubGuideReference.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubGuideReference 21 | { 22 | public string Type { get; set; } 23 | public string Title { get; set; } 24 | public string Href { get; set; } 25 | 26 | public override string ToString() 27 | { 28 | return string.Format("Type: {0}, Href: {1}", Type, Href); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubManifest.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubManifest : List 23 | { 24 | } 25 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubManifestItem.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubManifestItem 21 | { 22 | public string Id { get; set; } 23 | public string Href { get; set; } 24 | public string MediaType { get; set; } 25 | public string RequiredNamespace { get; set; } 26 | public string RequiredModules { get; set; } 27 | public string Fallback { get; set; } 28 | public string FallbackStyle { get; set; } 29 | 30 | public override string ToString() 31 | { 32 | return string.Format("Id: {0}, Href = {1}, MediaType = {2}", Id, Href, MediaType); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubMetadata.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubMetadata 23 | { 24 | public List Titles { get; set; } 25 | public List Creators { get; set; } 26 | public List Subjects { get; set; } 27 | public string Description { get; set; } 28 | public List Publishers { get; set; } 29 | public List Contributors { get; set; } 30 | public List Dates { get; set; } 31 | public List Types { get; set; } 32 | public List Formats { get; set; } 33 | public List Identifiers { get; set; } 34 | public List Sources { get; set; } 35 | public List Languages { get; set; } 36 | public List Relations { get; set; } 37 | public List Coverages { get; set; } 38 | public List Rights { get; set; } 39 | public List MetaItems { get; set; } 40 | } 41 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubMetadataContributor.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubMetadataContributor 21 | { 22 | public string Contributor { get; set; } 23 | public string FileAs { get; set; } 24 | public string Role { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubMetadataCreator.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubMetadataCreator 21 | { 22 | public string Creator { get; set; } 23 | public string FileAs { get; set; } 24 | public string Role { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubMetadataDate.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubMetadataDate 21 | { 22 | public string Date { get; set; } 23 | public string Event { get; set; } 24 | } 25 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubMetadataIdentifier.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubMetadataIdentifier 21 | { 22 | public string Id { get; set; } 23 | public string Scheme { get; set; } 24 | public string Identifier { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubMetadataMeta.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubMetadataMeta 21 | { 22 | public string Name { get; set; } 23 | public string Content { get; set; } 24 | public string Id { get; set; } 25 | public string Refines { get; set; } 26 | public string Property { get; set; } 27 | public string Scheme { get; set; } 28 | } 29 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubPackage.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubPackage 21 | { 22 | public EpubVersion EpubVersion { get; set; } 23 | public EpubMetadata Metadata { get; set; } 24 | public EpubManifest Manifest { get; set; } 25 | public EpubSpine Spine { get; set; } 26 | public EpubGuide Guide { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubSpine.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.Collections.Generic; 19 | 20 | namespace VersOne.Epub.Schema 21 | { 22 | public class EpubSpine : List 23 | { 24 | public string Toc { get; set; } 25 | } 26 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubSpineItemRef.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public class EpubSpineItemRef 21 | { 22 | public string IdRef { get; set; } 23 | public bool IsLinear { get; set; } 24 | 25 | public override string ToString() 26 | { 27 | return string.Concat("IdRef: ", IdRef); 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /EpubReader/Schema/Opf/EpubVersion.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Schema 19 | { 20 | public enum EpubVersion 21 | { 22 | EPUB_2 = 2, 23 | EPUB_3 24 | } 25 | } -------------------------------------------------------------------------------- /EpubReader/Utils/XmlUtils.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | using System.IO; 19 | using System.Threading.Tasks; 20 | using System.Xml; 21 | using System.Xml.Linq; 22 | 23 | namespace VersOne.Epub.Internal 24 | { 25 | internal static class XmlUtils 26 | { 27 | public static async Task LoadDocumentAsync(Stream stream) 28 | { 29 | using (var memoryStream = new MemoryStream()) 30 | { 31 | await stream.CopyToAsync(memoryStream).ConfigureAwait(false); 32 | memoryStream.Position = 0; 33 | var xmlReaderSettings = new XmlReaderSettings 34 | { 35 | DtdProcessing = DtdProcessing.Ignore, 36 | Async = true 37 | }; 38 | using (var xmlReader = XmlReader.Create(memoryStream, xmlReaderSettings)) 39 | { 40 | return await Task.Run(() => XDocument.Load(memoryStream)).ConfigureAwait(false); 41 | } 42 | } 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /EpubReader/Utils/ZipPathUtils.cs: -------------------------------------------------------------------------------- 1 | // Copyright © 2018 Marco Gavelli and Paddy Xu 2 | // 3 | // This file is part of QuickLook program. 4 | // 5 | // This program is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // This program is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU General Public License 16 | // along with this program. If not, see . 17 | 18 | namespace VersOne.Epub.Internal 19 | { 20 | internal static class ZipPathUtils 21 | { 22 | public static string GetDirectoryPath(string filePath) 23 | { 24 | var lastSlashIndex = filePath.LastIndexOf('/'); 25 | if (lastSlashIndex == -1) 26 | return string.Empty; 27 | return filePath.Substring(0, lastSlashIndex); 28 | } 29 | 30 | public static string Combine(string directory, string fileName) 31 | { 32 | if (string.IsNullOrEmpty(directory)) 33 | return fileName; 34 | return string.Concat(directory, "/", fileName); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /EpubViewerControl.xaml: -------------------------------------------------------------------------------- 1 |  9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |