aboutsummaryrefslogtreecommitdiffstats
path: root/vendor
diff options
context:
space:
mode:
authorMario <mario@mariovavti.com>2024-11-09 10:24:26 +0000
committerMario <mario@mariovavti.com>2024-11-09 10:24:26 +0000
commit0ed08274f16d65b427bd4a5bbd8bd5bd6b2a65c2 (patch)
tree25b05973f824b95fc5705cf8aa79b86a44cfde00 /vendor
parent2a152e0803309eb3646316bbe0d2a47353bad2b9 (diff)
parent0534fe68869aae231259ee48a38b4533f3f1ff99 (diff)
downloadvolse-hubzilla-0ed08274f16d65b427bd4a5bbd8bd5bd6b2a65c2.tar.gz
volse-hubzilla-0ed08274f16d65b427bd4a5bbd8bd5bd6b2a65c2.tar.bz2
volse-hubzilla-0ed08274f16d65b427bd4a5bbd8bd5bd6b2a65c2.zip
Merge branch 'clean-up-some-dependencies' into 'dev'
Clean up deps and upgrade EpubMeta See merge request hubzilla/core!2162
Diffstat (limited to 'vendor')
-rw-r--r--vendor/composer/autoload_classmap.php49
-rw-r--r--vendor/composer/autoload_psr4.php1
-rw-r--r--vendor/composer/autoload_static.php54
-rw-r--r--vendor/composer/installed.json155
-rw-r--r--vendor/composer/installed.php30
-rw-r--r--vendor/composer/platform_check.php4
-rw-r--r--vendor/maennchen/zipstream-php/.editorconfig22
-rw-r--r--vendor/maennchen/zipstream-php/.gitattributes6
-rw-r--r--vendor/maennchen/zipstream-php/.github/CODE_OF_CONDUCT.md132
-rw-r--r--vendor/maennchen/zipstream-php/.github/CONTRIBUTING.md139
-rw-r--r--vendor/maennchen/zipstream-php/.github/FUNDING.yml1
-rw-r--r--vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/BUG.yml71
-rw-r--r--vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/FEATURE.yml11
-rw-r--r--vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE.md6
-rw-r--r--vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FAILING_TEST.md13
-rw-r--r--vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FIX.md13
-rw-r--r--vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/IMPROVEMENT.md9
-rw-r--r--vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/NEW_FEATURE.md9
-rw-r--r--vendor/maennchen/zipstream-php/.github/SECURITY.md22
-rw-r--r--vendor/maennchen/zipstream-php/.github/dependabot.yml13
-rw-r--r--vendor/maennchen/zipstream-php/.github/scorecard.yml14
-rw-r--r--vendor/maennchen/zipstream-php/.github/workflows/branch_main.yml24
-rw-r--r--vendor/maennchen/zipstream-php/.github/workflows/part_dependabot.yml30
-rw-r--r--vendor/maennchen/zipstream-php/.github/workflows/part_docs.yml51
-rw-r--r--vendor/maennchen/zipstream-php/.github/workflows/part_release.yml94
-rw-r--r--vendor/maennchen/zipstream-php/.github/workflows/part_test.yml183
-rw-r--r--vendor/maennchen/zipstream-php/.github/workflows/pr.yml50
-rw-r--r--vendor/maennchen/zipstream-php/.github/workflows/scorecard.yml78
-rw-r--r--vendor/maennchen/zipstream-php/.github/workflows/tag-beta.yml29
-rw-r--r--vendor/maennchen/zipstream-php/.github/workflows/tag-stable.yml55
-rw-r--r--vendor/maennchen/zipstream-php/.gitignore12
-rw-r--r--vendor/maennchen/zipstream-php/.phive/phars.xml4
-rw-r--r--vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php70
-rw-r--r--vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig15
-rw-r--r--vendor/maennchen/zipstream-php/.tool-versions1
-rw-r--r--vendor/maennchen/zipstream-php/LICENSE24
-rw-r--r--vendor/maennchen/zipstream-php/README.md154
-rw-r--r--vendor/maennchen/zipstream-php/composer.json88
-rw-r--r--vendor/maennchen/zipstream-php/guides/ContentLength.rst47
-rw-r--r--vendor/maennchen/zipstream-php/guides/FlySystem.rst34
-rw-r--r--vendor/maennchen/zipstream-php/guides/Nginx.rst16
-rw-r--r--vendor/maennchen/zipstream-php/guides/Options.rst66
-rw-r--r--vendor/maennchen/zipstream-php/guides/PSR7Streams.rst21
-rw-r--r--vendor/maennchen/zipstream-php/guides/StreamOutput.rst39
-rw-r--r--vendor/maennchen/zipstream-php/guides/Symfony.rst130
-rw-r--r--vendor/maennchen/zipstream-php/guides/Varnish.rst22
-rw-r--r--vendor/maennchen/zipstream-php/guides/index.rst126
-rw-r--r--vendor/maennchen/zipstream-php/phpdoc.dist.xml39
-rw-r--r--vendor/maennchen/zipstream-php/phpunit.xml.dist15
-rw-r--r--vendor/maennchen/zipstream-php/psalm.xml25
-rw-r--r--vendor/maennchen/zipstream-php/results.sarif1
-rw-r--r--vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php52
-rw-r--r--vendor/maennchen/zipstream-php/src/CompressionMethod.php106
-rw-r--r--vendor/maennchen/zipstream-php/src/DataDescriptor.php26
-rw-r--r--vendor/maennchen/zipstream-php/src/EndOfCentralDirectory.php35
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception.php7
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception/DosTimeOverflowException.php23
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception/FileNotFoundException.php22
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception/FileNotReadableException.php22
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception/FileSizeIncorrectException.php23
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception/OverflowException.php21
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception/ResourceActionException.php29
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php19
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php21
-rw-r--r--vendor/maennchen/zipstream-php/src/Exception/StreamNotSeekableException.php22
-rw-r--r--vendor/maennchen/zipstream-php/src/File.php420
-rw-r--r--vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php89
-rw-r--r--vendor/maennchen/zipstream-php/src/LocalFileHeader.php40
-rw-r--r--vendor/maennchen/zipstream-php/src/OperationMode.php35
-rw-r--r--vendor/maennchen/zipstream-php/src/PackField.php56
-rw-r--r--vendor/maennchen/zipstream-php/src/Time.php39
-rw-r--r--vendor/maennchen/zipstream-php/src/Version.php12
-rw-r--r--vendor/maennchen/zipstream-php/src/Zip64/DataDescriptor.php28
-rw-r--r--vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectory.php43
-rw-r--r--vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectoryLocator.php29
-rw-r--r--vendor/maennchen/zipstream-php/src/Zip64/ExtendedInformationExtraField.php45
-rw-r--r--vendor/maennchen/zipstream-php/src/ZipStream.php865
-rw-r--r--vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php23
-rw-r--r--vendor/maennchen/zipstream-php/test/Assertions.php49
-rw-r--r--vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php60
-rw-r--r--vendor/maennchen/zipstream-php/test/DataDescriptorTest.php26
-rw-r--r--vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php35
-rw-r--r--vendor/maennchen/zipstream-php/test/EndlessCycleStream.php104
-rw-r--r--vendor/maennchen/zipstream-php/test/FaultInjectionResource.php141
-rw-r--r--vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php47
-rw-r--r--vendor/maennchen/zipstream-php/test/PackFieldTest.php42
-rw-r--r--vendor/maennchen/zipstream-php/test/ResourceStream.php159
-rw-r--r--vendor/maennchen/zipstream-php/test/Tempfile.php42
-rw-r--r--vendor/maennchen/zipstream-php/test/TimeTest.php44
-rw-r--r--vendor/maennchen/zipstream-php/test/Util.php127
-rw-r--r--vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php28
-rw-r--r--vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php28
-rw-r--r--vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php41
-rw-r--r--vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php42
-rw-r--r--vendor/maennchen/zipstream-php/test/ZipStreamTest.php1195
-rw-r--r--vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php22
-rw-r--r--vendor/maennchen/zipstream-php/test/bootstrap.php7
-rw-r--r--vendor/mikespub/php-epub-meta/.gitignore8
-rw-r--r--vendor/mikespub/php-epub-meta/LICENSE21
-rw-r--r--vendor/mikespub/php-epub-meta/README.md54
-rw-r--r--vendor/mikespub/php-epub-meta/app/index.php23
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/cleditor/images/buttons.gifbin0 -> 3064 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/cleditor/images/toolbar.gifbin0 -> 68 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/cleditor/jquery.cleditor-1.4.5.css26
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.pngbin0 -> 180 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.pngbin0 -> 178 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.pngbin0 -> 429 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.pngbin0 -> 301 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_75_dadada_1x400.pngbin0 -> 359 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.pngbin0 -> 360 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.pngbin0 -> 426 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.pngbin0 -> 361 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_222222_256x240.pngbin0 -> 7061 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_2e83ff_256x240.pngbin0 -> 4654 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_454545_256x240.pngbin0 -> 7126 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_888888_256x240.pngbin0 -> 7147 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_cd0a0a_256x240.pngbin0 -> 4654 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/smoothness/jquery-ui-1.13.2.custom.min.css7
-rw-r--r--vendor/mikespub/php-epub-meta/assets/css/style.css180
-rw-r--r--vendor/mikespub/php-epub-meta/assets/js/jquery-3.7.1.min.js2
-rw-r--r--vendor/mikespub/php-epub-meta/assets/js/jquery-ui-1.13.2.custom.min.js6
-rw-r--r--vendor/mikespub/php-epub-meta/assets/js/jquery.cleditor-1.4.5.min.js11
-rw-r--r--vendor/mikespub/php-epub-meta/assets/js/script.js194
-rw-r--r--vendor/mikespub/php-epub-meta/composer.json46
-rw-r--r--vendor/mikespub/php-epub-meta/composer.lock1732
-rw-r--r--vendor/mikespub/php-epub-meta/package.json9
-rw-r--r--vendor/mikespub/php-epub-meta/phpstan-baseline.neon6
-rw-r--r--vendor/mikespub/php-epub-meta/phpstan.neon.dist14
-rw-r--r--vendor/mikespub/php-epub-meta/phpunit.xml26
-rw-r--r--vendor/mikespub/php-epub-meta/src/App/Handler.php236
-rw-r--r--vendor/mikespub/php-epub-meta/src/App/Util.php55
-rw-r--r--vendor/mikespub/php-epub-meta/src/Contents/Nav.php63
-rw-r--r--vendor/mikespub/php-epub-meta/src/Contents/NavPoint.php109
-rw-r--r--vendor/mikespub/php-epub-meta/src/Contents/NavPointList.php65
-rw-r--r--vendor/mikespub/php-epub-meta/src/Contents/Spine.php198
-rw-r--r--vendor/mikespub/php-epub-meta/src/Contents/Toc.php63
-rw-r--r--vendor/mikespub/php-epub-meta/src/Data/Item.php193
-rw-r--r--vendor/mikespub/php-epub-meta/src/Data/Manifest.php174
-rw-r--r--vendor/mikespub/php-epub-meta/src/Dom/Element.php196
-rw-r--r--vendor/mikespub/php-epub-meta/src/Dom/XPath.php32
-rw-r--r--vendor/mikespub/php-epub-meta/src/EPub.php2126
-rw-r--r--vendor/mikespub/php-epub-meta/src/Other.php121
-rw-r--r--vendor/mikespub/php-epub-meta/src/Tools/HtmlTools.php97
-rw-r--r--vendor/mikespub/php-epub-meta/src/Tools/ZipEdit.php450
-rw-r--r--vendor/mikespub/php-epub-meta/src/Tools/ZipFile.php343
-rw-r--r--vendor/mikespub/php-epub-meta/src/Tools/htmlBlockLevelElements.php42
-rw-r--r--vendor/mikespub/php-epub-meta/src/Tools/htmlEntityMap.php260
-rw-r--r--vendor/mikespub/php-epub-meta/templates/epub.html81
-rw-r--r--vendor/mikespub/php-epub-meta/templates/index.html35
-rw-r--r--vendor/mikespub/php-epub-meta/templates/titlepage.xhtml14
-rw-r--r--vendor/mikespub/php-epub-meta/test/.gitignore1
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/broken.zipbin0 -> 134 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/calibre_bookmarks.txt26
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/empty.zipbin0 -> 22 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/eng.components.json16
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/eng.contents.json96
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/eng.epubbin0 -> 22664 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/eng3.epubbin0 -> 53216 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/markup.1.xml41
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/markup.2.xml1175
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/markup.3.xml3
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/markup.4.xml5
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/markup.5.xml860
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/metadata.opf35
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/nav-non-text_img_title.epubbin0 -> 239564 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/test.epubbin0 -> 768780 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/test/data/test.jpgbin0 -> 821 bytes
-rw-r--r--vendor/mikespub/php-epub-meta/test/epubTest.php807
-rw-r--r--vendor/mikespub/php-epub-meta/test/monocleTest.php159
169 files changed, 17242 insertions, 8 deletions
diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php
index 69ec2d8ca..83e6cf08f 100644
--- a/vendor/composer/autoload_classmap.php
+++ b/vendor/composer/autoload_classmap.php
@@ -67,6 +67,7 @@ return array(
'HTMLPurifier_AttrDef_CSS_Multiple' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php',
'HTMLPurifier_AttrDef_CSS_Number' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php',
'HTMLPurifier_AttrDef_CSS_Percentage' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php',
+ 'HTMLPurifier_AttrDef_CSS_Ratio' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ratio.php',
'HTMLPurifier_AttrDef_CSS_TextDecoration' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php',
'HTMLPurifier_AttrDef_CSS_URI' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php',
'HTMLPurifier_AttrDef_Clone' => $vendorDir . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php',
@@ -395,6 +396,7 @@ return array(
'OTPHP\\FactoryInterface' => $vendorDir . '/spomky-labs/otphp/src/FactoryInterface.php',
'OTPHP\\HOTP' => $vendorDir . '/spomky-labs/otphp/src/HOTP.php',
'OTPHP\\HOTPInterface' => $vendorDir . '/spomky-labs/otphp/src/HOTPInterface.php',
+ 'OTPHP\\InternalClock' => $vendorDir . '/spomky-labs/otphp/src/InternalClock.php',
'OTPHP\\OTP' => $vendorDir . '/spomky-labs/otphp/src/OTP.php',
'OTPHP\\OTPInterface' => $vendorDir . '/spomky-labs/otphp/src/OTPInterface.php',
'OTPHP\\ParameterTrait' => $vendorDir . '/spomky-labs/otphp/src/ParameterTrait.php',
@@ -428,8 +430,10 @@ return array(
'Ramsey\\Collection\\CollectionInterface' => $vendorDir . '/ramsey/collection/src/CollectionInterface.php',
'Ramsey\\Collection\\DoubleEndedQueue' => $vendorDir . '/ramsey/collection/src/DoubleEndedQueue.php',
'Ramsey\\Collection\\DoubleEndedQueueInterface' => $vendorDir . '/ramsey/collection/src/DoubleEndedQueueInterface.php',
+ 'Ramsey\\Collection\\Exception\\CollectionException' => $vendorDir . '/ramsey/collection/src/Exception/CollectionException.php',
'Ramsey\\Collection\\Exception\\CollectionMismatchException' => $vendorDir . '/ramsey/collection/src/Exception/CollectionMismatchException.php',
'Ramsey\\Collection\\Exception\\InvalidArgumentException' => $vendorDir . '/ramsey/collection/src/Exception/InvalidArgumentException.php',
+ 'Ramsey\\Collection\\Exception\\InvalidPropertyOrMethod' => $vendorDir . '/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php',
'Ramsey\\Collection\\Exception\\InvalidSortOrderException' => $vendorDir . '/ramsey/collection/src/Exception/InvalidSortOrderException.php',
'Ramsey\\Collection\\Exception\\NoSuchElementException' => $vendorDir . '/ramsey/collection/src/Exception/NoSuchElementException.php',
'Ramsey\\Collection\\Exception\\OutOfBoundsException' => $vendorDir . '/ramsey/collection/src/Exception/OutOfBoundsException.php',
@@ -446,6 +450,7 @@ return array(
'Ramsey\\Collection\\Queue' => $vendorDir . '/ramsey/collection/src/Queue.php',
'Ramsey\\Collection\\QueueInterface' => $vendorDir . '/ramsey/collection/src/QueueInterface.php',
'Ramsey\\Collection\\Set' => $vendorDir . '/ramsey/collection/src/Set.php',
+ 'Ramsey\\Collection\\Sort' => $vendorDir . '/ramsey/collection/src/Sort.php',
'Ramsey\\Collection\\Tool\\TypeTrait' => $vendorDir . '/ramsey/collection/src/Tool/TypeTrait.php',
'Ramsey\\Collection\\Tool\\ValueExtractorTrait' => $vendorDir . '/ramsey/collection/src/Tool/ValueExtractorTrait.php',
'Ramsey\\Collection\\Tool\\ValueToStringTrait' => $vendorDir . '/ramsey/collection/src/Tool/ValueToStringTrait.php',
@@ -964,6 +969,22 @@ return array(
'ScssPhp\\ScssPhp\\ValueConverter' => $vendorDir . '/scssphp/scssphp/src/ValueConverter.php',
'ScssPhp\\ScssPhp\\Version' => $vendorDir . '/scssphp/scssphp/src/Version.php',
'ScssPhp\\ScssPhp\\Warn' => $vendorDir . '/scssphp/scssphp/src/Warn.php',
+ 'SebLucas\\EPubMeta\\App\\Handler' => $vendorDir . '/mikespub/php-epub-meta/src/App/Handler.php',
+ 'SebLucas\\EPubMeta\\App\\Util' => $vendorDir . '/mikespub/php-epub-meta/src/App/Util.php',
+ 'SebLucas\\EPubMeta\\Contents\\Nav' => $vendorDir . '/mikespub/php-epub-meta/src/Contents/Nav.php',
+ 'SebLucas\\EPubMeta\\Contents\\NavPoint' => $vendorDir . '/mikespub/php-epub-meta/src/Contents/NavPoint.php',
+ 'SebLucas\\EPubMeta\\Contents\\NavPointList' => $vendorDir . '/mikespub/php-epub-meta/src/Contents/NavPointList.php',
+ 'SebLucas\\EPubMeta\\Contents\\Spine' => $vendorDir . '/mikespub/php-epub-meta/src/Contents/Spine.php',
+ 'SebLucas\\EPubMeta\\Contents\\Toc' => $vendorDir . '/mikespub/php-epub-meta/src/Contents/Toc.php',
+ 'SebLucas\\EPubMeta\\Data\\Item' => $vendorDir . '/mikespub/php-epub-meta/src/Data/Item.php',
+ 'SebLucas\\EPubMeta\\Data\\Manifest' => $vendorDir . '/mikespub/php-epub-meta/src/Data/Manifest.php',
+ 'SebLucas\\EPubMeta\\Dom\\Element' => $vendorDir . '/mikespub/php-epub-meta/src/Dom/Element.php',
+ 'SebLucas\\EPubMeta\\Dom\\XPath' => $vendorDir . '/mikespub/php-epub-meta/src/Dom/XPath.php',
+ 'SebLucas\\EPubMeta\\EPub' => $vendorDir . '/mikespub/php-epub-meta/src/EPub.php',
+ 'SebLucas\\EPubMeta\\Other' => $vendorDir . '/mikespub/php-epub-meta/src/Other.php',
+ 'SebLucas\\EPubMeta\\Tools\\HtmlTools' => $vendorDir . '/mikespub/php-epub-meta/src/Tools/HtmlTools.php',
+ 'SebLucas\\EPubMeta\\Tools\\ZipEdit' => $vendorDir . '/mikespub/php-epub-meta/src/Tools/ZipEdit.php',
+ 'SebLucas\\EPubMeta\\Tools\\ZipFile' => $vendorDir . '/mikespub/php-epub-meta/src/Tools/ZipFile.php',
'SimplePie' => $vendorDir . '/simplepie/simplepie/library/SimplePie.php',
'SimplePie\\Author' => $vendorDir . '/simplepie/simplepie/src/Author.php',
'SimplePie\\Cache' => $vendorDir . '/simplepie/simplepie/src/Cache.php',
@@ -1222,6 +1243,33 @@ return array(
'Text_LanguageDetect_Parser' => $vendorDir . '/pear/text_languagedetect/Text/LanguageDetect/Parser.php',
'URLify' => $vendorDir . '/jbroadway/urlify/URLify.php',
'UploadHandler' => $vendorDir . '/blueimp/jquery-file-upload/server/php/UploadHandler.php',
+ 'ZipStream\\CentralDirectoryFileHeader' => $vendorDir . '/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php',
+ 'ZipStream\\CompressionMethod' => $vendorDir . '/maennchen/zipstream-php/src/CompressionMethod.php',
+ 'ZipStream\\DataDescriptor' => $vendorDir . '/maennchen/zipstream-php/src/DataDescriptor.php',
+ 'ZipStream\\EndOfCentralDirectory' => $vendorDir . '/maennchen/zipstream-php/src/EndOfCentralDirectory.php',
+ 'ZipStream\\Exception' => $vendorDir . '/maennchen/zipstream-php/src/Exception.php',
+ 'ZipStream\\Exception\\DosTimeOverflowException' => $vendorDir . '/maennchen/zipstream-php/src/Exception/DosTimeOverflowException.php',
+ 'ZipStream\\Exception\\FileNotFoundException' => $vendorDir . '/maennchen/zipstream-php/src/Exception/FileNotFoundException.php',
+ 'ZipStream\\Exception\\FileNotReadableException' => $vendorDir . '/maennchen/zipstream-php/src/Exception/FileNotReadableException.php',
+ 'ZipStream\\Exception\\FileSizeIncorrectException' => $vendorDir . '/maennchen/zipstream-php/src/Exception/FileSizeIncorrectException.php',
+ 'ZipStream\\Exception\\OverflowException' => $vendorDir . '/maennchen/zipstream-php/src/Exception/OverflowException.php',
+ 'ZipStream\\Exception\\ResourceActionException' => $vendorDir . '/maennchen/zipstream-php/src/Exception/ResourceActionException.php',
+ 'ZipStream\\Exception\\SimulationFileUnknownException' => $vendorDir . '/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php',
+ 'ZipStream\\Exception\\StreamNotReadableException' => $vendorDir . '/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php',
+ 'ZipStream\\Exception\\StreamNotSeekableException' => $vendorDir . '/maennchen/zipstream-php/src/Exception/StreamNotSeekableException.php',
+ 'ZipStream\\File' => $vendorDir . '/maennchen/zipstream-php/src/File.php',
+ 'ZipStream\\GeneralPurposeBitFlag' => $vendorDir . '/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php',
+ 'ZipStream\\LocalFileHeader' => $vendorDir . '/maennchen/zipstream-php/src/LocalFileHeader.php',
+ 'ZipStream\\OperationMode' => $vendorDir . '/maennchen/zipstream-php/src/OperationMode.php',
+ 'ZipStream\\PackField' => $vendorDir . '/maennchen/zipstream-php/src/PackField.php',
+ 'ZipStream\\Time' => $vendorDir . '/maennchen/zipstream-php/src/Time.php',
+ 'ZipStream\\Version' => $vendorDir . '/maennchen/zipstream-php/src/Version.php',
+ 'ZipStream\\Zip64\\DataDescriptor' => $vendorDir . '/maennchen/zipstream-php/src/Zip64/DataDescriptor.php',
+ 'ZipStream\\Zip64\\EndOfCentralDirectory' => $vendorDir . '/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectory.php',
+ 'ZipStream\\Zip64\\EndOfCentralDirectoryLocator' => $vendorDir . '/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectoryLocator.php',
+ 'ZipStream\\Zip64\\ExtendedInformationExtraField' => $vendorDir . '/maennchen/zipstream-php/src/Zip64/ExtendedInformationExtraField.php',
+ 'ZipStream\\ZipStream' => $vendorDir . '/maennchen/zipstream-php/src/ZipStream.php',
+ 'ZipStream\\Zs\\ExtendedInformationExtraField' => $vendorDir . '/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php',
'Zotlabs\\Access\\AccessList' => $baseDir . '/Zotlabs/Access/AccessList.php',
'Zotlabs\\Access\\PermissionLimits' => $baseDir . '/Zotlabs/Access/PermissionLimits.php',
'Zotlabs\\Access\\PermissionRoles' => $baseDir . '/Zotlabs/Access/PermissionRoles.php',
@@ -1551,7 +1599,6 @@ return array(
'Zotlabs\\Storage\\CalDAVClient' => $baseDir . '/Zotlabs/Storage/CalDAVClient.php',
'Zotlabs\\Storage\\Directory' => $baseDir . '/Zotlabs/Storage/Directory.php',
'Zotlabs\\Storage\\File' => $baseDir . '/Zotlabs/Storage/File.php',
- 'Zotlabs\\Storage\\GitRepo' => $baseDir . '/Zotlabs/Storage/GitRepo.php',
'Zotlabs\\Storage\\ZotOauth2Pdo' => $baseDir . '/Zotlabs/Storage/ZotOauth2Pdo.php',
'Zotlabs\\Text\\Tagadelic' => $baseDir . '/Zotlabs/Text/Tagadelic.php',
'Zotlabs\\Thumbs\\Epubthumb' => $baseDir . '/Zotlabs/Thumbs/Epubthumb.php',
diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php
index c2a27512d..9d4145d4c 100644
--- a/vendor/composer/autoload_psr4.php
+++ b/vendor/composer/autoload_psr4.php
@@ -11,6 +11,7 @@ return array(
'chillerlan\\Settings\\' => array($vendorDir . '/chillerlan/php-settings-container/src'),
'chillerlan\\QRCode\\' => array($vendorDir . '/chillerlan/php-qrcode/src'),
'Zotlabs\\' => array($baseDir . '/Zotlabs'),
+ 'ZipStream\\' => array($vendorDir . '/maennchen/zipstream-php/src'),
'Symfony\\Polyfill\\Php81\\' => array($vendorDir . '/symfony/polyfill-php81'),
'StephenHill\\Benchmarks\\' => array($vendorDir . '/stephenhill/base58/benchmarks'),
'StephenHill\\' => array($vendorDir . '/stephenhill/base58/src'),
diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php
index 1b958f6a8..23071b7c7 100644
--- a/vendor/composer/autoload_static.php
+++ b/vendor/composer/autoload_static.php
@@ -37,6 +37,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Z' =>
array (
'Zotlabs\\' => 8,
+ 'ZipStream\\' => 10,
),
'S' =>
array (
@@ -116,6 +117,10 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
array (
0 => __DIR__ . '/../..' . '/Zotlabs',
),
+ 'ZipStream\\' =>
+ array (
+ 0 => __DIR__ . '/..' . '/maennchen/zipstream-php/src',
+ ),
'Symfony\\Polyfill\\Php81\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php81',
@@ -314,6 +319,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'HTMLPurifier_AttrDef_CSS_Multiple' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Multiple.php',
'HTMLPurifier_AttrDef_CSS_Number' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Number.php',
'HTMLPurifier_AttrDef_CSS_Percentage' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Percentage.php',
+ 'HTMLPurifier_AttrDef_CSS_Ratio' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/Ratio.php',
'HTMLPurifier_AttrDef_CSS_TextDecoration' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/TextDecoration.php',
'HTMLPurifier_AttrDef_CSS_URI' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/CSS/URI.php',
'HTMLPurifier_AttrDef_Clone' => __DIR__ . '/..' . '/ezyang/htmlpurifier/library/HTMLPurifier/AttrDef/Clone.php',
@@ -642,6 +648,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'OTPHP\\FactoryInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/FactoryInterface.php',
'OTPHP\\HOTP' => __DIR__ . '/..' . '/spomky-labs/otphp/src/HOTP.php',
'OTPHP\\HOTPInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/HOTPInterface.php',
+ 'OTPHP\\InternalClock' => __DIR__ . '/..' . '/spomky-labs/otphp/src/InternalClock.php',
'OTPHP\\OTP' => __DIR__ . '/..' . '/spomky-labs/otphp/src/OTP.php',
'OTPHP\\OTPInterface' => __DIR__ . '/..' . '/spomky-labs/otphp/src/OTPInterface.php',
'OTPHP\\ParameterTrait' => __DIR__ . '/..' . '/spomky-labs/otphp/src/ParameterTrait.php',
@@ -675,8 +682,10 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Ramsey\\Collection\\CollectionInterface' => __DIR__ . '/..' . '/ramsey/collection/src/CollectionInterface.php',
'Ramsey\\Collection\\DoubleEndedQueue' => __DIR__ . '/..' . '/ramsey/collection/src/DoubleEndedQueue.php',
'Ramsey\\Collection\\DoubleEndedQueueInterface' => __DIR__ . '/..' . '/ramsey/collection/src/DoubleEndedQueueInterface.php',
+ 'Ramsey\\Collection\\Exception\\CollectionException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/CollectionException.php',
'Ramsey\\Collection\\Exception\\CollectionMismatchException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/CollectionMismatchException.php',
'Ramsey\\Collection\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/InvalidArgumentException.php',
+ 'Ramsey\\Collection\\Exception\\InvalidPropertyOrMethod' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/InvalidPropertyOrMethod.php',
'Ramsey\\Collection\\Exception\\InvalidSortOrderException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/InvalidSortOrderException.php',
'Ramsey\\Collection\\Exception\\NoSuchElementException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/NoSuchElementException.php',
'Ramsey\\Collection\\Exception\\OutOfBoundsException' => __DIR__ . '/..' . '/ramsey/collection/src/Exception/OutOfBoundsException.php',
@@ -693,6 +702,7 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Ramsey\\Collection\\Queue' => __DIR__ . '/..' . '/ramsey/collection/src/Queue.php',
'Ramsey\\Collection\\QueueInterface' => __DIR__ . '/..' . '/ramsey/collection/src/QueueInterface.php',
'Ramsey\\Collection\\Set' => __DIR__ . '/..' . '/ramsey/collection/src/Set.php',
+ 'Ramsey\\Collection\\Sort' => __DIR__ . '/..' . '/ramsey/collection/src/Sort.php',
'Ramsey\\Collection\\Tool\\TypeTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/TypeTrait.php',
'Ramsey\\Collection\\Tool\\ValueExtractorTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/ValueExtractorTrait.php',
'Ramsey\\Collection\\Tool\\ValueToStringTrait' => __DIR__ . '/..' . '/ramsey/collection/src/Tool/ValueToStringTrait.php',
@@ -1211,6 +1221,22 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'ScssPhp\\ScssPhp\\ValueConverter' => __DIR__ . '/..' . '/scssphp/scssphp/src/ValueConverter.php',
'ScssPhp\\ScssPhp\\Version' => __DIR__ . '/..' . '/scssphp/scssphp/src/Version.php',
'ScssPhp\\ScssPhp\\Warn' => __DIR__ . '/..' . '/scssphp/scssphp/src/Warn.php',
+ 'SebLucas\\EPubMeta\\App\\Handler' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/App/Handler.php',
+ 'SebLucas\\EPubMeta\\App\\Util' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/App/Util.php',
+ 'SebLucas\\EPubMeta\\Contents\\Nav' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Contents/Nav.php',
+ 'SebLucas\\EPubMeta\\Contents\\NavPoint' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Contents/NavPoint.php',
+ 'SebLucas\\EPubMeta\\Contents\\NavPointList' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Contents/NavPointList.php',
+ 'SebLucas\\EPubMeta\\Contents\\Spine' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Contents/Spine.php',
+ 'SebLucas\\EPubMeta\\Contents\\Toc' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Contents/Toc.php',
+ 'SebLucas\\EPubMeta\\Data\\Item' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Data/Item.php',
+ 'SebLucas\\EPubMeta\\Data\\Manifest' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Data/Manifest.php',
+ 'SebLucas\\EPubMeta\\Dom\\Element' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Dom/Element.php',
+ 'SebLucas\\EPubMeta\\Dom\\XPath' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Dom/XPath.php',
+ 'SebLucas\\EPubMeta\\EPub' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/EPub.php',
+ 'SebLucas\\EPubMeta\\Other' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Other.php',
+ 'SebLucas\\EPubMeta\\Tools\\HtmlTools' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Tools/HtmlTools.php',
+ 'SebLucas\\EPubMeta\\Tools\\ZipEdit' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Tools/ZipEdit.php',
+ 'SebLucas\\EPubMeta\\Tools\\ZipFile' => __DIR__ . '/..' . '/mikespub/php-epub-meta/src/Tools/ZipFile.php',
'SimplePie' => __DIR__ . '/..' . '/simplepie/simplepie/library/SimplePie.php',
'SimplePie\\Author' => __DIR__ . '/..' . '/simplepie/simplepie/src/Author.php',
'SimplePie\\Cache' => __DIR__ . '/..' . '/simplepie/simplepie/src/Cache.php',
@@ -1469,6 +1495,33 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Text_LanguageDetect_Parser' => __DIR__ . '/..' . '/pear/text_languagedetect/Text/LanguageDetect/Parser.php',
'URLify' => __DIR__ . '/..' . '/jbroadway/urlify/URLify.php',
'UploadHandler' => __DIR__ . '/..' . '/blueimp/jquery-file-upload/server/php/UploadHandler.php',
+ 'ZipStream\\CentralDirectoryFileHeader' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php',
+ 'ZipStream\\CompressionMethod' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/CompressionMethod.php',
+ 'ZipStream\\DataDescriptor' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/DataDescriptor.php',
+ 'ZipStream\\EndOfCentralDirectory' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/EndOfCentralDirectory.php',
+ 'ZipStream\\Exception' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception.php',
+ 'ZipStream\\Exception\\DosTimeOverflowException' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception/DosTimeOverflowException.php',
+ 'ZipStream\\Exception\\FileNotFoundException' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception/FileNotFoundException.php',
+ 'ZipStream\\Exception\\FileNotReadableException' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception/FileNotReadableException.php',
+ 'ZipStream\\Exception\\FileSizeIncorrectException' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception/FileSizeIncorrectException.php',
+ 'ZipStream\\Exception\\OverflowException' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception/OverflowException.php',
+ 'ZipStream\\Exception\\ResourceActionException' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception/ResourceActionException.php',
+ 'ZipStream\\Exception\\SimulationFileUnknownException' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php',
+ 'ZipStream\\Exception\\StreamNotReadableException' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php',
+ 'ZipStream\\Exception\\StreamNotSeekableException' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Exception/StreamNotSeekableException.php',
+ 'ZipStream\\File' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/File.php',
+ 'ZipStream\\GeneralPurposeBitFlag' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php',
+ 'ZipStream\\LocalFileHeader' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/LocalFileHeader.php',
+ 'ZipStream\\OperationMode' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/OperationMode.php',
+ 'ZipStream\\PackField' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/PackField.php',
+ 'ZipStream\\Time' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Time.php',
+ 'ZipStream\\Version' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Version.php',
+ 'ZipStream\\Zip64\\DataDescriptor' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Zip64/DataDescriptor.php',
+ 'ZipStream\\Zip64\\EndOfCentralDirectory' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectory.php',
+ 'ZipStream\\Zip64\\EndOfCentralDirectoryLocator' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectoryLocator.php',
+ 'ZipStream\\Zip64\\ExtendedInformationExtraField' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Zip64/ExtendedInformationExtraField.php',
+ 'ZipStream\\ZipStream' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/ZipStream.php',
+ 'ZipStream\\Zs\\ExtendedInformationExtraField' => __DIR__ . '/..' . '/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php',
'Zotlabs\\Access\\AccessList' => __DIR__ . '/../..' . '/Zotlabs/Access/AccessList.php',
'Zotlabs\\Access\\PermissionLimits' => __DIR__ . '/../..' . '/Zotlabs/Access/PermissionLimits.php',
'Zotlabs\\Access\\PermissionRoles' => __DIR__ . '/../..' . '/Zotlabs/Access/PermissionRoles.php',
@@ -1798,7 +1851,6 @@ class ComposerStaticInit7b34d7e50a62201ec5d5e526a5b8b35d
'Zotlabs\\Storage\\CalDAVClient' => __DIR__ . '/../..' . '/Zotlabs/Storage/CalDAVClient.php',
'Zotlabs\\Storage\\Directory' => __DIR__ . '/../..' . '/Zotlabs/Storage/Directory.php',
'Zotlabs\\Storage\\File' => __DIR__ . '/../..' . '/Zotlabs/Storage/File.php',
- 'Zotlabs\\Storage\\GitRepo' => __DIR__ . '/../..' . '/Zotlabs/Storage/GitRepo.php',
'Zotlabs\\Storage\\ZotOauth2Pdo' => __DIR__ . '/../..' . '/Zotlabs/Storage/ZotOauth2Pdo.php',
'Zotlabs\\Text\\Tagadelic' => __DIR__ . '/../..' . '/Zotlabs/Text/Tagadelic.php',
'Zotlabs\\Thumbs\\Epubthumb' => __DIR__ . '/../..' . '/Zotlabs/Thumbs/Epubthumb.php',
diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json
index abbf62c86..93684f1e8 100644
--- a/vendor/composer/installed.json
+++ b/vendor/composer/installed.json
@@ -705,6 +705,86 @@
"install-path": "../lukasreschke/id3parser"
},
{
+ "name": "maennchen/zipstream-php",
+ "version": "3.1.1",
+ "version_normalized": "3.1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/maennchen/ZipStream-PHP.git",
+ "reference": "6187e9cc4493da94b9b63eb2315821552015fca9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/6187e9cc4493da94b9b63eb2315821552015fca9",
+ "reference": "6187e9cc4493da94b9b63eb2315821552015fca9",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "ext-zlib": "*",
+ "php-64bit": "^8.1"
+ },
+ "require-dev": {
+ "ext-zip": "*",
+ "friendsofphp/php-cs-fixer": "^3.16",
+ "guzzlehttp/guzzle": "^7.5",
+ "mikey179/vfsstream": "^1.6",
+ "php-coveralls/php-coveralls": "^2.5",
+ "phpunit/phpunit": "^10.0",
+ "vimeo/psalm": "^5.0"
+ },
+ "suggest": {
+ "guzzlehttp/psr7": "^2.4",
+ "psr/http-message": "^2.0"
+ },
+ "time": "2024-10-10T12:33:01+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "psr-4": {
+ "ZipStream\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paul Duncan",
+ "email": "pabs@pablotron.org"
+ },
+ {
+ "name": "Jonatan Männchen",
+ "email": "jonatan@maennchen.ch"
+ },
+ {
+ "name": "Jesse Donat",
+ "email": "donatj@gmail.com"
+ },
+ {
+ "name": "András Kolesár",
+ "email": "kolesar@kolesar.hu"
+ }
+ ],
+ "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
+ "keywords": [
+ "stream",
+ "zip"
+ ],
+ "support": {
+ "issues": "https://github.com/maennchen/ZipStream-PHP/issues",
+ "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/maennchen",
+ "type": "github"
+ }
+ ],
+ "install-path": "../maennchen/zipstream-php"
+ },
+ {
"name": "michelf/php-markdown",
"version": "2.0.0",
"version_normalized": "2.0.0.0",
@@ -764,6 +844,81 @@
"install-path": "../michelf/php-markdown"
},
{
+ "name": "mikespub/php-epub-meta",
+ "version": "2.3.1",
+ "version_normalized": "2.3.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/mikespub-org/php-epub-meta.git",
+ "reference": "55072c507da19861bc80c26762a13a3aa4574566"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/mikespub-org/php-epub-meta/zipball/55072c507da19861bc80c26762a13a3aa4574566",
+ "reference": "55072c507da19861bc80c26762a13a3aa4574566",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-zip": "*",
+ "ext-zlib": "*",
+ "maennchen/zipstream-php": "^3.1",
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.5"
+ },
+ "suggest": {
+ "mikespub/epub-loader": "epub-loader is a utility resource for ebooks",
+ "mikespub/seblucas-cops": "COPS - Calibre OPDS (and HTML) PHP Server"
+ },
+ "time": "2024-08-21T16:21:54+00:00",
+ "type": "library",
+ "installation-source": "dist",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Andreas Gohr",
+ "email": "andi@splitbrain.org",
+ "homepage": "https://www.splitbrain.org/",
+ "role": "Developer"
+ },
+ {
+ "name": "Sébastien Lucas",
+ "email": "sebastien@slucas.fr",
+ "homepage": "http://www.slucas.fr/",
+ "role": "Developer"
+ },
+ {
+ "name": "mikespub",
+ "homepage": "https://github.com/mikespub-org/php-epub-meta",
+ "role": "Developer"
+ }
+ ],
+ "description": "Reading and writing metadata included in the EPub ebook format",
+ "homepage": "https://github.com/mikespub-org/php-epub-meta",
+ "keywords": [
+ "ebook",
+ "epub",
+ "metadata"
+ ],
+ "support": {
+ "issues": "https://github.com/mikespub-org/php-epub-meta/issues",
+ "source": "https://github.com/mikespub-org/php-epub-meta/tree/2.3.1"
+ },
+ "install-path": "../mikespub/php-epub-meta"
+ },
+ {
"name": "mmccook/php-json-canonicalization-scheme",
"version": "1.0.0",
"version_normalized": "1.0.0.0",
diff --git a/vendor/composer/installed.php b/vendor/composer/installed.php
index 7de5f28cd..b0a11c37d 100644
--- a/vendor/composer/installed.php
+++ b/vendor/composer/installed.php
@@ -1,9 +1,9 @@
<?php return array(
'root' => array(
'name' => 'zotlabs/hubzilla',
- 'pretty_version' => 'dev-master',
- 'version' => 'dev-master',
- 'reference' => 'becd4c6ffd3138731e528acdf6842fe53f381f6a',
+ 'pretty_version' => '1.0.0+no-version-set',
+ 'version' => '1.0.0.0',
+ 'reference' => null,
'type' => 'application',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
@@ -109,6 +109,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
+ 'maennchen/zipstream-php' => array(
+ 'pretty_version' => '3.1.1',
+ 'version' => '3.1.1.0',
+ 'reference' => '6187e9cc4493da94b9b63eb2315821552015fca9',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../maennchen/zipstream-php',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
'michelf/php-markdown' => array(
'pretty_version' => '2.0.0',
'version' => '2.0.0.0',
@@ -118,6 +127,15 @@
'aliases' => array(),
'dev_requirement' => false,
),
+ 'mikespub/php-epub-meta' => array(
+ 'pretty_version' => '2.3.1',
+ 'version' => '2.3.1.0',
+ 'reference' => '55072c507da19861bc80c26762a13a3aa4574566',
+ 'type' => 'library',
+ 'install_path' => __DIR__ . '/../mikespub/php-epub-meta',
+ 'aliases' => array(),
+ 'dev_requirement' => false,
+ ),
'mmccook/php-json-canonicalization-scheme' => array(
'pretty_version' => '1.0.0',
'version' => '1.0.0.0',
@@ -347,9 +365,9 @@
'dev_requirement' => false,
),
'zotlabs/hubzilla' => array(
- 'pretty_version' => 'dev-master',
- 'version' => 'dev-master',
- 'reference' => 'becd4c6ffd3138731e528acdf6842fe53f381f6a',
+ 'pretty_version' => '1.0.0+no-version-set',
+ 'version' => '1.0.0.0',
+ 'reference' => null,
'type' => 'application',
'install_path' => __DIR__ . '/../../',
'aliases' => array(),
diff --git a/vendor/composer/platform_check.php b/vendor/composer/platform_check.php
index 4c3a5d68f..f71b2f899 100644
--- a/vendor/composer/platform_check.php
+++ b/vendor/composer/platform_check.php
@@ -8,6 +8,10 @@ if (!(PHP_VERSION_ID >= 80100)) {
$issues[] = 'Your Composer dependencies require a PHP version ">= 8.1.0". You are running ' . PHP_VERSION . '.';
}
+if (PHP_INT_SIZE !== 8) {
+ $issues[] = 'Your Composer dependencies require a 64-bit build of PHP.';
+}
+
if ($issues) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
diff --git a/vendor/maennchen/zipstream-php/.editorconfig b/vendor/maennchen/zipstream-php/.editorconfig
new file mode 100644
index 000000000..f7cd91427
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.editorconfig
@@ -0,0 +1,22 @@
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+charset = utf-8
+
+[*.{yml,md,xml}]
+indent_style = space
+indent_size = 2
+
+[*.{rst,php}]
+indent_style = space
+indent_size = 4
+
+[composer.json]
+indent_style = space
+indent_size = 2
+
+[composer.lock]
+indent_style = space
+indent_size = 4
diff --git a/vendor/maennchen/zipstream-php/.gitattributes b/vendor/maennchen/zipstream-php/.gitattributes
new file mode 100644
index 000000000..e058ebd0a
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.gitattributes
@@ -0,0 +1,6 @@
+.gitignore text eol=lf
+.gitattributes text eol=lf
+*.md text eol=lf
+*.php text eol=lf
+*.yml text eol=lf
+*.xml text eol=lf
diff --git a/vendor/maennchen/zipstream-php/.github/CODE_OF_CONDUCT.md b/vendor/maennchen/zipstream-php/.github/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..9d75b8763
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/CODE_OF_CONDUCT.md
@@ -0,0 +1,132 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, caste, color, religion, or sexual
+identity and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+- Demonstrating empathy and kindness toward other people
+- Being respectful of differing opinions, viewpoints, and experiences
+- Giving and gracefully accepting constructive feedback
+- Accepting responsibility and apologizing to those affected by our mistakes,
+ and learning from the experience
+- Focusing on what is best not just for us as individuals, but for the overall
+ community
+
+Examples of unacceptable behavior include:
+
+- The use of sexualized language or imagery, and sexual attention or advances of
+ any kind
+- Trolling, insulting or derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or email address,
+ without their explicit permission
+- Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+jonatan@maennchen.ch.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series of
+actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or permanent
+ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior, harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within the
+community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.1, available at
+[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
+
+Community Impact Guidelines were inspired by
+[Mozilla's code of conduct enforcement ladder][mozilla coc].
+
+For answers to common questions about this code of conduct, see the FAQ at
+[https://www.contributor-covenant.org/faq][faq]. Translations are available at
+[https://www.contributor-covenant.org/translations][translations].
+
+[homepage]: https://www.contributor-covenant.org
+[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
+[mozilla coc]: https://github.com/mozilla/diversity
+[faq]: https://www.contributor-covenant.org/faq
+[translations]: https://www.contributor-covenant.org/translations
diff --git a/vendor/maennchen/zipstream-php/.github/CONTRIBUTING.md b/vendor/maennchen/zipstream-php/.github/CONTRIBUTING.md
new file mode 100644
index 000000000..d8caee081
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/CONTRIBUTING.md
@@ -0,0 +1,139 @@
+# Contributing to ZipStream-PHP
+
+## Welcome!
+
+We look forward to your contributions! Here are some examples how you can
+contribute:
+
+- [Report a bug](https://github.com/maennchen/ZipStream-PHP/issues/new?labels=bug&template=BUG.md)
+- [Propose a new feature](https://github.com/maennchen/ZipStream-PHP/issues/new?labels=enhancement&template=FEATURE.md)
+- [Send a pull request](https://github.com/maennchen/ZipStream-PHP/pulls)
+
+## We have a Code of Conduct
+
+Please note that this project is released with a
+[Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this
+project you agree to abide by its terms.
+
+## Any contributions you make will be under the MIT License
+
+When you submit code changes, your submissions are understood to be under the
+same [MIT License](https://github.com/maennchen/ZipStream-PHP/blob/main/LICENSE)
+that covers the project. By contributing to this project, you agree that your
+contributions will be licensed under its MIT License.
+
+## Write bug reports with detail, background, and sample code
+
+In your bug report, please provide the following:
+
+- A quick summary and/or background
+- Steps to reproduce
+ - Be specific!
+ - Give sample code if you can.
+- What you expected would happen
+- What actually happens
+- Notes (possibly including why you think this might be happening, or stuff you
+- tried that didn't work)
+
+Please do not report a bug for a version of ZIPStream-PHP that is no longer
+supported (`< 3.0.0`). Please do not report a bug if you are using a version of
+PHP that is not supported by the version of ZipStream-PHP you are using.
+
+Please post code and output as text
+([using proper markup](https://guides.github.com/features/mastering-markdown/)).
+Do not post screenshots of code or output.
+
+Please include the output of `composer info | sort`.
+
+## Workflow for Pull Requests
+
+1. Fork the repository.
+2. Create your branch from `main` if you plan to implement new functionality or
+ change existing code significantly; create your branch from the oldest branch
+ that is affected by the bug if you plan to fix a bug.
+3. Implement your change and add tests for it.
+4. Ensure the test suite passes.
+5. Ensure the code complies with our coding guidelines (see below).
+6. Send that pull request!
+
+Please make sure you have
+[set up your user name and email address](https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup)
+for use with Git. Strings such as `silly nick name <root@localhost>` look really
+stupid in the commit history of a project.
+
+We encourage you to
+[sign your Git commits with your GPG key](https://docs.github.com/en/github/authenticating-to-github/signing-commits).
+
+Pull requests for new features must be based on the `main` branch.
+
+We are trying to keep backwards compatibility breaks in ZipStream-PHP to a
+minimum. Please take this into account when proposing changes.
+
+Due to time constraints, we are not always able to respond as quickly as we
+would like. Please do not take delays personal and feel free to remind us if you
+feel that we forgot to respond.
+
+## Coding Guidelines
+
+This project comes with a configuration file (located at `/psalm.yml` in the
+repository) that you can use to perform static analysis (with a focus on type
+checking):
+
+```bash
+$ .composer run test:lint
+```
+
+This project comes with a configuration file (located at
+`/.php-cs-fixer.dist.php` in the repository) that you can use to (re)format your
+source code for compliance with this project's coding guidelines:
+
+```bash
+$ composer run format
+```
+
+Please understand that we will not accept a pull request when its changes
+violate this project's coding guidelines.
+
+## Using ZipStream-PHP from a Git checkout
+
+The following commands can be used to perform the initial checkout of
+ZipStream-PHP:
+
+```bash
+$ git clone git@github.com:maennchen/ZipStream-PHP.git
+
+$ cd ZipStream-PHP
+```
+
+Install ZipStream-PHP's dependencies using [Composer](https://getcomposer.org/):
+
+```bash
+$ composer install
+$ composer run install:tools # Install phpDocumentor using phive
+```
+
+## Running ZipStream-PHP's test suite
+
+After following the steps shown above, ZipStream-PHP's test suite is run like
+this:
+
+```bash
+$ composer run test:unit
+```
+
+There's some slow tests in the test suite that test the handling of big files in
+the archives. To skip them use the following command instead:
+
+```bash
+$ composer run test:unit:fast
+```
+
+## Generating ZipStream-PHP Documentation
+
+To generate the documentation for the library, run:
+
+```bash
+$ composer run docs:generate
+```
+
+The guide documentation pages can be found in the `/guides/` directory.
diff --git a/vendor/maennchen/zipstream-php/.github/FUNDING.yml b/vendor/maennchen/zipstream-php/.github/FUNDING.yml
new file mode 100644
index 000000000..5a4612769
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/FUNDING.yml
@@ -0,0 +1 @@
+github: maennchen
diff --git a/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/BUG.yml b/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/BUG.yml
new file mode 100644
index 000000000..0eb8cc772
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/BUG.yml
@@ -0,0 +1,71 @@
+name: 🐞 Bug Report
+description: Something is broken?
+labels: ["bug"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ - Create a discussion instead if you are looking for support:
+ https://github.com/maennchen/ZipStream-PHP/discussions
+ - type: input
+ id: version
+ attributes:
+ label: ZipStream-PHP version
+ placeholder: x.y.z
+ validations:
+ required: true
+ - type: input
+ id: php-version
+ attributes:
+ label: PHP version
+ placeholder: x.y.z
+ validations:
+ required: true
+ - type: checkboxes
+ id: constraints
+ attributes:
+ label: Constraints for Bug Report
+ options:
+ - label: |
+ I'm using a version of ZipStream that is currently supported:
+ https://github.com/maennchen/ZipStream-PHP#version-support
+ required: true
+ - label: |
+ I'm using a version of PHP that has active support:
+ https://www.php.net/supported-versions.php
+ required: true
+ - label: |
+ I'm using a version of PHP that is compatible with your used
+ ZipStream version.
+ required: true
+ - label: |
+ I'm using the latest release of the used ZipStream major version.
+ required: true
+ - type: textarea
+ id: summary
+ attributes:
+ label: Summary
+ description: Provide a summary describing the problem you are experiencing.
+ validations:
+ required: true
+ - type: textarea
+ id: current-behaviour
+ attributes:
+ label: Current behavior
+ description: What is the current (buggy) behavior?
+ validations:
+ required: true
+ - type: textarea
+ id: reproduction
+ attributes:
+ label: How to reproduce
+ description: Provide steps to reproduce the bug.
+ validations:
+ required: true
+ - type: textarea
+ id: expected-behaviour
+ attributes:
+ label: Expected behavior
+ description: What was the expected (correct) behavior?
+ validations:
+ required: true
diff --git a/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/FEATURE.yml b/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/FEATURE.yml
new file mode 100644
index 000000000..e5dec6371
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/ISSUE_TEMPLATE/FEATURE.yml
@@ -0,0 +1,11 @@
+name: 🎉 Feature Request
+description: You have a neat idea that should be implemented?
+labels: ["enhancement"]
+body:
+ - type: textarea
+ id: description
+ attributes:
+ label: Description
+ description: Provide a summary of the feature you would like to see implemented.
+ validations:
+ required: true
diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 000000000..6892c571b
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,6 @@
+Please go the the `Preview` tab and select the appropriate sub-template:
+
+* [🐞 Failing Test](?expand=1&template=FAILING_TEST.md)
+* [🐞 Bug Fix](?expand=1&template=FIX.md)
+* [⚙ Improvement](?expand=1&template=IMPROVEMENT.md)
+* [🎉 New Feature](?expand=1&template=NEW_FEATURE.md)
diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FAILING_TEST.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FAILING_TEST.md
new file mode 100644
index 000000000..24603cb63
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FAILING_TEST.md
@@ -0,0 +1,13 @@
+<!---
+name: 🐞 Failing Test
+about: You found a bug and have a failing test?
+labels: bug, tests
+--->
+
+<!--
+- Please do not send a pull request for an issue in a version of ZipStream-PHP
+ that is no longer supported.
+ See: https://github.com/maennchen/ZipStream-PHP#version-support
+- Please target the oldest branch of ZipStream-PHP that is still supported and
+ where the test fails.
+-->
diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FIX.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FIX.md
new file mode 100644
index 000000000..77f65a080
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/FIX.md
@@ -0,0 +1,13 @@
+<!---
+name: 🐞 Bug Fix
+about: You have a fix for a bug?
+labels: bug
+--->
+
+<!--
+- Please do not send a pull request for an issue in a version of ZipStream-PHP
+ that is no longer supported.
+ See: https://github.com/maennchen/ZipStream-PHP#version-support
+- Please target the oldest branch of ZipStream-PHP that is still supported and
+ affected by this bug.
+-->
diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/IMPROVEMENT.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/IMPROVEMENT.md
new file mode 100644
index 000000000..3ac8e3100
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/IMPROVEMENT.md
@@ -0,0 +1,9 @@
+<!---
+name: ⚙ Improvement
+about: You have some improvement to make ZipStream-PHP better?
+labels: enhancement
+--->
+
+<!--
+- Please target the `main` branch of ZipStream-PHP.
+-->
diff --git a/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/NEW_FEATURE.md b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/NEW_FEATURE.md
new file mode 100644
index 000000000..ca53939c8
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/PULL_REQUEST_TEMPLATE/NEW_FEATURE.md
@@ -0,0 +1,9 @@
+<!---
+name: 🎉 New Feature
+about: You have implemented some neat idea that you want to make part of ZipStream-PHP?
+labels: type/enhancement
+--->
+
+<!--
+- Please target the `main` branch of ZipStream-PHP.
+-->
diff --git a/vendor/maennchen/zipstream-php/.github/SECURITY.md b/vendor/maennchen/zipstream-php/.github/SECURITY.md
new file mode 100644
index 000000000..3046c3107
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/SECURITY.md
@@ -0,0 +1,22 @@
+# Security Policy
+
+[![OpenSSF Vulnerability Disclosure](https://img.shields.io/badge/OpenSSF-Vulnerability_Disclosure-green)](https://github.com/ossf/oss-vulnerability-guide/blob/main/finder-guide.md)
+[![GitHub Report](https://img.shields.io/badge/GitHub-Security_Advisories-blue)](https://github.com/maennchen/ZipStream-PHP/security/advisories/new)
+[![Email Report](https://img.shields.io/badge/Email-jonatan%40maennchen.ch-blue)](mailto:jonatan@maennchen.ch)
+
+This repository follows the
+[OpenSSF Vulnerability Disclosure guide](https://github.com/ossf/oss-vulnerability-guide/tree/main).
+You can learn more about it in the
+[Finders Guide](https://github.com/ossf/oss-vulnerability-guide/blob/main/finder-guide.md).
+
+Please report vulnerabilities via the
+[GitHub Security Vulnerability Reporting](https://github.com/maennchen/ZipStream-PHP/security/advisories/new)
+or via email to [`jonatan@maennchen.ch`](mailto:jonatan@maennchen.ch) if this does
+not work for you.
+
+Our vulnerability management team will respond within 3 working days of your
+report. If the issue is confirmed as a vulnerability, we will open a Security
+Advisory. This project follows a 90 day disclosure timeline.
+
+If you have questions about reporting security issues, email the vulnerability
+management team: [`jonatan@maennchen.ch`](mailto:jonatan@maennchen.ch)
diff --git a/vendor/maennchen/zipstream-php/.github/dependabot.yml b/vendor/maennchen/zipstream-php/.github/dependabot.yml
new file mode 100644
index 000000000..6056437b9
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/dependabot.yml
@@ -0,0 +1,13 @@
+version: 2
+updates:
+ - package-ecosystem: "composer"
+ directory: "/"
+ schedule:
+ interval: "daily"
+ - package-ecosystem: "github-actions"
+ directory: "/"
+ schedule:
+ interval: "weekly"
+ groups:
+ github-actions:
+ applies-to: version-updates \ No newline at end of file
diff --git a/vendor/maennchen/zipstream-php/.github/scorecard.yml b/vendor/maennchen/zipstream-php/.github/scorecard.yml
new file mode 100644
index 000000000..219fc0bfd
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/scorecard.yml
@@ -0,0 +1,14 @@
+annotations:
+ - checks:
+ - fuzzing
+ reasons:
+ - reason: not-applicable # PHP is memory safe
+ - checks:
+ - packaging
+ reasons:
+ - reason: not-supported # Using Composer
+ - checks:
+ - signed-releases
+ reasons:
+ - reason: not-applicable # Releases are distributed via Composer
+
diff --git a/vendor/maennchen/zipstream-php/.github/workflows/branch_main.yml b/vendor/maennchen/zipstream-php/.github/workflows/branch_main.yml
new file mode 100644
index 000000000..15ff2782c
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/workflows/branch_main.yml
@@ -0,0 +1,24 @@
+on:
+ push:
+ branches:
+ - "main"
+
+name: "Main Branch"
+
+permissions:
+ contents: read
+
+jobs:
+ test:
+ name: "Test"
+
+ permissions:
+ contents: read
+ security-events: write
+
+ uses: ./.github/workflows/part_test.yml
+
+ docs:
+ name: "Docs"
+
+ uses: ./.github/workflows/part_docs.yml
diff --git a/vendor/maennchen/zipstream-php/.github/workflows/part_dependabot.yml b/vendor/maennchen/zipstream-php/.github/workflows/part_dependabot.yml
new file mode 100644
index 000000000..77e466b81
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/workflows/part_dependabot.yml
@@ -0,0 +1,30 @@
+on:
+ workflow_call: {}
+
+name: "Dependabot"
+
+permissions:
+ contents: read
+
+jobs:
+ automerge_dependabot:
+ name: "Automerge PRs"
+
+ runs-on: ubuntu-latest
+
+ permissions:
+ pull-requests: write
+ contents: write
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - uses: fastify/github-action-merge-dependabot@3892334d1c649bb8119af3d22a3f3766bd5e593f # v3.10.2
+ with:
+ github-token: ${{ github.token }}
+ use-github-auto-merge: true
+ # Major Updates need to be merged manually
+ target: minor
diff --git a/vendor/maennchen/zipstream-php/.github/workflows/part_docs.yml b/vendor/maennchen/zipstream-php/.github/workflows/part_docs.yml
new file mode 100644
index 000000000..7af16f3be
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/workflows/part_docs.yml
@@ -0,0 +1,51 @@
+on:
+ workflow_call: {}
+
+name: "Documentation"
+
+permissions:
+ contents: read
+
+jobs:
+ generate:
+ name: "Generate"
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - name: Checkout Code
+ uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
+ - name: SetUp PHP
+ id: setup-php
+ uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2
+ with:
+ php-version: "8.3"
+ tools: phive
+ - name: Cache Tools
+ uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
+ id: cache
+ with:
+ path: ~/.phive
+ key: tools-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-${{ hashFiles('**/phars.xml') }}
+ restore-keys: |
+ tools-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-
+ tools-${{ steps.setup-php.outputs.php-version }}-
+ tools-
+ - name: Install Tools
+ run: composer run install:tools
+ - name: Generate Docs
+ run: composer run docs:generate
+ - uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1
+ with:
+ name: docs
+ path: docs
+ - name: Package for GitHub Pages
+ uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
+ with:
+ path: docs
+
diff --git a/vendor/maennchen/zipstream-php/.github/workflows/part_release.yml b/vendor/maennchen/zipstream-php/.github/workflows/part_release.yml
new file mode 100644
index 000000000..c0f3867df
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/workflows/part_release.yml
@@ -0,0 +1,94 @@
+on:
+ workflow_call:
+ inputs:
+ releaseName:
+ required: true
+ type: string
+ stable:
+ required: false
+ type: boolean
+ default: false
+
+name: "Release"
+
+permissions:
+ contents: read
+
+jobs:
+ create:
+ name: Create Release
+
+ runs-on: ubuntu-latest
+
+ permissions:
+ contents: write
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - name: Create prerelease
+ if: ${{ !inputs.stable }}
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
+ run: |
+ gh release create \
+ --repo ${{ github.repository }} \
+ --title ${{ inputs.releaseName }} \
+ --prerelease \
+ --generate-notes \
+ ${{ inputs.releaseName }}
+
+ - name: Create release
+ if: ${{ inputs.stable }}
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
+ run: |
+ gh release create \
+ --repo ${{ github.repository }} \
+ --title ${{ inputs.releaseName }} \
+ --generate-notes \
+ ${{ inputs.releaseName }}
+
+ upload_release:
+ name: "Upload"
+
+ needs: ["create"]
+
+ runs-on: ubuntu-latest
+
+ permissions:
+ id-token: write
+ contents: write
+ attestations: write
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
+ - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
+ with:
+ name: docs
+ path: docs
+ - run: |
+ tar -czvf docs.tar.gz docs
+ - name: "Attest Documentation"
+ id: attestation
+ uses: actions/attest-build-provenance@1c608d11d69870c2092266b3f9a6f3abbf17002c # v1.4.3
+ with:
+ subject-path: "docs.tar.gz"
+ - name: Copy Attestation
+ run: cp "$ATTESTATION" docs.tar.gz.sigstore
+ env:
+ ATTESTATION: "${{ steps.attestation.outputs.bundle-path }}"
+ - name: Upload
+ env:
+ GITHUB_TOKEN: ${{ github.token }}
+ run: |
+ gh release upload --clobber "${{ github.ref_name }}" \
+ docs.tar.gz docs.tar.gz.sigstore
diff --git a/vendor/maennchen/zipstream-php/.github/workflows/part_test.yml b/vendor/maennchen/zipstream-php/.github/workflows/part_test.yml
new file mode 100644
index 000000000..ccf4d660e
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/workflows/part_test.yml
@@ -0,0 +1,183 @@
+on:
+ workflow_call:
+
+name: "Test"
+
+permissions:
+ contents: read
+
+jobs:
+ phpunit:
+ name: PHPUnit (PHP ${{ matrix.php }} on ${{ matrix.os }})
+
+ runs-on: ${{ matrix.os }}
+
+ continue-on-error: ${{ matrix.experimental }}
+
+ strategy:
+ fail-fast: false
+ matrix:
+ php: ["8.1", "8.2", "8.3"]
+ os: [ubuntu-latest]
+ experimental: [false]
+ include:
+ - php: nightly
+ os: ubuntu-latest
+ experimental: true
+ - php: "8.3"
+ os: windows-latest
+ experimental: false
+ - php: "8.3"
+ os: macos-latest
+ experimental: false
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - name: Checkout Code
+ uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
+ - name: SetUp PHP
+ id: setup-php
+ uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2
+ with:
+ php-version: "${{ matrix.php }}"
+ tools: phpunit
+ coverage: xdebug
+ extensions: xdebug,zip
+ - name: Get composer cache directory
+ id: composer-cache-common
+ if: "${{ runner.os != 'Windows' }}"
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+ - name: Get composer cache directory
+ id: composer-cache-windows
+ if: "${{ runner.os == 'Windows' }}"
+ run: echo "dir=$(composer config cache-files-dir)" >> $env:GITHUB_OUTPUT
+ - name: Cache Deps
+ uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
+ id: cache
+ with:
+ path: ${{ steps.composer-cache-common.outputs.dir }}${{ steps.composer-cache-windows.outputs.dir }}
+ key: deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer-
+ deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-
+ deps-${{ steps.setup-php.outputs.php-version }}-
+ deps-
+ - name: Install Deps
+ if: matrix.php != 'nightly'
+ run: composer install --prefer-dist
+ - name: Install Deps (ignore PHP requirement)
+ if: matrix.php == 'nightly'
+ run: composer install --prefer-dist --ignore-platform-req=php+
+ - name: Run PHPUnit
+ run: composer run test:unit
+ env:
+ XDEBUG_MODE: coverage
+ - name: Upload coverage results to Coveralls
+ env:
+ COVERALLS_REPO_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ COVERALLS_PARALLEL: true
+ COVERALLS_FLAG_NAME: ${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}
+ run: composer run coverage:report
+ continue-on-error: ${{ matrix.experimental }}
+
+ mark_coverage_done:
+ needs: ["phpunit"]
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - name: Coveralls Finished
+ uses: coverallsapp/github-action@643bc377ffa44ace6394b2b5d0d3950076de9f63 # v2.3.0
+ with:
+ github-token: ${{ secrets.github_token }}
+ parallel-finished: true
+
+ psalm:
+ name: Run Psalm
+
+ runs-on: "ubuntu-latest"
+
+ permissions:
+ security-events: write
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - name: Checkout Code
+ uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
+ - name: SetUp PHP
+ id: setup-php
+ uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2
+ with:
+ php-version: "8.3"
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+ - name: Cache Deps
+ uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
+ id: cache
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer-
+ deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-
+ deps-${{ steps.setup-php.outputs.php-version }}-
+ deps-
+ - name: Install Deps
+ run: composer install --prefer-dist
+ - name: Run Psalm
+ run: composer run test:lint -- --report=results.sarif
+ - name: "Upload SARIF"
+ uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3
+ with:
+ sarif_file: results.sarif
+
+ php-cs:
+ name: Run PHP-CS
+
+ runs-on: "ubuntu-latest"
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - name: Checkout Code
+ uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
+ - name: SetUp PHP
+ id: setup-php
+ uses: shivammathur/setup-php@c541c155eee45413f5b09a52248675b1a2575231 # v2
+ with:
+ php-version: "8.3"
+ - name: Get composer cache directory
+ id: composer-cache
+ run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+ - name: Cache Deps
+ uses: actions/cache@3624ceb22c1c5a301c8db4169662070a689d9ea8 # v4.1.1
+ id: cache
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-composer-
+ deps-${{ runner.os }}-${{ steps.setup-php.outputs.php-version }}-
+ deps-${{ steps.setup-php.outputs.php-version }}-
+ deps-
+ - name: Install Deps
+ run: composer install --prefer-dist
+ - name: Run PHP-CS
+ run: composer run test:formatted
diff --git a/vendor/maennchen/zipstream-php/.github/workflows/pr.yml b/vendor/maennchen/zipstream-php/.github/workflows/pr.yml
new file mode 100644
index 000000000..05259d4f7
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/workflows/pr.yml
@@ -0,0 +1,50 @@
+on:
+ pull_request:
+ branches:
+ - "*"
+ workflow_dispatch: {}
+
+name: "Pull Request"
+
+permissions:
+ contents: read
+
+jobs:
+ test:
+ name: "Test"
+
+ permissions:
+ contents: read
+ security-events: write
+
+ uses: ./.github/workflows/part_test.yml
+
+ docs:
+ name: "Docs"
+
+ uses: ./.github/workflows/part_docs.yml
+
+ dependabot:
+ name: "Dependabot"
+
+ if: ${{ github.actor == 'dependabot[bot]'}}
+
+ permissions:
+ pull-requests: write
+ contents: write
+
+ uses: ./.github/workflows/part_dependabot.yml
+
+ dependency-review:
+ name: Dependency Review
+ runs-on: ubuntu-latest
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - name: 'Checkout Repository'
+ uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
+ - name: 'Dependency Review'
+ uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
diff --git a/vendor/maennchen/zipstream-php/.github/workflows/scorecard.yml b/vendor/maennchen/zipstream-php/.github/workflows/scorecard.yml
new file mode 100644
index 000000000..7bb8dbb6c
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/workflows/scorecard.yml
@@ -0,0 +1,78 @@
+# This workflow uses actions that are not certified by GitHub. They are provided
+# by a third-party and are governed by separate terms of service, privacy
+# policy, and support documentation.
+
+name: Scorecard supply-chain security
+on:
+ # For Branch-Protection check. Only the default branch is supported. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
+ branch_protection_rule:
+ # To guarantee Maintained check is occasionally updated. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
+ schedule:
+ - cron: '28 11 * * 3'
+ push:
+ branches: [ "main" ]
+
+# Declare default permissions as read only.
+permissions: read-all
+
+jobs:
+ analysis:
+ name: Scorecard analysis
+ runs-on: ubuntu-latest
+ permissions:
+ # Needed to upload the results to code-scanning dashboard.
+ security-events: write
+ # Needed to publish results and get a badge (see publish_results below).
+ id-token: write
+ # Uncomment the permissions below if installing in a private repository.
+ # contents: read
+ # actions: read
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - name: "Checkout code"
+ uses: actions/checkout@eef61447b9ff4aafe5dcd4e0bbf5d482be7e7871 # v4.2.1
+ with:
+ persist-credentials: false
+
+ - name: "Run analysis"
+ uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
+ with:
+ results_file: results.sarif
+ results_format: sarif
+ # (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
+ # - you want to enable the Branch-Protection check on a *public* repository, or
+ # - you are installing Scorecard on a *private* repository
+ # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
+ # repo_token: ${{ secrets.SCORECARD_TOKEN }}
+
+ # Public repositories:
+ # - Publish results to OpenSSF REST API for easy access by consumers
+ # - Allows the repository to include the Scorecard badge.
+ # - See https://github.com/ossf/scorecard-action#publishing-results.
+ # For private repositories:
+ # - `publish_results` will always be set to `false`, regardless
+ # of the value entered here.
+ publish_results: true
+
+ # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
+ # format to the repository Actions tab.
+ - name: "Upload artifact"
+ uses: actions/upload-artifact@604373da6381bf24206979c74d06a550515601b9 # v4.4.1
+ with:
+ name: SARIF file
+ path: results.sarif
+ retention-days: 5
+
+ # Upload the results to GitHub's code scanning dashboard (optional).
+ # Commenting out will disable upload of results to your repo's Code Scanning dashboard
+ - name: "Upload to code-scanning"
+ uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
+ with:
+ sarif_file: results.sarif
diff --git a/vendor/maennchen/zipstream-php/.github/workflows/tag-beta.yml b/vendor/maennchen/zipstream-php/.github/workflows/tag-beta.yml
new file mode 100644
index 000000000..b3399454a
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/workflows/tag-beta.yml
@@ -0,0 +1,29 @@
+on:
+ push:
+ tags:
+ - "[0-9]+.[0-9]+.[0-9]+-beta.[0-9]+"
+
+name: "Beta Tag"
+
+permissions:
+ contents: read
+
+jobs:
+ docs:
+ name: "Docs"
+
+ uses: ./.github/workflows/part_docs.yml
+
+ release:
+ name: "Release"
+
+ needs: ["docs"]
+
+ permissions:
+ id-token: write
+ contents: write
+ attestations: write
+
+ uses: ./.github/workflows/part_release.yml
+ with:
+ releaseName: "${{ github.ref_name }}"
diff --git a/vendor/maennchen/zipstream-php/.github/workflows/tag-stable.yml b/vendor/maennchen/zipstream-php/.github/workflows/tag-stable.yml
new file mode 100644
index 000000000..0e91cf0d0
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.github/workflows/tag-stable.yml
@@ -0,0 +1,55 @@
+on:
+ push:
+ tags:
+ - "[0-9]+.[0-9]+.[0-9]+"
+
+name: "Stable Tag"
+
+permissions:
+ contents: read
+
+jobs:
+ docs:
+ name: "Docs"
+
+ uses: ./.github/workflows/part_docs.yml
+
+ release:
+ name: "Release"
+
+ needs: ["docs"]
+
+ permissions:
+ id-token: write
+ contents: write
+ attestations: write
+
+ uses: ./.github/workflows/part_release.yml
+ with:
+ releaseName: "${{ github.ref_name }}"
+ stable: true
+
+ deploy_pages:
+ name: "Deploy to GitHub Pages"
+
+ needs: ["release", "docs"]
+
+ runs-on: ubuntu-latest
+
+ permissions:
+ pages: write
+ id-token: write
+
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+
+ steps:
+ - name: Harden Runner
+ uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+ with:
+ egress-policy: audit
+
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
diff --git a/vendor/maennchen/zipstream-php/.gitignore b/vendor/maennchen/zipstream-php/.gitignore
new file mode 100644
index 000000000..e52a49877
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.gitignore
@@ -0,0 +1,12 @@
+/composer.lock
+/cov
+/coverage.clover.xml
+/docs
+.idea
+/.php-cs-fixer.cache
+/.phpdoc/cache
+/.phpunit.result.cache
+/phpunit.xml
+/.phpunit.cache
+/tools
+/vendor
diff --git a/vendor/maennchen/zipstream-php/.phive/phars.xml b/vendor/maennchen/zipstream-php/.phive/phars.xml
new file mode 100644
index 000000000..183927b12
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.phive/phars.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<phive xmlns="https://phar.io/phive">
+ <phar name="phpdocumentor" version="^3.3.1" installed="3.4.3" location="./tools/phpdocumentor" copy="false"/>
+</phive>
diff --git a/vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php b/vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php
new file mode 100644
index 000000000..38d6a7658
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.php-cs-fixer.dist.php
@@ -0,0 +1,70 @@
+<?php
+
+declare(strict_types=1);
+
+/**
+ * PHP-CS-Fixer config for ZipStream-PHP
+ * @author Nicolas CARPi <nico-git@deltablot.email>
+ * @copyright 2022 Nicolas CARPi
+ * @see https://github.com/maennchen/ZipStream-PHP
+ * @license MIT
+ * @package maennchen/ZipStream-PHP
+ */
+
+use PhpCsFixer\Config;
+use PhpCsFixer\Finder;
+
+$finder = Finder::create()
+ ->exclude('.github')
+ ->exclude('.phpdoc')
+ ->exclude('docs')
+ ->exclude('tools')
+ ->exclude('vendor')
+ ->in(__DIR__);
+
+$config = new Config();
+return $config->setRules([
+ '@PER' => true,
+ '@PER:risky' => true,
+ '@PHP82Migration' => true,
+ '@PHPUnit84Migration:risky' => true,
+ 'array_syntax' => ['syntax' => 'short'],
+ 'class_attributes_separation' => true,
+ 'declare_strict_types' => true,
+ 'dir_constant' => true,
+ 'is_null' => true,
+ 'no_homoglyph_names' => true,
+ 'no_null_property_initialization' => true,
+ 'no_php4_constructor' => true,
+ 'no_unused_imports' => true,
+ 'no_useless_else' => true,
+ 'non_printable_character' => true,
+ 'ordered_imports' => true,
+ 'ordered_class_elements' => true,
+ 'php_unit_construct' => true,
+ 'pow_to_exponentiation' => true,
+ 'psr_autoloading' => true,
+ 'random_api_migration' => true,
+ 'return_assignment' => true,
+ 'self_accessor' => true,
+ 'semicolon_after_instruction' => true,
+ 'short_scalar_cast' => true,
+ 'simplified_null_return' => true,
+ 'single_class_element_per_statement' => true,
+ 'single_line_comment_style' => true,
+ 'single_quote' => true,
+ 'space_after_semicolon' => true,
+ 'standardize_not_equals' => true,
+ 'strict_param' => true,
+ 'ternary_operator_spaces' => true,
+ 'trailing_comma_in_multiline' => true,
+ 'trim_array_spaces' => true,
+ 'unary_operator_spaces' => true,
+ 'global_namespace_import' => [
+ 'import_classes' => true,
+ 'import_functions' => true,
+ 'import_constants' => true,
+ ],
+ ])
+ ->setFinder($finder)
+ ->setRiskyAllowed(true);
diff --git a/vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig b/vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig
new file mode 100644
index 000000000..b7507fb9c
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.phpdoc/template/base.html.twig
@@ -0,0 +1,15 @@
+{% extends 'layout.html.twig' %}
+
+{% set topMenu = {
+ "menu": [
+ { "name": "Guides", "url": "https://maennchen.dev/ZipStream-PHP/guide/index.html"},
+ { "name": "API", "url": "https://maennchen.dev/ZipStream-PHP/classes/ZipStream-ZipStream.html"},
+ { "name": "Issues", "url": "https://github.com/maennchen/ZipStream-PHP/issues"},
+ ],
+ "social": [
+ { "iconClass": "fab fa-github", "url": "https://github.com/maennchen/ZipStream-PHP"},
+ { "iconClass": "fas fa-envelope-open-text", "url": "https://github.com/maennchen/ZipStream-PHP/discussions"},
+ { "iconClass": "fas fa-money-bill", "url": "https://opencollective.com/zipstream"},
+ ]
+}
+%} \ No newline at end of file
diff --git a/vendor/maennchen/zipstream-php/.tool-versions b/vendor/maennchen/zipstream-php/.tool-versions
new file mode 100644
index 000000000..4a3dc9dfd
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/.tool-versions
@@ -0,0 +1 @@
+php 8.3.1
diff --git a/vendor/maennchen/zipstream-php/LICENSE b/vendor/maennchen/zipstream-php/LICENSE
new file mode 100644
index 000000000..ebe7fe2f8
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/LICENSE
@@ -0,0 +1,24 @@
+MIT License
+
+Copyright (C) 2007-2009 Paul Duncan <pabs@pablotron.org>
+Copyright (C) 2014 Jonatan Männchen <jonatan@maennchen.ch>
+Copyright (C) 2014 Jesse G. Donat <donatj@gmail.com>
+Copyright (C) 2018 Nicolas CARPi <nicolas.carpi@curie.fr>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/maennchen/zipstream-php/README.md b/vendor/maennchen/zipstream-php/README.md
new file mode 100644
index 000000000..858add09f
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/README.md
@@ -0,0 +1,154 @@
+# ZipStream-PHP
+
+[![Main Branch](https://github.com/maennchen/ZipStream-PHP/actions/workflows/branch_main.yml/badge.svg)](https://github.com/maennchen/ZipStream-PHP/actions/workflows/branch_main.yml)
+[![Coverage Status](https://coveralls.io/repos/github/maennchen/ZipStream-PHP/badge.svg?branch=main)](https://coveralls.io/github/maennchen/ZipStream-PHP?branch=main)
+[![Latest Stable Version](https://poser.pugx.org/maennchen/zipstream-php/v/stable)](https://packagist.org/packages/maennchen/zipstream-php)
+[![Total Downloads](https://poser.pugx.org/maennchen/zipstream-php/downloads)](https://packagist.org/packages/maennchen/zipstream-php)
+[![Financial Contributors on Open Collective](https://opencollective.com/zipstream/all/badge.svg?label=financial+contributors)](https://opencollective.com/zipstream) [![License](https://img.shields.io/github/license/maennchen/zipstream-php.svg)](LICENSE)
+[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/9524/badge)](https://www.bestpractices.dev/projects/9524)
+[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/maennchen/ZipStream-PHP/badge)](https://scorecard.dev/viewer/?uri=github.com/maennchen/ZipStream-PHP)
+
+## Unstable Branch
+
+The `main` branch is not stable. Please see the
+[releases](https://github.com/maennchen/ZipStream-PHP/releases) for a stable
+version.
+
+## Overview
+
+A fast and simple streaming zip file downloader for PHP. Using this library will
+save you from having to write the Zip to disk. You can directly send it to the
+user, which is much faster. It can work with S3 buckets or any PSR7 Stream.
+
+Please see the [LICENSE](LICENSE) file for licensing and warranty information.
+
+## Installation
+
+Simply add a dependency on maennchen/zipstream-php to your project's
+`composer.json` file if you use Composer to manage the dependencies of your
+project. Use following command to add the package to your project's dependencies:
+
+```bash
+composer require maennchen/zipstream-php
+```
+
+## Usage
+
+For detailed instructions, please check the
+[Documentation](https://maennchen.github.io/ZipStream-PHP/).
+
+```php
+// Autoload the dependencies
+require 'vendor/autoload.php';
+
+// create a new zipstream object
+$zip = new ZipStream\ZipStream(
+ outputName: 'example.zip',
+
+ // enable output of HTTP headers
+ sendHttpHeaders: true,
+);
+
+// create a file named 'hello.txt'
+$zip->addFile(
+ fileName: 'hello.txt',
+ data: 'This is the contents of hello.txt',
+);
+
+// add a file named 'some_image.jpg' from a local file 'path/to/image.jpg'
+$zip->addFileFromPath(
+ fileName: 'some_image.jpg',
+ path: 'path/to/image.jpg',
+);
+
+// finish the zip stream
+$zip->finish();
+```
+
+## Upgrade to version 3.0.0
+
+### General
+
+- Minimum PHP Version: `8.1`
+- Only 64bit Architecture is supported.
+- The class `ZipStream\Option\Method` has been replaced with the enum
+ `ZipStream\CompressionMethod`.
+- Most clases have been flagged as `@internal` and should not be used from the
+ outside.
+ If you're using internal resources to extend this library, please open an
+ issue so that a clean interface can be added & published.
+ The externally available classes & enums are:
+ - `ZipStream\CompressionMethod`
+ - `ZipStream\Exception*`
+ - `ZipStream\ZipStream`
+
+### Archive Options
+
+- The class `ZipStream\Option\Archive` has been replaced in favor of named
+ arguments in the `ZipStream\ZipStream` constuctor.
+- The archive options `largeFileSize` & `largeFileMethod` has been removed. If
+ you want different `compressionMethods` based on the file size, you'll have to
+ implement this yourself.
+- The archive option `httpHeaderCallback` changed the type from `callable` to
+ `Closure`.
+- The archive option `zeroHeader` has been replaced with the option
+ `defaultEnableZeroHeader` and can be overridden for every file. Its default
+ value changed from `false` to `true`.
+- The archive option `statFiles` was removed since the library no longer checks
+ filesizes this way.
+- The archive option `deflateLevel` has been replaced with the option
+ `defaultDeflateLevel` and can be overridden for every file.
+- The first argument (`name`) of the `ZipStream\ZipStream` constuctor has been
+ replaced with the named argument `outputName`.
+- Headers are now also sent if the `outputName` is empty. If you do not want to
+ automatically send http headers, set `sendHttpHeaders` to `false`.
+
+### File Options
+
+- The class `ZipStream\Option\File` has been replaced in favor of named
+ arguments in the `ZipStream\ZipStream->addFile*` functions.
+- The file option `method` has been renamed to `compressionMethod`.
+- The file option `time` has been renamed to `lastModificationDateTime`.
+- The file option `size` has been renamed to `maxSize`.
+
+## Upgrade to version 2.0.0
+
+https://github.com/maennchen/ZipStream-PHP/tree/2.0.0#upgrade-to-version-200
+
+## Upgrade to version 1.0.0
+
+https://github.com/maennchen/ZipStream-PHP/tree/2.0.0#upgrade-to-version-100
+
+## Contributing
+
+ZipStream-PHP is a collaborative project. Please take a look at the
+[.github/CONTRIBUTING.md](.github/CONTRIBUTING.md) file.
+
+## Version Support
+
+Versions are supported according to the table below.
+
+Please do not open any pull requests contradicting the current version support
+status.
+
+Careful: Always check the `README` on `main` for up-to-date information.
+
+| Version | New Features | Bugfixes | Security |
+|---------|--------------|----------|----------|
+| *3* | ✓ | ✓ | ✓ |
+| *2* | ✗ | ✗ | ✓ |
+| *1* | ✗ | ✗ | ✗ |
+| *0* | ✗ | ✗ | ✗ |
+
+This library aligns itself with the PHP core support. New features and bugfixes
+will only target PHP versions according to their current status.
+
+See: https://www.php.net/supported-versions.php
+
+## About the Authors
+
+- Paul Duncan <pabs@pablotron.org> - https://pablotron.org/
+- Jonatan Männchen <jonatan@maennchen.ch> - https://maennchen.dev
+- Jesse G. Donat <donatj@gmail.com> - https://donatstudios.com
+- Nicolas CARPi <nico-git@deltablot.email> - https://www.deltablot.com
+- Nik Barham <nik@brokencube.co.uk> - https://www.brokencube.co.uk
diff --git a/vendor/maennchen/zipstream-php/composer.json b/vendor/maennchen/zipstream-php/composer.json
new file mode 100644
index 000000000..de5e62413
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/composer.json
@@ -0,0 +1,88 @@
+{
+ "name": "maennchen/zipstream-php",
+ "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
+ "keywords": ["zip", "stream"],
+ "type": "library",
+ "license": "MIT",
+ "authors": [{
+ "name": "Paul Duncan",
+ "email": "pabs@pablotron.org"
+ },
+ {
+ "name": "Jonatan Männchen",
+ "email": "jonatan@maennchen.ch"
+ },
+ {
+ "name": "Jesse Donat",
+ "email": "donatj@gmail.com"
+ },
+ {
+ "name": "András Kolesár",
+ "email": "kolesar@kolesar.hu"
+ }
+ ],
+ "require": {
+ "php-64bit": "^8.1",
+ "ext-mbstring": "*",
+ "ext-zlib": "*"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0",
+ "guzzlehttp/guzzle": "^7.5",
+ "ext-zip": "*",
+ "mikey179/vfsstream": "^1.6",
+ "php-coveralls/php-coveralls": "^2.5",
+ "friendsofphp/php-cs-fixer": "^3.16",
+ "vimeo/psalm": "^5.0"
+ },
+ "suggest": {
+ "psr/http-message": "^2.0",
+ "guzzlehttp/psr7": "^2.4"
+ },
+ "scripts": {
+ "format": "php-cs-fixer fix",
+ "test": [
+ "@test:unit",
+ "@test:formatted",
+ "@test:lint"
+ ],
+ "test:unit": "phpunit --coverage-clover=coverage.clover.xml --coverage-html cov",
+ "test:unit:slow": "@test:unit --group slow",
+ "test:unit:fast": "@test:unit --exclude-group slow",
+ "test:formatted": "@format --dry-run --stop-on-violation --using-cache=no",
+ "test:lint": "psalm --stats --show-info=true --find-unused-psalm-suppress",
+ "coverage:report": "php-coveralls --coverage_clover=coverage.clover.xml --json_path=coveralls-upload.json --insecure",
+ "install:tools": "phive install --trust-gpg-keys 0x67F861C3D889C656 --trust-gpg-keys 0x8AC0BAA79732DD42",
+ "docs:generate": "tools/phpdocumentor --sourcecode"
+ },
+ "autoload": {
+ "psr-4": {
+ "ZipStream\\": "src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": { "ZipStream\\Test\\": "test/" }
+ },
+ "archive": {
+ "exclude": [
+ "/composer.lock",
+ "/docs",
+ "/.gitattributes",
+ "/.github",
+ "/.gitignore",
+ "/guides",
+ "/.phive",
+ "/.php-cs-fixer.cache",
+ "/.php-cs-fixer.dist.php",
+ "/.phpdoc",
+ "/phpdoc.dist.xml",
+ "/.phpunit.result.cache",
+ "/phpunit.xml.dist",
+ "/psalm.xml",
+ "/test",
+ "/tools",
+ "/.tool-versions",
+ "/vendor"
+ ]
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/guides/ContentLength.rst b/vendor/maennchen/zipstream-php/guides/ContentLength.rst
new file mode 100644
index 000000000..21fea34d7
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/guides/ContentLength.rst
@@ -0,0 +1,47 @@
+Adding Content-Length header
+=============
+
+Adding a ``Content-Length`` header for ``ZipStream`` can be achieved by
+using the options ``SIMULATION_STRICT`` or ``SIMULATION_LAX`` in the
+``operationMode`` parameter.
+
+In the ``SIMULATION_STRICT`` mode, ``ZipStream`` will not allow to calculate the
+size based on reading the whole file. ``SIMULATION_LAX`` will read the whole
+file if neccessary.
+
+``SIMULATION_STRICT`` is therefore useful to make sure that the size can be
+calculated efficiently.
+
+.. code-block:: php
+ use ZipStream\OperationMode;
+ use ZipStream\ZipStream;
+
+ $zip = new ZipStream(
+ operationMode: OperationMode::SIMULATE_STRICT, // or SIMULATE_LAX
+ defaultEnableZeroHeader: false,
+ sendHttpHeaders: true,
+ outputStream: $stream,
+ );
+
+ // Normally add files
+ $zip->addFile('sample.txt', 'Sample String Data');
+
+ // Use addFileFromCallback and exactSize if you want to defer opening of
+ // the file resource
+ $zip->addFileFromCallback(
+ 'sample.txt',
+ exactSize: 18,
+ callback: function () {
+ return fopen('...');
+ }
+ );
+
+ // Read resulting file size
+ $size = $zip->finish();
+
+ // Tell it to the browser
+ header('Content-Length: '. $size);
+
+ // Execute the Simulation and stream the actual zip to the client
+ $zip->executeSimulation();
+
diff --git a/vendor/maennchen/zipstream-php/guides/FlySystem.rst b/vendor/maennchen/zipstream-php/guides/FlySystem.rst
new file mode 100644
index 000000000..4e6c6fb82
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/guides/FlySystem.rst
@@ -0,0 +1,34 @@
+Usage with FlySystem
+===============
+
+For saving or uploading the generated zip, you can use the
+`Flysystem <https://flysystem.thephpleague.com>`_ package, and its many
+adapters.
+
+For that you will need to provide another stream than the ``php://output``
+default one, and pass it to Flysystem ``putStream`` method.
+
+.. code-block:: php
+
+ // Open Stream only once for read and write since it's a memory stream and
+ // the content is lost when closing the stream / opening another one
+ $tempStream = fopen('php://memory', 'w+');
+
+ // Create Zip Archive
+ $zipStream = new ZipStream(
+ outputStream: $tempStream,
+ outputName: 'test.zip',
+ );
+ $zipStream->addFile('test.txt', 'text');
+ $zipStream->finish();
+
+ // Store File
+ // (see Flysystem documentation, and all its framework integration)
+ // Can be any adapter (AWS, Google, Ftp, etc.)
+ $adapter = new Local(__DIR__.'/path/to/folder');
+ $filesystem = new Filesystem($adapter);
+
+ $filesystem->writeStream('test.zip', $tempStream)
+
+ // Close Stream
+ fclose($tempStream);
diff --git a/vendor/maennchen/zipstream-php/guides/Nginx.rst b/vendor/maennchen/zipstream-php/guides/Nginx.rst
new file mode 100644
index 000000000..c53d3000e
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/guides/Nginx.rst
@@ -0,0 +1,16 @@
+Usage with nginx
+=============
+
+If you are using nginx as a webserver, it will try to buffer the response.
+So you'll want to disable this with a custom header:
+
+.. code-block:: php
+ header('X-Accel-Buffering: no');
+ # or with the Response class from Symfony
+ $response->headers->set('X-Accel-Buffering', 'no');
+
+Alternatively, you can tweak the
+`fastcgi cache parameters <https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html#fastcgi_buffers>`_
+within nginx config.
+
+See `original issue <https://github.com/maennchen/ZipStream-PHP/issues/77>`_. \ No newline at end of file
diff --git a/vendor/maennchen/zipstream-php/guides/Options.rst b/vendor/maennchen/zipstream-php/guides/Options.rst
new file mode 100644
index 000000000..5e92e94d6
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/guides/Options.rst
@@ -0,0 +1,66 @@
+Available options
+===============
+
+Here is the full list of options available to you. You can also have a look at
+``src/ZipStream.php`` file.
+
+.. code-block:: php
+
+ use ZipStream\ZipStream;
+
+ require_once 'vendor/autoload.php';
+
+ $zip = new ZipStream(
+ // Define output stream
+ // (argument is eiter a resource or implementing
+ // `Psr\Http\Message\StreamInterface`)
+ //
+ // Setup with `psr/http-message` & `guzzlehttp/psr7` dependencies
+ // required when using `Psr\Http\Message\StreamInterface`.
+ outputStream: $filePointer,
+
+ // Set the deflate level (default is 6; use -1 to disable it)
+ defaultDeflateLevel: 6,
+
+ // Add a comment to the zip file
+ comment: 'This is a comment.',
+
+ // Send http headers (default is true)
+ sendHttpHeaders: false,
+
+ // HTTP Content-Disposition.
+ // Defaults to 'attachment', where FILENAME is the specified filename.
+ // Note that this does nothing if you are not sending HTTP headers.
+ contentDisposition: 'attachment',
+
+ // Output Name for HTTP Content-Disposition
+ // Defaults to no name
+ outputName: "example.zip",
+
+ // HTTP Content-Type.
+ // Defaults to 'application/x-zip'.
+ // Note that this does nothing if you are not sending HTTP headers.
+ contentType: 'application/x-zip',
+
+ // Set the function called for setting headers.
+ // Default is the `header()` of PHP
+ httpHeaderCallback: header(...),
+
+ // Enable streaming files with single read where general purpose bit 3
+ // indicates local file header contain zero values in crc and size
+ // fields, these appear only after file contents in data descriptor
+ // block.
+ // Set to true if your input stream is remote
+ // (used with addFileFromStream()).
+ // Default is false.
+ defaultEnableZeroHeader: false,
+
+ // Enable zip64 extension, allowing very large archives
+ // (> 4Gb or file count > 64k)
+ // Default is true
+ enableZip64: true,
+
+ // Flush output buffer after every write
+ // Default is false
+ flushOutput: true,
+ );
diff --git a/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst b/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst
new file mode 100644
index 000000000..22af71d4a
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/guides/PSR7Streams.rst
@@ -0,0 +1,21 @@
+Usage with PSR 7 Streams
+===============
+
+PSR-7 streams are `standardized streams <https://www.php-fig.org/psr/psr-7/>`_.
+
+ZipStream-PHP supports working with these streams with the function
+``addFileFromPsr7Stream``.
+
+For all parameters of the function see the API documentation.
+
+Example
+---------------
+
+.. code-block:: php
+
+ $stream = $response->getBody();
+ // add a file named 'streamfile.txt' from the content of the stream
+ $zip->addFileFromPsr7Stream(
+ fileName: 'streamfile.txt',
+ stream: $stream,
+ );
diff --git a/vendor/maennchen/zipstream-php/guides/StreamOutput.rst b/vendor/maennchen/zipstream-php/guides/StreamOutput.rst
new file mode 100644
index 000000000..9f3165b75
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/guides/StreamOutput.rst
@@ -0,0 +1,39 @@
+Stream Output
+===============
+
+Stream to S3 Bucket
+---------------
+
+.. code-block:: php
+
+ use Aws\S3\S3Client;
+ use Aws\Credentials\CredentialProvider;
+ use ZipStream\ZipStream;
+
+ $bucket = 'your bucket name';
+ $client = new S3Client([
+ 'region' => 'your region',
+ 'version' => 'latest',
+ 'bucketName' => $bucket,
+ 'credentials' => CredentialProvider::defaultProvider(),
+ ]);
+ $client->registerStreamWrapper();
+
+ $zipFile = fopen("s3://$bucket/example.zip", 'w');
+
+ $zip = new ZipStream(
+ enableZip64: false,
+ outputStream: $zipFile,
+ );
+
+ $zip->addFile(
+ fileName: 'file1.txt',
+ data: 'File1 data',
+ );
+ $zip->addFile(
+ fileName: 'file2.txt',
+ data: 'File2 data',
+ );
+ $zip->finish();
+
+ fclose($zipFile);
diff --git a/vendor/maennchen/zipstream-php/guides/Symfony.rst b/vendor/maennchen/zipstream-php/guides/Symfony.rst
new file mode 100644
index 000000000..902552c92
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/guides/Symfony.rst
@@ -0,0 +1,130 @@
+Usage with Symfony
+===============
+
+Overview for using ZipStream in Symfony
+--------
+
+Using ZipStream in Symfony requires use of Symfony's ``StreamedResponse`` when
+used in controller actions.
+
+Wrap your call to the relevant ``ZipStream`` stream method (i.e. ``addFile``,
+``addFileFromPath``, ``addFileFromStream``) in Symfony's ``StreamedResponse``
+function passing in any required arguments for your use case.
+
+Using Symfony's ``StreamedResponse`` will allow Symfony to stream output from
+ZipStream correctly to users' browsers and avoid a corrupted final zip landing
+on the users' end.
+
+Example for using ``ZipStream`` in a controller action to zip stream files
+stored in an AWS S3 bucket by key:
+
+.. code-block:: php
+
+ use Symfony\Component\HttpFoundation\StreamedResponse;
+ use Aws\S3\S3Client;
+ use ZipStream;
+
+ //...
+
+ /**
+ * @Route("/zipstream", name="zipstream")
+ */
+ public function zipStreamAction()
+ {
+ // sample test file on s3
+ $s3keys = array(
+ "ziptestfolder/file1.txt"
+ );
+
+ $s3Client = $this->get('app.amazon.s3'); //s3client service
+ $s3Client->registerStreamWrapper(); //required
+
+ // using StreamedResponse to wrap ZipStream functionality
+ // for files on AWS s3.
+ $response = new StreamedResponse(function() use($s3keys, $s3Client)
+ {
+ // Define suitable options for ZipStream Archive.
+ // this is needed to prevent issues with truncated zip files
+ //initialise zipstream with output zip filename and options.
+ $zip = new ZipStream\ZipStream(
+ outputName: 'test.zip',
+ defaultEnableZeroHeader: true,
+ contentType: 'application/octet-stream',
+ );
+
+ //loop keys - useful for multiple files
+ foreach ($s3keys as $key) {
+ // Get the file name in S3 key so we can save it to the zip
+ //file using the same name.
+ $fileName = basename($key);
+
+ // concatenate s3path.
+ // replace with your bucket name or get from parameters file.
+ $bucket = 'bucketname';
+ $s3path = "s3://" . $bucket . "/" . $key;
+
+ //addFileFromStream
+ if ($streamRead = fopen($s3path, 'r')) {
+ $zip->addFileFromStream(
+ fileName: $fileName,
+ stream: $streamRead,
+ );
+ } else {
+ die('Could not open stream for reading');
+ }
+ }
+
+ $zip->finish();
+
+ });
+
+ return $response;
+ }
+
+In the above example, files on AWS S3 are being streamed from S3 to the Symfon
+application via ``fopen`` call when the s3Client has ``registerStreamWrapper``
+applied. This stream is then passed to ``ZipStream`` via the
+``addFileFromStream`` function, which ZipStream then streams as a zip to the
+client browser via Symfony's ``StreamedResponse``. No Zip is created server
+side, which makes this approach a more efficient solution for streaming zips to
+the client browser especially for larger files.
+
+For the above use case you will need to have installed
+`aws/aws-sdk-php-symfony <https://github.com/aws/aws-sdk-php-symfony>`_ to
+support accessing S3 objects in your Symfony web application. This is not
+required for locally stored files on you server you intend to stream via
+``ZipStream``.
+
+See official Symfony documentation for details on
+`Symfony's StreamedResponse <https://symfony.com/doc/current/components/http_foundation.html#streaming-a-response>`_
+``Symfony\Component\HttpFoundation\StreamedResponse``.
+
+Note from `S3 documentation <https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-stream-wrapper.html>`_:
+
+ Streams opened in "r" mode only allow data to be read from the stream, and
+ are not seekable by default. This is so that data can be downloaded from
+ Amazon S3 in a truly streaming manner, where previously read bytes do not
+ need to be buffered into memory. If you need a stream to be seekable, you
+ can pass seekable into the stream context options of a function.
+
+Make sure to configure your S3 context correctly!
+
+Uploading a file
+--------
+
+You need to add correct permissions
+(see `#120 <https://github.com/maennchen/ZipStream-PHP/issues/120>`_)
+
+**example code**
+
+
+.. code-block:: php
+
+ $path = "s3://{$adapter->getBucket()}/{$this->getArchivePath()}";
+
+ // the important bit
+ $outputContext = stream_context_create([
+ 's3' => ['ACL' => 'public-read'],
+ ]);
+
+ fopen($path, 'w', null, $outputContext);
diff --git a/vendor/maennchen/zipstream-php/guides/Varnish.rst b/vendor/maennchen/zipstream-php/guides/Varnish.rst
new file mode 100644
index 000000000..952d28749
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/guides/Varnish.rst
@@ -0,0 +1,22 @@
+Usage with Varnish
+=============
+
+Serving a big zip with varnish in between can cause random stream close.
+This can be solved by adding attached code to the vcl file.
+
+To avoid the problem, add the following to your varnish config file:
+
+.. code-block::
+ sub vcl_recv {
+ # Varnish can’t intercept the discussion anymore
+ # helps for streaming big zips
+ if (req.url ~ "\.(tar|gz|zip|7z|exe)$") {
+ return (pipe);
+ }
+ }
+ # Varnish can’t intercept the discussion anymore
+ # helps for streaming big zips
+ sub vcl_pipe {
+ set bereq.http.connection = "close";
+ return (pipe);
+ }
diff --git a/vendor/maennchen/zipstream-php/guides/index.rst b/vendor/maennchen/zipstream-php/guides/index.rst
new file mode 100644
index 000000000..48f465aea
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/guides/index.rst
@@ -0,0 +1,126 @@
+ZipStream PHP
+=============
+
+A fast and simple streaming zip file downloader for PHP. Using this library will
+save you from having to write the Zip to disk. You can directly send it to the
+user, which is much faster. It can work with S3 buckets or any PSR7 Stream.
+
+.. toctree::
+
+ index
+ Symfony
+ Options
+ StreamOutput
+ FlySystem
+ PSR7Streams
+ Nginx
+ Varnish
+ ContentLength
+
+Installation
+---------------
+
+Simply add a dependency on ``maennchen/zipstream-php`` to your project's
+``composer.json`` file if you use Composer to manage the dependencies of your
+project. Use following command to add the package to your project's
+dependencies:
+
+.. code-block:: sh
+ composer require maennchen/zipstream-php
+
+If you want to use``addFileFromPsr7Stream```
+(``Psr\Http\Message\StreamInterface``) or use a stream instead of a
+``resource`` as ``outputStream``, the following dependencies must be installed
+as well:
+
+.. code-block:: sh
+ composer require psr/http-message guzzlehttp/psr7
+
+If ``composer install`` yields the following error, your installation is missing
+the `mbstring extension <https://www.php.net/manual/en/book.mbstring.php>`_,
+either `install it <https://www.php.net/manual/en/mbstring.installation.php>`_
+or run the follwoing command:
+
+.. code-block::
+ Your requirements could not be resolved to an installable set of packages.
+
+ Problem 1
+ - Root composer.json requires PHP extension ext-mbstring * but it is
+ missing from your system. Install or enable PHP's mbstrings extension.
+
+.. code-block:: sh
+ composer require symfony/polyfill-mbstring
+
+Usage Intro
+---------------
+
+Here's a simple example:
+
+.. code-block:: php
+
+ // Autoload the dependencies
+ require 'vendor/autoload.php';
+
+ // create a new zipstream object
+ $zip = new ZipStream\ZipStream(
+ outputName: 'example.zip',
+
+ // enable output of HTTP headers
+ sendHttpHeaders: true,
+ );
+
+ // create a file named 'hello.txt'
+ $zip->addFile(
+ fileName: 'hello.txt',
+ data: 'This is the contents of hello.txt',
+ );
+
+ // add a file named 'some_image.jpg' from a local file 'path/to/image.jpg'
+ $zip->addFileFromPath(
+ fileName: 'some_image.jpg',
+ path: 'path/to/image.jpg',
+ );
+
+ // add a file named 'goodbye.txt' from an open stream resource
+ $filePointer = tmpfile();
+ fwrite($filePointer, 'The quick brown fox jumped over the lazy dog.');
+ rewind($filePointer);
+ $zip->addFileFromStream(
+ fileName: 'goodbye.txt',
+ stream: $filePointer,
+ );
+ fclose($filePointer);
+
+ // add a file named 'streamfile.txt' from the body of a `guzzle` response
+ // Setup with `psr/http-message` & `guzzlehttp/psr7` dependencies required.
+ $zip->addFileFromPsr7Stream(
+ fileName: 'streamfile.txt',
+ stream: $response->getBody(),
+ );
+
+ // finish the zip stream
+ $zip->finish();
+
+You can also add comments, modify file timestamps, and customize (or
+disable) the HTTP headers. It is also possible to specify the storage method
+when adding files, the current default storage method is ``DEFLATE``
+i.e files are stored with Compression mode 0x08.
+
+Known Issues
+---------------
+
+The native Mac OS archive extraction tool prior to macOS 10.15 might not open
+archives in some conditions. A workaround is to disable the Zip64 feature with
+the option ``enableZip64: false``. This limits the archive to 4 Gb and 64k files
+but will allow users on macOS 10.14 and below to open them without issue.
+See `#116 <https://github.com/maennchen/ZipStream-PHP/issues/116>`_.
+
+The linux ``unzip`` utility might not handle properly unicode characters.
+It is recommended to extract with another tool like
+`7-zip <https://www.7-zip.org/>`_.
+See `#146 <https://github.com/maennchen/ZipStream-PHP/issues/146>`_.
+
+It is the responsability of the client code to make sure that files are not
+saved with the same path, as it is not possible for the library to figure it out
+while streaming a zip.
+See `#154 <https://github.com/maennchen/ZipStream-PHP/issues/154>`_.
diff --git a/vendor/maennchen/zipstream-php/phpdoc.dist.xml b/vendor/maennchen/zipstream-php/phpdoc.dist.xml
new file mode 100644
index 000000000..b98fe1cd2
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/phpdoc.dist.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<phpdocumentor
+ configVersion="3"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="https://www.phpdoc.org"
+ xsi:noNamespaceSchemaLocation="https://raw.githubusercontent.com/phpDocumentor/phpDocumentor/master/data/xsd/phpdoc.xsd"
+>
+ <title>💾 ZipStream-PHP</title>
+ <paths>
+ <output>docs</output>
+ </paths>
+ <version number="3.0.0">
+ <folder>latest</folder>
+ <api>
+ <source dsn=".">
+ <path>src</path>
+ </source>
+ <output>api</output>
+ <ignore hidden="true" symlinks="true">
+ <path>tests/**/*</path>
+ <path>vendor/**/*</path>
+ </ignore>
+ <extensions>
+ <extension>php</extension>
+ </extensions>
+ <visibility>public</visibility>
+ <default-package-name>ZipStream</default-package-name>
+ <include-source>true</include-source>
+ </api>
+ <guide>
+ <source dsn=".">
+ <path>guides</path>
+ </source>
+ <output>guide</output>
+ </guide>
+ </version>
+ <setting name="guides.enabled" value="true"/>
+ <template name="default" />
+</phpdocumentor> \ No newline at end of file
diff --git a/vendor/maennchen/zipstream-php/phpunit.xml.dist b/vendor/maennchen/zipstream-php/phpunit.xml.dist
new file mode 100644
index 000000000..1b02a3af8
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/phpunit.xml.dist
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="test/bootstrap.php" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.1/phpunit.xsd" cacheDirectory=".phpunit.cache">
+ <coverage/>
+ <testsuites>
+ <testsuite name="Application">
+ <directory>test</directory>
+ </testsuite>
+ </testsuites>
+ <logging/>
+ <source>
+ <include>
+ <directory suffix=".php">src</directory>
+ </include>
+ </source>
+</phpunit>
diff --git a/vendor/maennchen/zipstream-php/psalm.xml b/vendor/maennchen/zipstream-php/psalm.xml
new file mode 100644
index 000000000..4da861836
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/psalm.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0"?>
+<psalm
+ errorLevel="1"
+ resolveFromConfigFile="true"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="https://getpsalm.org/schema/config"
+ xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
+ findUnusedBaselineEntry="true"
+ findUnusedCode="true"
+ phpVersion="8.1.0"
+>
+ <!-- TODO: Update phpVersion when raising the minimum supported version -->
+ <projectFiles>
+ <directory name="src" />
+ <ignoreFiles>
+ <directory name="vendor" />
+ </ignoreFiles>
+ </projectFiles>
+ <issueHandlers>
+ <!-- Turn off dead code warnings for externally called functions -->
+ <PossiblyUnusedProperty errorLevel="suppress" />
+ <PossiblyUnusedMethod errorLevel="suppress" />
+ <PossiblyUnusedReturnValue errorLevel="suppress" />
+ </issueHandlers>
+</psalm>
diff --git a/vendor/maennchen/zipstream-php/results.sarif b/vendor/maennchen/zipstream-php/results.sarif
new file mode 100644
index 000000000..c99a3f47f
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/results.sarif
@@ -0,0 +1 @@
+{"version":"2.1.0","$schema":"https:\/\/json.schemastore.org\/sarif-2.1.0.json","runs":[{"tool":{"driver":{"name":"Psalm","informationUri":"https:\/\/psalm.dev","version":"5.26.1@d747f6500b38ac4f7dfc5edbcae6e4b637d7add0"}},"results":[]}]}
diff --git a/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php b/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php
new file mode 100644
index 000000000..ffcfc6e97
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/CentralDirectoryFileHeader.php
@@ -0,0 +1,52 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+use DateTimeInterface;
+
+/**
+ * @internal
+ */
+abstract class CentralDirectoryFileHeader
+{
+ private const SIGNATURE = 0x02014b50;
+
+ public static function generate(
+ int $versionMadeBy,
+ int $versionNeededToExtract,
+ int $generalPurposeBitFlag,
+ CompressionMethod $compressionMethod,
+ DateTimeInterface $lastModificationDateTime,
+ int $crc32,
+ int $compressedSize,
+ int $uncompressedSize,
+ string $fileName,
+ string $extraField,
+ string $fileComment,
+ int $diskNumberStart,
+ int $internalFileAttributes,
+ int $externalFileAttributes,
+ int $relativeOffsetOfLocalHeader,
+ ): string {
+ return PackField::pack(
+ new PackField(format: 'V', value: self::SIGNATURE),
+ new PackField(format: 'v', value: $versionMadeBy),
+ new PackField(format: 'v', value: $versionNeededToExtract),
+ new PackField(format: 'v', value: $generalPurposeBitFlag),
+ new PackField(format: 'v', value: $compressionMethod->value),
+ new PackField(format: 'V', value: Time::dateTimeToDosTime($lastModificationDateTime)),
+ new PackField(format: 'V', value: $crc32),
+ new PackField(format: 'V', value: $compressedSize),
+ new PackField(format: 'V', value: $uncompressedSize),
+ new PackField(format: 'v', value: strlen($fileName)),
+ new PackField(format: 'v', value: strlen($extraField)),
+ new PackField(format: 'v', value: strlen($fileComment)),
+ new PackField(format: 'v', value: $diskNumberStart),
+ new PackField(format: 'v', value: $internalFileAttributes),
+ new PackField(format: 'V', value: $externalFileAttributes),
+ new PackField(format: 'V', value: $relativeOffsetOfLocalHeader),
+ ) . $fileName . $extraField . $fileComment;
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/CompressionMethod.php b/vendor/maennchen/zipstream-php/src/CompressionMethod.php
new file mode 100644
index 000000000..51e436370
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/CompressionMethod.php
@@ -0,0 +1,106 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+enum CompressionMethod: int
+{
+ /**
+ * The file is stored (no compression)
+ */
+ case STORE = 0x00;
+
+ // 0x01: legacy algorithm - The file is Shrunk
+ // 0x02: legacy algorithm - The file is Reduced with compression factor 1
+ // 0x03: legacy algorithm - The file is Reduced with compression factor 2
+ // 0x04: legacy algorithm - The file is Reduced with compression factor 3
+ // 0x05: legacy algorithm - The file is Reduced with compression factor 4
+ // 0x06: legacy algorithm - The file is Imploded
+ // 0x07: Reserved for Tokenizing compression algorithm
+
+ /**
+ * The file is Deflated
+ */
+ case DEFLATE = 0x08;
+
+ // /**
+ // * Enhanced Deflating using Deflate64(tm)
+ // */
+ // case DEFLATE_64 = 0x09;
+
+ // /**
+ // * PKWARE Data Compression Library Imploding (old IBM TERSE)
+ // */
+ // case PKWARE = 0x0a;
+
+ // // 0x0b: Reserved by PKWARE
+
+ // /**
+ // * File is compressed using BZIP2 algorithm
+ // */
+ // case BZIP2 = 0x0c;
+
+ // // 0x0d: Reserved by PKWARE
+
+ // /**
+ // * LZMA
+ // */
+ // case LZMA = 0x0e;
+
+ // // 0x0f: Reserved by PKWARE
+
+ // /**
+ // * IBM z/OS CMPSC Compression
+ // */
+ // case IBM_ZOS_CMPSC = 0x10;
+
+ // // 0x11: Reserved by PKWARE
+
+ // /**
+ // * File is compressed using IBM TERSE
+ // */
+ // case IBM_TERSE = 0x12;
+
+ // /**
+ // * IBM LZ77 z Architecture
+ // */
+ // case IBM_LZ77 = 0x13;
+
+ // // 0x14: deprecated (use method 93 for zstd)
+
+ // /**
+ // * Zstandard (zstd) Compression
+ // */
+ // case ZSTD = 0x5d;
+
+ // /**
+ // * MP3 Compression
+ // */
+ // case MP3 = 0x5e;
+
+ // /**
+ // * XZ Compression
+ // */
+ // case XZ = 0x5f;
+
+ // /**
+ // * JPEG variant
+ // */
+ // case JPEG = 0x60;
+
+ // /**
+ // * WavPack compressed data
+ // */
+ // case WAV_PACK = 0x61;
+
+ // /**
+ // * PPMd version I, Rev 1
+ // */
+ // case PPMD_1_1 = 0x62;
+
+ // /**
+ // * AE-x encryption marker
+ // */
+ // case AE_X_ENCRYPTION = 0x63;
+}
diff --git a/vendor/maennchen/zipstream-php/src/DataDescriptor.php b/vendor/maennchen/zipstream-php/src/DataDescriptor.php
new file mode 100644
index 000000000..04146190d
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/DataDescriptor.php
@@ -0,0 +1,26 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+/**
+ * @internal
+ */
+abstract class DataDescriptor
+{
+ private const SIGNATURE = 0x08074b50;
+
+ public static function generate(
+ int $crc32UncompressedData,
+ int $compressedSize,
+ int $uncompressedSize,
+ ): string {
+ return PackField::pack(
+ new PackField(format: 'V', value: self::SIGNATURE),
+ new PackField(format: 'V', value: $crc32UncompressedData),
+ new PackField(format: 'V', value: $compressedSize),
+ new PackField(format: 'V', value: $uncompressedSize),
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/EndOfCentralDirectory.php b/vendor/maennchen/zipstream-php/src/EndOfCentralDirectory.php
new file mode 100644
index 000000000..4320addc3
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/EndOfCentralDirectory.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+/**
+ * @internal
+ */
+abstract class EndOfCentralDirectory
+{
+ private const SIGNATURE = 0x06054b50;
+
+ public static function generate(
+ int $numberOfThisDisk,
+ int $numberOfTheDiskWithCentralDirectoryStart,
+ int $numberOfCentralDirectoryEntriesOnThisDisk,
+ int $numberOfCentralDirectoryEntries,
+ int $sizeOfCentralDirectory,
+ int $centralDirectoryStartOffsetOnDisk,
+ string $zipFileComment,
+ ): string {
+ /** @psalm-suppress MixedArgument */
+ return PackField::pack(
+ new PackField(format: 'V', value: static::SIGNATURE),
+ new PackField(format: 'v', value: $numberOfThisDisk),
+ new PackField(format: 'v', value: $numberOfTheDiskWithCentralDirectoryStart),
+ new PackField(format: 'v', value: $numberOfCentralDirectoryEntriesOnThisDisk),
+ new PackField(format: 'v', value: $numberOfCentralDirectoryEntries),
+ new PackField(format: 'V', value: $sizeOfCentralDirectory),
+ new PackField(format: 'V', value: $centralDirectoryStartOffsetOnDisk),
+ new PackField(format: 'v', value: strlen($zipFileComment)),
+ ) . $zipFileComment;
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Exception.php b/vendor/maennchen/zipstream-php/src/Exception.php
new file mode 100644
index 000000000..2e81e307b
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception.php
@@ -0,0 +1,7 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+abstract class Exception extends \Exception {}
diff --git a/vendor/maennchen/zipstream-php/src/Exception/DosTimeOverflowException.php b/vendor/maennchen/zipstream-php/src/Exception/DosTimeOverflowException.php
new file mode 100644
index 000000000..b8d050808
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception/DosTimeOverflowException.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Exception;
+
+use DateTimeInterface;
+use ZipStream\Exception;
+
+/**
+ * This Exception gets invoked if a file wasn't found
+ */
+class DosTimeOverflowException extends Exception
+{
+ /**
+ * @internal
+ */
+ public function __construct(
+ public readonly DateTimeInterface $dateTime
+ ) {
+ parent::__construct('The date ' . $dateTime->format(DateTimeInterface::ATOM) . " can't be represented as DOS time / date.");
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Exception/FileNotFoundException.php b/vendor/maennchen/zipstream-php/src/Exception/FileNotFoundException.php
new file mode 100644
index 000000000..350a7bfe5
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception/FileNotFoundException.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Exception;
+
+use ZipStream\Exception;
+
+/**
+ * This Exception gets invoked if a file wasn't found
+ */
+class FileNotFoundException extends Exception
+{
+ /**
+ * @internal
+ */
+ public function __construct(
+ public readonly string $path
+ ) {
+ parent::__construct("The file with the path $path wasn't found.");
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Exception/FileNotReadableException.php b/vendor/maennchen/zipstream-php/src/Exception/FileNotReadableException.php
new file mode 100644
index 000000000..93d0c6c64
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception/FileNotReadableException.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Exception;
+
+use ZipStream\Exception;
+
+/**
+ * This Exception gets invoked if a file wasn't found
+ */
+class FileNotReadableException extends Exception
+{
+ /**
+ * @internal
+ */
+ public function __construct(
+ public readonly string $path
+ ) {
+ parent::__construct("The file with the path $path isn't readable.");
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Exception/FileSizeIncorrectException.php b/vendor/maennchen/zipstream-php/src/Exception/FileSizeIncorrectException.php
new file mode 100644
index 000000000..11f0b67b3
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception/FileSizeIncorrectException.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Exception;
+
+use ZipStream\Exception;
+
+/**
+ * This Exception gets invoked if a file is not as large as it was specified.
+ */
+class FileSizeIncorrectException extends Exception
+{
+ /**
+ * @internal
+ */
+ public function __construct(
+ public readonly int $expectedSize,
+ public readonly int $actualSize
+ ) {
+ parent::__construct("File is {$actualSize} instead of {$expectedSize} bytes large. Adjust `exactSize` parameter.");
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Exception/OverflowException.php b/vendor/maennchen/zipstream-php/src/Exception/OverflowException.php
new file mode 100644
index 000000000..09bdafb28
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception/OverflowException.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Exception;
+
+use ZipStream\Exception;
+
+/**
+ * This Exception gets invoked if a counter value exceeds storage size
+ */
+class OverflowException extends Exception
+{
+ /**
+ * @internal
+ */
+ public function __construct()
+ {
+ parent::__construct('File size exceeds limit of 32 bit integer. Please enable "zip64" option.');
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Exception/ResourceActionException.php b/vendor/maennchen/zipstream-php/src/Exception/ResourceActionException.php
new file mode 100644
index 000000000..cbd9b0bb9
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception/ResourceActionException.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Exception;
+
+use ZipStream\Exception;
+
+/**
+ * This Exception gets invoked if a resource like `fread` returns false
+ */
+class ResourceActionException extends Exception
+{
+ /**
+ * @var ?resource
+ */
+ public $resource;
+
+ /**
+ * @param resource $resource
+ */
+ public function __construct(
+ public readonly string $function,
+ $resource = null,
+ ) {
+ $this->resource = $resource;
+ parent::__construct('Function ' . $function . 'failed on resource.');
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php b/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php
new file mode 100644
index 000000000..717c1aafe
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception/SimulationFileUnknownException.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Exception;
+
+use ZipStream\Exception;
+
+/**
+ * This Exception gets invoked if a strict simulation is executed and the file
+ * information can't be determined without reading the entire file.
+ */
+class SimulationFileUnknownException extends Exception
+{
+ public function __construct()
+ {
+ parent::__construct('The details of the strict simulation file could not be determined without reading the entire file.');
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php b/vendor/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php
new file mode 100644
index 000000000..c1446735a
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception/StreamNotReadableException.php
@@ -0,0 +1,21 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Exception;
+
+use ZipStream\Exception;
+
+/**
+ * This Exception gets invoked if a stream can't be read.
+ */
+class StreamNotReadableException extends Exception
+{
+ /**
+ * @internal
+ */
+ public function __construct()
+ {
+ parent::__construct('The stream could not be read.');
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Exception/StreamNotSeekableException.php b/vendor/maennchen/zipstream-php/src/Exception/StreamNotSeekableException.php
new file mode 100644
index 000000000..606f11f14
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Exception/StreamNotSeekableException.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Exception;
+
+use ZipStream\Exception;
+
+/**
+ * This Exception gets invoked if a non seekable stream is
+ * provided and zero headers are disabled.
+ */
+class StreamNotSeekableException extends Exception
+{
+ /**
+ * @internal
+ */
+ public function __construct()
+ {
+ parent::__construct('enableZeroHeader must be enable to add non seekable streams');
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/File.php b/vendor/maennchen/zipstream-php/src/File.php
new file mode 100644
index 000000000..0462196e2
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/File.php
@@ -0,0 +1,420 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+use Closure;
+use DateTimeInterface;
+use DeflateContext;
+use RuntimeException;
+use ZipStream\Exception\FileSizeIncorrectException;
+use ZipStream\Exception\OverflowException;
+use ZipStream\Exception\ResourceActionException;
+use ZipStream\Exception\SimulationFileUnknownException;
+use ZipStream\Exception\StreamNotReadableException;
+use ZipStream\Exception\StreamNotSeekableException;
+
+/**
+ * @internal
+ */
+class File
+{
+ private const CHUNKED_READ_BLOCK_SIZE = 0x1000000;
+
+ private Version $version;
+
+ private int $compressedSize = 0;
+
+ private int $uncompressedSize = 0;
+
+ private int $crc = 0;
+
+ private int $generalPurposeBitFlag = 0;
+
+ private readonly string $fileName;
+
+ /**
+ * @var resource|null
+ */
+ private $stream;
+
+ /**
+ * @param Closure $dataCallback
+ * @psalm-param Closure(): resource $dataCallback
+ */
+ public function __construct(
+ string $fileName,
+ private readonly Closure $dataCallback,
+ private readonly OperationMode $operationMode,
+ private readonly int $startOffset,
+ private readonly CompressionMethod $compressionMethod,
+ private readonly string $comment,
+ private readonly DateTimeInterface $lastModificationDateTime,
+ private readonly int $deflateLevel,
+ private readonly ?int $maxSize,
+ private readonly ?int $exactSize,
+ private readonly bool $enableZip64,
+ private readonly bool $enableZeroHeader,
+ private readonly Closure $send,
+ private readonly Closure $recordSentBytes,
+ ) {
+ $this->fileName = self::filterFilename($fileName);
+ $this->checkEncoding();
+
+ if ($this->enableZeroHeader) {
+ $this->generalPurposeBitFlag |= GeneralPurposeBitFlag::ZERO_HEADER;
+ }
+
+ $this->version = $this->compressionMethod === CompressionMethod::DEFLATE ? Version::DEFLATE : Version::STORE;
+ }
+
+ public function cloneSimulationExecution(): self
+ {
+ return new self(
+ $this->fileName,
+ $this->dataCallback,
+ OperationMode::NORMAL,
+ $this->startOffset,
+ $this->compressionMethod,
+ $this->comment,
+ $this->lastModificationDateTime,
+ $this->deflateLevel,
+ $this->maxSize,
+ $this->exactSize,
+ $this->enableZip64,
+ $this->enableZeroHeader,
+ $this->send,
+ $this->recordSentBytes,
+ );
+ }
+
+ public function process(): string
+ {
+ $forecastSize = $this->forecastSize();
+
+ if ($this->enableZeroHeader) {
+ // No calculation required
+ } elseif ($this->isSimulation() && $forecastSize !== null) {
+ $this->uncompressedSize = $forecastSize;
+ $this->compressedSize = $forecastSize;
+ } else {
+ $this->readStream(send: false);
+ if (rewind($this->unpackStream()) === false) {
+ throw new ResourceActionException('rewind', $this->unpackStream());
+ }
+ }
+
+ $this->addFileHeader();
+
+ $detectedSize = $forecastSize ?? ($this->compressedSize > 0 ? $this->compressedSize : null);
+
+ if (
+ $this->isSimulation() &&
+ $detectedSize !== null
+ ) {
+ ($this->recordSentBytes)($detectedSize);
+ } else {
+ $this->readStream(send: true);
+ }
+
+ $this->addFileFooter();
+ return $this->getCdrFile();
+ }
+
+ /**
+ * @return resource
+ */
+ private function unpackStream()
+ {
+ if ($this->stream) {
+ return $this->stream;
+ }
+
+ if ($this->operationMode === OperationMode::SIMULATE_STRICT) {
+ throw new SimulationFileUnknownException();
+ }
+
+ $this->stream = ($this->dataCallback)();
+
+ if (!$this->enableZeroHeader && !stream_get_meta_data($this->stream)['seekable']) {
+ throw new StreamNotSeekableException();
+ }
+ if (!(
+ str_contains(stream_get_meta_data($this->stream)['mode'], 'r')
+ || str_contains(stream_get_meta_data($this->stream)['mode'], 'w+')
+ || str_contains(stream_get_meta_data($this->stream)['mode'], 'a+')
+ || str_contains(stream_get_meta_data($this->stream)['mode'], 'x+')
+ || str_contains(stream_get_meta_data($this->stream)['mode'], 'c+')
+ )) {
+ throw new StreamNotReadableException();
+ }
+
+ return $this->stream;
+ }
+
+ private function forecastSize(): ?int
+ {
+ if ($this->compressionMethod !== CompressionMethod::STORE) {
+ return null;
+ }
+ if ($this->exactSize !== null) {
+ return $this->exactSize;
+ }
+ $fstat = fstat($this->unpackStream());
+ if (!$fstat || !array_key_exists('size', $fstat) || $fstat['size'] < 1) {
+ return null;
+ }
+
+ if ($this->maxSize !== null && $this->maxSize < $fstat['size']) {
+ return $this->maxSize;
+ }
+
+ return $fstat['size'];
+ }
+
+ /**
+ * Create and send zip header for this file.
+ */
+ private function addFileHeader(): void
+ {
+ $forceEnableZip64 = $this->enableZeroHeader && $this->enableZip64;
+
+ $footer = $this->buildZip64ExtraBlock($forceEnableZip64);
+
+ $zip64Enabled = $footer !== '';
+
+ if ($zip64Enabled) {
+ $this->version = Version::ZIP64;
+ }
+
+ if ($this->generalPurposeBitFlag & GeneralPurposeBitFlag::EFS) {
+ // Put the tricky entry to
+ // force Linux unzip to lookup EFS flag.
+ $footer .= Zs\ExtendedInformationExtraField::generate();
+ }
+
+ $data = LocalFileHeader::generate(
+ versionNeededToExtract: $this->version->value,
+ generalPurposeBitFlag: $this->generalPurposeBitFlag,
+ compressionMethod: $this->compressionMethod,
+ lastModificationDateTime: $this->lastModificationDateTime,
+ crc32UncompressedData: $this->crc,
+ compressedSize: $zip64Enabled
+ ? 0xFFFFFFFF
+ : $this->compressedSize,
+ uncompressedSize: $zip64Enabled
+ ? 0xFFFFFFFF
+ : $this->uncompressedSize,
+ fileName: $this->fileName,
+ extraField: $footer,
+ );
+
+
+ ($this->send)($data);
+ }
+
+ /**
+ * Strip characters that are not legal in Windows filenames
+ * to prevent compatibility issues
+ */
+ private static function filterFilename(
+ /**
+ * Unprocessed filename
+ */
+ string $fileName
+ ): string {
+ // strip leading slashes from file name
+ // (fixes bug in windows archive viewer)
+ $fileName = ltrim($fileName, '/');
+
+ return str_replace(['\\', ':', '*', '?', '"', '<', '>', '|'], '_', $fileName);
+ }
+
+ private function checkEncoding(): void
+ {
+ // Sets Bit 11: Language encoding flag (EFS). If this bit is set,
+ // the filename and comment fields for this file
+ // MUST be encoded using UTF-8. (see APPENDIX D)
+ if (mb_check_encoding($this->fileName, 'UTF-8') &&
+ mb_check_encoding($this->comment, 'UTF-8')) {
+ $this->generalPurposeBitFlag |= GeneralPurposeBitFlag::EFS;
+ }
+ }
+
+ private function buildZip64ExtraBlock(bool $force = false): string
+ {
+ $outputZip64ExtraBlock = false;
+
+ $originalSize = null;
+ if ($force || $this->uncompressedSize > 0xFFFFFFFF) {
+ $outputZip64ExtraBlock = true;
+ $originalSize = $this->uncompressedSize;
+ }
+
+ $compressedSize = null;
+ if ($force || $this->compressedSize > 0xFFFFFFFF) {
+ $outputZip64ExtraBlock = true;
+ $compressedSize = $this->compressedSize;
+ }
+
+ // If this file will start over 4GB limit in ZIP file,
+ // CDR record will have to use Zip64 extension to describe offset
+ // to keep consistency we use the same value here
+ $relativeHeaderOffset = null;
+ if ($this->startOffset > 0xFFFFFFFF) {
+ $outputZip64ExtraBlock = true;
+ $relativeHeaderOffset = $this->startOffset;
+ }
+
+ if (!$outputZip64ExtraBlock) {
+ return '';
+ }
+
+ if (!$this->enableZip64) {
+ throw new OverflowException();
+ }
+
+ return Zip64\ExtendedInformationExtraField::generate(
+ originalSize: $originalSize,
+ compressedSize: $compressedSize,
+ relativeHeaderOffset: $relativeHeaderOffset,
+ diskStartNumber: null,
+ );
+ }
+
+ private function addFileFooter(): void
+ {
+ if (($this->compressedSize > 0xFFFFFFFF || $this->uncompressedSize > 0xFFFFFFFF) && $this->version !== Version::ZIP64) {
+ throw new OverflowException();
+ }
+
+ if (!$this->enableZeroHeader) {
+ return;
+ }
+
+ if ($this->version === Version::ZIP64) {
+ $footer = Zip64\DataDescriptor::generate(
+ crc32UncompressedData: $this->crc,
+ compressedSize: $this->compressedSize,
+ uncompressedSize: $this->uncompressedSize,
+ );
+ } else {
+ $footer = DataDescriptor::generate(
+ crc32UncompressedData: $this->crc,
+ compressedSize: $this->compressedSize,
+ uncompressedSize: $this->uncompressedSize,
+ );
+ }
+
+ ($this->send)($footer);
+ }
+
+ private function readStream(bool $send): void
+ {
+ $this->compressedSize = 0;
+ $this->uncompressedSize = 0;
+ $hash = hash_init('crc32b');
+
+ $deflate = $this->compressionInit();
+
+ while (
+ !feof($this->unpackStream()) &&
+ ($this->maxSize === null || $this->uncompressedSize < $this->maxSize) &&
+ ($this->exactSize === null || $this->uncompressedSize < $this->exactSize)
+ ) {
+ $readLength = min(
+ ($this->maxSize ?? PHP_INT_MAX) - $this->uncompressedSize,
+ ($this->exactSize ?? PHP_INT_MAX) - $this->uncompressedSize,
+ self::CHUNKED_READ_BLOCK_SIZE
+ );
+
+ $data = fread($this->unpackStream(), $readLength);
+
+ hash_update($hash, $data);
+
+ $this->uncompressedSize += strlen($data);
+
+ if ($deflate) {
+ $data = deflate_add(
+ $deflate,
+ $data,
+ feof($this->unpackStream()) ? ZLIB_FINISH : ZLIB_NO_FLUSH
+ );
+ }
+
+ $this->compressedSize += strlen($data);
+
+ if ($send) {
+ ($this->send)($data);
+ }
+ }
+
+ if ($this->exactSize !== null && $this->uncompressedSize !== $this->exactSize) {
+ throw new FileSizeIncorrectException(expectedSize: $this->exactSize, actualSize: $this->uncompressedSize);
+ }
+
+ $this->crc = hexdec(hash_final($hash));
+ }
+
+ private function compressionInit(): ?DeflateContext
+ {
+ switch ($this->compressionMethod) {
+ case CompressionMethod::STORE:
+ // Noting to do
+ return null;
+ case CompressionMethod::DEFLATE:
+ $deflateContext = deflate_init(
+ ZLIB_ENCODING_RAW,
+ ['level' => $this->deflateLevel]
+ );
+
+ if (!$deflateContext) {
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException("Can't initialize deflate context.");
+ // @codeCoverageIgnoreEnd
+ }
+
+ // False positive, resource is no longer returned from this function
+ return $deflateContext;
+ default:
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException('Unsupported Compression Method ' . print_r($this->compressionMethod, true));
+ // @codeCoverageIgnoreEnd
+ }
+ }
+
+ private function getCdrFile(): string
+ {
+ $footer = $this->buildZip64ExtraBlock();
+
+ return CentralDirectoryFileHeader::generate(
+ versionMadeBy: ZipStream::ZIP_VERSION_MADE_BY,
+ versionNeededToExtract: $this->version->value,
+ generalPurposeBitFlag: $this->generalPurposeBitFlag,
+ compressionMethod: $this->compressionMethod,
+ lastModificationDateTime: $this->lastModificationDateTime,
+ crc32: $this->crc,
+ compressedSize: $this->compressedSize > 0xFFFFFFFF
+ ? 0xFFFFFFFF
+ : $this->compressedSize,
+ uncompressedSize: $this->uncompressedSize > 0xFFFFFFFF
+ ? 0xFFFFFFFF
+ : $this->uncompressedSize,
+ fileName: $this->fileName,
+ extraField: $footer,
+ fileComment: $this->comment,
+ diskNumberStart: 0,
+ internalFileAttributes: 0,
+ externalFileAttributes: 32,
+ relativeOffsetOfLocalHeader: $this->startOffset > 0xFFFFFFFF
+ ? 0xFFFFFFFF
+ : $this->startOffset,
+ );
+ }
+
+ private function isSimulation(): bool
+ {
+ return $this->operationMode === OperationMode::SIMULATE_LAX || $this->operationMode === OperationMode::SIMULATE_STRICT;
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php b/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php
new file mode 100644
index 000000000..23a66d889
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/GeneralPurposeBitFlag.php
@@ -0,0 +1,89 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+/**
+ * @internal
+ */
+abstract class GeneralPurposeBitFlag
+{
+ /**
+ * If set, indicates that the file is encrypted.
+ */
+ public const ENCRYPTED = 1 << 0;
+
+ /**
+ * (For Methods 8 and 9 - Deflating)
+ * Normal (-en) compression option was used.
+ */
+ public const DEFLATE_COMPRESSION_NORMAL = 0 << 1;
+
+ /**
+ * (For Methods 8 and 9 - Deflating)
+ * Maximum (-exx/-ex) compression option was used.
+ */
+ public const DEFLATE_COMPRESSION_MAXIMUM = 1 << 1;
+
+ /**
+ * (For Methods 8 and 9 - Deflating)
+ * Fast (-ef) compression option was used.
+ */
+ public const DEFLATE_COMPRESSION_FAST = 10 << 1;
+
+ /**
+ * (For Methods 8 and 9 - Deflating)
+ * Super Fast (-es) compression option was used.
+ */
+ public const DEFLATE_COMPRESSION_SUPERFAST = 11 << 1;
+
+ /**
+ * If the compression method used was type 14,
+ * LZMA, then this bit, if set, indicates
+ * an end-of-stream (EOS) marker is used to
+ * mark the end of the compressed data stream.
+ * If clear, then an EOS marker is not present
+ * and the compressed data size must be known
+ * to extract.
+ */
+ public const LZMA_EOS = 1 << 1;
+
+ /**
+ * If this bit is set, the fields crc-32, compressed
+ * size and uncompressed size are set to zero in the
+ * local header. The correct values are put in the
+ * data descriptor immediately following the compressed
+ * data.
+ */
+ public const ZERO_HEADER = 1 << 3;
+
+ /**
+ * If this bit is set, this indicates that the file is
+ * compressed patched data.
+ */
+ public const COMPRESSED_PATCHED_DATA = 1 << 5;
+
+ /**
+ * Strong encryption. If this bit is set, you MUST
+ * set the version needed to extract value to at least
+ * 50 and you MUST also set bit 0. If AES encryption
+ * is used, the version needed to extract value MUST
+ * be at least 51.
+ */
+ public const STRONG_ENCRYPTION = 1 << 6;
+
+ /**
+ * Language encoding flag (EFS). If this bit is set,
+ * the filename and comment fields for this file
+ * MUST be encoded using UTF-8.
+ */
+ public const EFS = 1 << 11;
+
+ /**
+ * Set when encrypting the Central Directory to indicate
+ * selected data values in the Local Header are masked to
+ * hide their actual values.
+ */
+ public const ENCRYPT_CENTRAL_DIRECTORY = 1 << 13;
+}
diff --git a/vendor/maennchen/zipstream-php/src/LocalFileHeader.php b/vendor/maennchen/zipstream-php/src/LocalFileHeader.php
new file mode 100644
index 000000000..e08b65610
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/LocalFileHeader.php
@@ -0,0 +1,40 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+use DateTimeInterface;
+
+/**
+ * @internal
+ */
+abstract class LocalFileHeader
+{
+ private const SIGNATURE = 0x04034b50;
+
+ public static function generate(
+ int $versionNeededToExtract,
+ int $generalPurposeBitFlag,
+ CompressionMethod $compressionMethod,
+ DateTimeInterface $lastModificationDateTime,
+ int $crc32UncompressedData,
+ int $compressedSize,
+ int $uncompressedSize,
+ string $fileName,
+ string $extraField,
+ ): string {
+ return PackField::pack(
+ new PackField(format: 'V', value: self::SIGNATURE),
+ new PackField(format: 'v', value: $versionNeededToExtract),
+ new PackField(format: 'v', value: $generalPurposeBitFlag),
+ new PackField(format: 'v', value: $compressionMethod->value),
+ new PackField(format: 'V', value: Time::dateTimeToDosTime($lastModificationDateTime)),
+ new PackField(format: 'V', value: $crc32UncompressedData),
+ new PackField(format: 'V', value: $compressedSize),
+ new PackField(format: 'V', value: $uncompressedSize),
+ new PackField(format: 'v', value: strlen($fileName)),
+ new PackField(format: 'v', value: strlen($extraField)),
+ ) . $fileName . $extraField;
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/OperationMode.php b/vendor/maennchen/zipstream-php/src/OperationMode.php
new file mode 100644
index 000000000..dd650f070
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/OperationMode.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+/**
+ * ZipStream execution operation modes
+ */
+enum OperationMode
+{
+ /**
+ * Stream file into output stream
+ */
+ case NORMAL;
+
+ /**
+ * Simulate the zip to figure out the resulting file size
+ *
+ * This only supports entries where the file size is known beforehand and
+ * deflation is disabled.
+ */
+ case SIMULATE_STRICT;
+
+ /**
+ * Simulate the zip to figure out the resulting file size
+ *
+ * If the file size is not known beforehand or deflation is enabled, the
+ * entry streams will be read and rewound.
+ *
+ * If the entry does not support rewinding either, you will not be able to
+ * use the same stream in a later operation mode like `NORMAL`.
+ */
+ case SIMULATE_LAX;
+}
diff --git a/vendor/maennchen/zipstream-php/src/PackField.php b/vendor/maennchen/zipstream-php/src/PackField.php
new file mode 100644
index 000000000..892b4009a
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/PackField.php
@@ -0,0 +1,56 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+use RuntimeException;
+
+/**
+ * @internal
+ * TODO: Make class readonly when requiring PHP 8.2 exclusively
+ */
+class PackField
+{
+ public const MAX_V = 0xFFFFFFFF;
+
+ public const MAX_v = 0xFFFF;
+
+ public function __construct(
+ public readonly string $format,
+ public readonly int|string $value
+ ) {}
+
+ /**
+ * Create a format string and argument list for pack(), then call
+ * pack() and return the result.
+ */
+ public static function pack(self ...$fields): string
+ {
+ $fmt = array_reduce($fields, function (string $acc, self $field) {
+ return $acc . $field->format;
+ }, '');
+
+ $args = array_map(function (self $field) {
+ switch ($field->format) {
+ case 'V':
+ if ($field->value > self::MAX_V) {
+ throw new RuntimeException(print_r($field->value, true) . ' is larger than 32 bits');
+ }
+ break;
+ case 'v':
+ if ($field->value > self::MAX_v) {
+ throw new RuntimeException(print_r($field->value, true) . ' is larger than 16 bits');
+ }
+ break;
+ case 'P': break;
+ default:
+ break;
+ }
+
+ return $field->value;
+ }, $fields);
+
+ return pack($fmt, ...$args);
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Time.php b/vendor/maennchen/zipstream-php/src/Time.php
new file mode 100644
index 000000000..1b4121ca9
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Time.php
@@ -0,0 +1,39 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+use DateInterval;
+use DateTimeImmutable;
+use DateTimeInterface;
+use ZipStream\Exception\DosTimeOverflowException;
+
+/**
+ * @internal
+ */
+abstract class Time
+{
+ private const DOS_MINIMUM_DATE = '1980-01-01 00:00:00Z';
+
+ public static function dateTimeToDosTime(DateTimeInterface $dateTime): int
+ {
+ $dosMinimumDate = new DateTimeImmutable(self::DOS_MINIMUM_DATE);
+
+ if ($dateTime->getTimestamp() < $dosMinimumDate->getTimestamp()) {
+ throw new DosTimeOverflowException(dateTime: $dateTime);
+ }
+
+ $dateTime = DateTimeImmutable::createFromInterface($dateTime)->sub(new DateInterval('P1980Y'));
+
+ [$year, $month, $day, $hour, $minute, $second] = explode(' ', $dateTime->format('Y n j G i s'));
+
+ return
+ ((int) $year << 25) |
+ ((int) $month << 21) |
+ ((int) $day << 16) |
+ ((int) $hour << 11) |
+ ((int) $minute << 5) |
+ ((int) $second >> 1);
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Version.php b/vendor/maennchen/zipstream-php/src/Version.php
new file mode 100644
index 000000000..c014f8a10
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Version.php
@@ -0,0 +1,12 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+enum Version: int
+{
+ case STORE = 0x000A; // 1.00
+ case DEFLATE = 0x0014; // 2.00
+ case ZIP64 = 0x002D; // 4.50
+}
diff --git a/vendor/maennchen/zipstream-php/src/Zip64/DataDescriptor.php b/vendor/maennchen/zipstream-php/src/Zip64/DataDescriptor.php
new file mode 100644
index 000000000..041c5579d
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Zip64/DataDescriptor.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Zip64;
+
+use ZipStream\PackField;
+
+/**
+ * @internal
+ */
+abstract class DataDescriptor
+{
+ private const SIGNATURE = 0x08074b50;
+
+ public static function generate(
+ int $crc32UncompressedData,
+ int $compressedSize,
+ int $uncompressedSize,
+ ): string {
+ return PackField::pack(
+ new PackField(format: 'V', value: self::SIGNATURE),
+ new PackField(format: 'V', value: $crc32UncompressedData),
+ new PackField(format: 'P', value: $compressedSize),
+ new PackField(format: 'P', value: $uncompressedSize),
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectory.php b/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectory.php
new file mode 100644
index 000000000..08588e49c
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectory.php
@@ -0,0 +1,43 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Zip64;
+
+use ZipStream\PackField;
+
+/**
+ * @internal
+ */
+abstract class EndOfCentralDirectory
+{
+ private const SIGNATURE = 0x06064b50;
+
+ public static function generate(
+ int $versionMadeBy,
+ int $versionNeededToExtract,
+ int $numberOfThisDisk,
+ int $numberOfTheDiskWithCentralDirectoryStart,
+ int $numberOfCentralDirectoryEntriesOnThisDisk,
+ int $numberOfCentralDirectoryEntries,
+ int $sizeOfCentralDirectory,
+ int $centralDirectoryStartOffsetOnDisk,
+ string $extensibleDataSector,
+ ): string {
+ $recordSize = 44 + strlen($extensibleDataSector); // (length of block - 12) = 44;
+
+ /** @psalm-suppress MixedArgument */
+ return PackField::pack(
+ new PackField(format: 'V', value: static::SIGNATURE),
+ new PackField(format: 'P', value: $recordSize),
+ new PackField(format: 'v', value: $versionMadeBy),
+ new PackField(format: 'v', value: $versionNeededToExtract),
+ new PackField(format: 'V', value: $numberOfThisDisk),
+ new PackField(format: 'V', value: $numberOfTheDiskWithCentralDirectoryStart),
+ new PackField(format: 'P', value: $numberOfCentralDirectoryEntriesOnThisDisk),
+ new PackField(format: 'P', value: $numberOfCentralDirectoryEntries),
+ new PackField(format: 'P', value: $sizeOfCentralDirectory),
+ new PackField(format: 'P', value: $centralDirectoryStartOffsetOnDisk),
+ ) . $extensibleDataSector;
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectoryLocator.php b/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectoryLocator.php
new file mode 100644
index 000000000..ef431c347
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Zip64/EndOfCentralDirectoryLocator.php
@@ -0,0 +1,29 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Zip64;
+
+use ZipStream\PackField;
+
+/**
+ * @internal
+ */
+abstract class EndOfCentralDirectoryLocator
+{
+ private const SIGNATURE = 0x07064b50;
+
+ public static function generate(
+ int $numberOfTheDiskWithZip64CentralDirectoryStart,
+ int $zip64centralDirectoryStartOffsetOnDisk,
+ int $totalNumberOfDisks,
+ ): string {
+ /** @psalm-suppress MixedArgument */
+ return PackField::pack(
+ new PackField(format: 'V', value: static::SIGNATURE),
+ new PackField(format: 'V', value: $numberOfTheDiskWithZip64CentralDirectoryStart),
+ new PackField(format: 'P', value: $zip64centralDirectoryStartOffsetOnDisk),
+ new PackField(format: 'V', value: $totalNumberOfDisks),
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Zip64/ExtendedInformationExtraField.php b/vendor/maennchen/zipstream-php/src/Zip64/ExtendedInformationExtraField.php
new file mode 100644
index 000000000..aaac51c83
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Zip64/ExtendedInformationExtraField.php
@@ -0,0 +1,45 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Zip64;
+
+use ZipStream\PackField;
+
+/**
+ * @internal
+ */
+abstract class ExtendedInformationExtraField
+{
+ private const TAG = 0x0001;
+
+ public static function generate(
+ ?int $originalSize = null,
+ ?int $compressedSize = null,
+ ?int $relativeHeaderOffset = null,
+ ?int $diskStartNumber = null,
+ ): string {
+ return PackField::pack(
+ new PackField(format: 'v', value: self::TAG),
+ new PackField(
+ format: 'v',
+ value: ($originalSize === null ? 0 : 8) +
+ ($compressedSize === null ? 0 : 8) +
+ ($relativeHeaderOffset === null ? 0 : 8) +
+ ($diskStartNumber === null ? 0 : 4)
+ ),
+ ...($originalSize === null ? [] : [
+ new PackField(format: 'P', value: $originalSize),
+ ]),
+ ...($compressedSize === null ? [] : [
+ new PackField(format: 'P', value: $compressedSize),
+ ]),
+ ...($relativeHeaderOffset === null ? [] : [
+ new PackField(format: 'P', value: $relativeHeaderOffset),
+ ]),
+ ...($diskStartNumber === null ? [] : [
+ new PackField(format: 'V', value: $diskStartNumber),
+ ]),
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/ZipStream.php b/vendor/maennchen/zipstream-php/src/ZipStream.php
new file mode 100644
index 000000000..3f4f481a8
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/ZipStream.php
@@ -0,0 +1,865 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream;
+
+use Closure;
+use DateTimeImmutable;
+use DateTimeInterface;
+use GuzzleHttp\Psr7\StreamWrapper;
+use Psr\Http\Message\StreamInterface;
+use RuntimeException;
+use ZipStream\Exception\FileNotFoundException;
+use ZipStream\Exception\FileNotReadableException;
+use ZipStream\Exception\OverflowException;
+use ZipStream\Exception\ResourceActionException;
+
+/**
+ * Streamed, dynamically generated zip archives.
+ *
+ * ## Usage
+ *
+ * Streaming zip archives is a simple, three-step process:
+ *
+ * 1. Create the zip stream:
+ *
+ * ```php
+ * $zip = new ZipStream(outputName: 'example.zip');
+ * ```
+ *
+ * 2. Add one or more files to the archive:
+ *
+ * ```php
+ * // add first file
+ * $zip->addFile(fileName: 'world.txt', data: 'Hello World');
+ *
+ * // add second file
+ * $zip->addFile(fileName: 'moon.txt', data: 'Hello Moon');
+ * ```
+ *
+ * 3. Finish the zip stream:
+ *
+ * ```php
+ * $zip->finish();
+ * ```
+ *
+ * You can also add an archive comment, add comments to individual files,
+ * and adjust the timestamp of files. See the API documentation for each
+ * method below for additional information.
+ *
+ * ## Example
+ *
+ * ```php
+ * // create a new zip stream object
+ * $zip = new ZipStream(outputName: 'some_files.zip');
+ *
+ * // list of local files
+ * $files = array('foo.txt', 'bar.jpg');
+ *
+ * // read and add each file to the archive
+ * foreach ($files as $path)
+ * $zip->addFileFromPath(fileName: $path, $path);
+ *
+ * // write archive footer to stream
+ * $zip->finish();
+ * ```
+ */
+class ZipStream
+{
+ /**
+ * This number corresponds to the ZIP version/OS used (2 bytes)
+ * From: https://www.iana.org/assignments/media-types/application/zip
+ * The upper byte (leftmost one) indicates the host system (OS) for the
+ * file. Software can use this information to determine
+ * the line record format for text files etc. The current
+ * mappings are:
+ *
+ * 0 - MS-DOS and OS/2 (F.A.T. file systems)
+ * 1 - Amiga 2 - VAX/VMS
+ * 3 - *nix 4 - VM/CMS
+ * 5 - Atari ST 6 - OS/2 H.P.F.S.
+ * 7 - Macintosh 8 - Z-System
+ * 9 - CP/M 10 thru 255 - unused
+ *
+ * The lower byte (rightmost one) indicates the version number of the
+ * software used to encode the file. The value/10
+ * indicates the major version number, and the value
+ * mod 10 is the minor version number.
+ * Here we are using 6 for the OS, indicating OS/2 H.P.F.S.
+ * to prevent file permissions issues upon extract (see #84)
+ * 0x603 is 00000110 00000011 in binary, so 6 and 3
+ *
+ * @internal
+ */
+ public const ZIP_VERSION_MADE_BY = 0x603;
+
+ private bool $ready = true;
+
+ private int $offset = 0;
+
+ /**
+ * @var string[]
+ */
+ private array $centralDirectoryRecords = [];
+
+ /**
+ * @var resource
+ */
+ private $outputStream;
+
+ private readonly Closure $httpHeaderCallback;
+
+ /**
+ * @var File[]
+ */
+ private array $recordedSimulation = [];
+
+ /**
+ * Create a new ZipStream object.
+ *
+ * ##### Examples
+ *
+ * ```php
+ * // create a new zip file named 'foo.zip'
+ * $zip = new ZipStream(outputName: 'foo.zip');
+ *
+ * // create a new zip file named 'bar.zip' with a comment
+ * $zip = new ZipStream(
+ * outputName: 'bar.zip',
+ * comment: 'this is a comment for the zip file.',
+ * );
+ * ```
+ *
+ * @param OperationMode $operationMode
+ * The mode can be used to switch between `NORMAL` and `SIMULATION_*` modes.
+ * For details see the `OperationMode` documentation.
+ *
+ * Default to `NORMAL`.
+ *
+ * @param string $comment
+ * Archive Level Comment
+ *
+ * @param StreamInterface|resource|null $outputStream
+ * Override the output of the archive to a different target.
+ *
+ * By default the archive is sent to `STDOUT`.
+ *
+ * @param CompressionMethod $defaultCompressionMethod
+ * How to handle file compression. Legal values are
+ * `CompressionMethod::DEFLATE` (the default), or
+ * `CompressionMethod::STORE`. `STORE` sends the file raw and is
+ * significantly faster, while `DEFLATE` compresses the file and
+ * is much, much slower.
+ *
+ * @param int $defaultDeflateLevel
+ * Default deflation level. Only relevant if `compressionMethod`
+ * is `DEFLATE`.
+ *
+ * See details of [`deflate_init`](https://www.php.net/manual/en/function.deflate-init.php#refsect1-function.deflate-init-parameters)
+ *
+ * @param bool $enableZip64
+ * Enable Zip64 extension, supporting very large
+ * archives (any size > 4 GB or file count > 64k)
+ *
+ * @param bool $defaultEnableZeroHeader
+ * Enable streaming files with single read.
+ *
+ * When the zero header is set, the file is streamed into the output
+ * and the size & checksum are added at the end of the file. This is the
+ * fastest method and uses the least memory. Unfortunately not all
+ * ZIP clients fully support this and can lead to clients reporting
+ * the generated ZIP files as corrupted in combination with other
+ * circumstances. (Zip64 enabled, using UTF8 in comments / names etc.)
+ *
+ * When the zero header is not set, the length & checksum need to be
+ * defined before the file is actually added. To prevent loading all
+ * the data into memory, the data has to be read twice. If the data
+ * which is added is not seekable, this call will fail.
+ *
+ * @param bool $sendHttpHeaders
+ * Boolean indicating whether or not to send
+ * the HTTP headers for this file.
+ *
+ * @param ?Closure $httpHeaderCallback
+ * The method called to send HTTP headers
+ *
+ * @param string|null $outputName
+ * The name of the created archive.
+ *
+ * Only relevant if `$sendHttpHeaders = true`.
+ *
+ * @param string $contentDisposition
+ * HTTP Content-Disposition
+ *
+ * Only relevant if `sendHttpHeaders = true`.
+ *
+ * @param string $contentType
+ * HTTP Content Type
+ *
+ * Only relevant if `sendHttpHeaders = true`.
+ *
+ * @param bool $flushOutput
+ * Enable flush after every write to output stream.
+ *
+ * @return self
+ */
+ public function __construct(
+ private OperationMode $operationMode = OperationMode::NORMAL,
+ private readonly string $comment = '',
+ $outputStream = null,
+ private readonly CompressionMethod $defaultCompressionMethod = CompressionMethod::DEFLATE,
+ private readonly int $defaultDeflateLevel = 6,
+ private readonly bool $enableZip64 = true,
+ private readonly bool $defaultEnableZeroHeader = true,
+ private bool $sendHttpHeaders = true,
+ ?Closure $httpHeaderCallback = null,
+ private readonly ?string $outputName = null,
+ private readonly string $contentDisposition = 'attachment',
+ private readonly string $contentType = 'application/x-zip',
+ private bool $flushOutput = false,
+ ) {
+ $this->outputStream = self::normalizeStream($outputStream);
+ $this->httpHeaderCallback = $httpHeaderCallback ?? header(...);
+ }
+
+ /**
+ * Add a file to the archive.
+ *
+ * ##### File Options
+ *
+ * See {@see addFileFromPsr7Stream()}
+ *
+ * ##### Examples
+ *
+ * ```php
+ * // add a file named 'world.txt'
+ * $zip->addFile(fileName: 'world.txt', data: 'Hello World!');
+ *
+ * // add a file named 'bar.jpg' with a comment and a last-modified
+ * // time of two hours ago
+ * $zip->addFile(
+ * fileName: 'bar.jpg',
+ * data: $data,
+ * comment: 'this is a comment about bar.jpg',
+ * lastModificationDateTime: new DateTime('2 hours ago'),
+ * );
+ * ```
+ *
+ * @param string $data
+ *
+ * contents of file
+ */
+ public function addFile(
+ string $fileName,
+ string $data,
+ string $comment = '',
+ ?CompressionMethod $compressionMethod = null,
+ ?int $deflateLevel = null,
+ ?DateTimeInterface $lastModificationDateTime = null,
+ ?int $maxSize = null,
+ ?int $exactSize = null,
+ ?bool $enableZeroHeader = null,
+ ): void {
+ $this->addFileFromCallback(
+ fileName: $fileName,
+ callback: fn() => $data,
+ comment: $comment,
+ compressionMethod: $compressionMethod,
+ deflateLevel: $deflateLevel,
+ lastModificationDateTime: $lastModificationDateTime,
+ maxSize: $maxSize,
+ exactSize: $exactSize,
+ enableZeroHeader: $enableZeroHeader,
+ );
+ }
+
+ /**
+ * Add a file at path to the archive.
+ *
+ * ##### File Options
+ *
+ * See {@see addFileFromPsr7Stream()}
+ *
+ * ###### Examples
+ *
+ * ```php
+ * // add a file named 'foo.txt' from the local file '/tmp/foo.txt'
+ * $zip->addFileFromPath(
+ * fileName: 'foo.txt',
+ * path: '/tmp/foo.txt',
+ * );
+ *
+ * // add a file named 'bigfile.rar' from the local file
+ * // '/usr/share/bigfile.rar' with a comment and a last-modified
+ * // time of two hours ago
+ * $zip->addFileFromPath(
+ * fileName: 'bigfile.rar',
+ * path: '/usr/share/bigfile.rar',
+ * comment: 'this is a comment about bigfile.rar',
+ * lastModificationDateTime: new DateTime('2 hours ago'),
+ * );
+ * ```
+ *
+ * @throws \ZipStream\Exception\FileNotFoundException
+ * @throws \ZipStream\Exception\FileNotReadableException
+ */
+ public function addFileFromPath(
+ /**
+ * name of file in archive (including directory path).
+ */
+ string $fileName,
+
+ /**
+ * path to file on disk (note: paths should be encoded using
+ * UNIX-style forward slashes -- e.g '/path/to/some/file').
+ */
+ string $path,
+ string $comment = '',
+ ?CompressionMethod $compressionMethod = null,
+ ?int $deflateLevel = null,
+ ?DateTimeInterface $lastModificationDateTime = null,
+ ?int $maxSize = null,
+ ?int $exactSize = null,
+ ?bool $enableZeroHeader = null,
+ ): void {
+ if (!is_readable($path)) {
+ if (!file_exists($path)) {
+ throw new FileNotFoundException($path);
+ }
+ throw new FileNotReadableException($path);
+ }
+
+ $fileTime = filemtime($path);
+ if ($fileTime !== false) {
+ $lastModificationDateTime ??= (new DateTimeImmutable())->setTimestamp($fileTime);
+ }
+
+ $this->addFileFromCallback(
+ fileName: $fileName,
+ callback: function () use ($path) {
+
+ $stream = fopen($path, 'rb');
+
+ if (!$stream) {
+ // @codeCoverageIgnoreStart
+ throw new ResourceActionException('fopen');
+ // @codeCoverageIgnoreEnd
+ }
+
+ return $stream;
+ },
+ comment: $comment,
+ compressionMethod: $compressionMethod,
+ deflateLevel: $deflateLevel,
+ lastModificationDateTime: $lastModificationDateTime,
+ maxSize: $maxSize,
+ exactSize: $exactSize,
+ enableZeroHeader: $enableZeroHeader,
+ );
+ }
+
+ /**
+ * Add an open stream (resource) to the archive.
+ *
+ * ##### File Options
+ *
+ * See {@see addFileFromPsr7Stream()}
+ *
+ * ##### Examples
+ *
+ * ```php
+ * // create a temporary file stream and write text to it
+ * $filePointer = tmpfile();
+ * fwrite($filePointer, 'The quick brown fox jumped over the lazy dog.');
+ *
+ * // add a file named 'streamfile.txt' from the content of the stream
+ * $archive->addFileFromStream(
+ * fileName: 'streamfile.txt',
+ * stream: $filePointer,
+ * );
+ * ```
+ *
+ * @param resource $stream contents of file as a stream resource
+ */
+ public function addFileFromStream(
+ string $fileName,
+ $stream,
+ string $comment = '',
+ ?CompressionMethod $compressionMethod = null,
+ ?int $deflateLevel = null,
+ ?DateTimeInterface $lastModificationDateTime = null,
+ ?int $maxSize = null,
+ ?int $exactSize = null,
+ ?bool $enableZeroHeader = null,
+ ): void {
+ $this->addFileFromCallback(
+ fileName: $fileName,
+ callback: fn() => $stream,
+ comment: $comment,
+ compressionMethod: $compressionMethod,
+ deflateLevel: $deflateLevel,
+ lastModificationDateTime: $lastModificationDateTime,
+ maxSize: $maxSize,
+ exactSize: $exactSize,
+ enableZeroHeader: $enableZeroHeader,
+ );
+ }
+
+ /**
+ * Add an open stream to the archive.
+ *
+ * ##### Examples
+ *
+ * ```php
+ * $stream = $response->getBody();
+ * // add a file named 'streamfile.txt' from the content of the stream
+ * $archive->addFileFromPsr7Stream(
+ * fileName: 'streamfile.txt',
+ * stream: $stream,
+ * );
+ * ```
+ *
+ * @param string $fileName
+ * path of file in archive (including directory)
+ *
+ * @param StreamInterface $stream
+ * contents of file as a stream resource
+ *
+ * @param string $comment
+ * ZIP comment for this file
+ *
+ * @param ?CompressionMethod $compressionMethod
+ * Override `defaultCompressionMethod`
+ *
+ * See {@see __construct()}
+ *
+ * @param ?int $deflateLevel
+ * Override `defaultDeflateLevel`
+ *
+ * See {@see __construct()}
+ *
+ * @param ?DateTimeInterface $lastModificationDateTime
+ * Set last modification time of file.
+ *
+ * Default: `now`
+ *
+ * @param ?int $maxSize
+ * Only read `maxSize` bytes from file.
+ *
+ * The file is considered done when either reaching `EOF`
+ * or the `maxSize`.
+ *
+ * @param ?int $exactSize
+ * Read exactly `exactSize` bytes from file.
+ * If `EOF` is reached before reading `exactSize` bytes, an error will be
+ * thrown. The parameter allows for faster size calculations if the `stream`
+ * does not support `fstat` size or is slow and otherwise known beforehand.
+ *
+ * @param ?bool $enableZeroHeader
+ * Override `defaultEnableZeroHeader`
+ *
+ * See {@see __construct()}
+ */
+ public function addFileFromPsr7Stream(
+ string $fileName,
+ StreamInterface $stream,
+ string $comment = '',
+ ?CompressionMethod $compressionMethod = null,
+ ?int $deflateLevel = null,
+ ?DateTimeInterface $lastModificationDateTime = null,
+ ?int $maxSize = null,
+ ?int $exactSize = null,
+ ?bool $enableZeroHeader = null,
+ ): void {
+ $this->addFileFromCallback(
+ fileName: $fileName,
+ callback: fn() => $stream,
+ comment: $comment,
+ compressionMethod: $compressionMethod,
+ deflateLevel: $deflateLevel,
+ lastModificationDateTime: $lastModificationDateTime,
+ maxSize: $maxSize,
+ exactSize: $exactSize,
+ enableZeroHeader: $enableZeroHeader,
+ );
+ }
+
+ /**
+ * Add a file based on a callback.
+ *
+ * This is useful when you want to simulate a lot of files without keeping
+ * all of the file handles open at the same time.
+ *
+ * ##### Examples
+ *
+ * ```php
+ * foreach($files as $name => $size) {
+ * $archive->addFileFromCallback(
+ * fileName: 'streamfile.txt',
+ * exactSize: $size,
+ * callback: function() use($name): Psr\Http\Message\StreamInterface {
+ * $response = download($name);
+ * return $response->getBody();
+ * }
+ * );
+ * }
+ * ```
+ *
+ * @param string $fileName
+ * path of file in archive (including directory)
+ *
+ * @param Closure $callback
+ * @psalm-param Closure(): (resource|StreamInterface|string) $callback
+ * A callback to get the file contents in the shape of a PHP stream,
+ * a Psr StreamInterface implementation, or a string.
+ *
+ * @param string $comment
+ * ZIP comment for this file
+ *
+ * @param ?CompressionMethod $compressionMethod
+ * Override `defaultCompressionMethod`
+ *
+ * See {@see __construct()}
+ *
+ * @param ?int $deflateLevel
+ * Override `defaultDeflateLevel`
+ *
+ * See {@see __construct()}
+ *
+ * @param ?DateTimeInterface $lastModificationDateTime
+ * Set last modification time of file.
+ *
+ * Default: `now`
+ *
+ * @param ?int $maxSize
+ * Only read `maxSize` bytes from file.
+ *
+ * The file is considered done when either reaching `EOF`
+ * or the `maxSize`.
+ *
+ * @param ?int $exactSize
+ * Read exactly `exactSize` bytes from file.
+ * If `EOF` is reached before reading `exactSize` bytes, an error will be
+ * thrown. The parameter allows for faster size calculations if the `stream`
+ * does not support `fstat` size or is slow and otherwise known beforehand.
+ *
+ * @param ?bool $enableZeroHeader
+ * Override `defaultEnableZeroHeader`
+ *
+ * See {@see __construct()}
+ */
+ public function addFileFromCallback(
+ string $fileName,
+ Closure $callback,
+ string $comment = '',
+ ?CompressionMethod $compressionMethod = null,
+ ?int $deflateLevel = null,
+ ?DateTimeInterface $lastModificationDateTime = null,
+ ?int $maxSize = null,
+ ?int $exactSize = null,
+ ?bool $enableZeroHeader = null,
+ ): void {
+ $file = new File(
+ dataCallback: function () use ($callback, $maxSize) {
+ $data = $callback();
+
+ if (is_resource($data)) {
+ return $data;
+ }
+
+ if ($data instanceof StreamInterface) {
+ return StreamWrapper::getResource($data);
+ }
+
+
+ $stream = fopen('php://memory', 'rw+');
+ if ($stream === false) {
+ // @codeCoverageIgnoreStart
+ throw new ResourceActionException('fopen');
+ // @codeCoverageIgnoreEnd
+ }
+ if ($maxSize !== null && fwrite($stream, $data, $maxSize) === false) {
+ // @codeCoverageIgnoreStart
+ throw new ResourceActionException('fwrite', $stream);
+ // @codeCoverageIgnoreEnd
+ } elseif (fwrite($stream, $data) === false) {
+ // @codeCoverageIgnoreStart
+ throw new ResourceActionException('fwrite', $stream);
+ // @codeCoverageIgnoreEnd
+ }
+ if (rewind($stream) === false) {
+ // @codeCoverageIgnoreStart
+ throw new ResourceActionException('rewind', $stream);
+ // @codeCoverageIgnoreEnd
+ }
+
+ return $stream;
+
+ },
+ send: $this->send(...),
+ recordSentBytes: $this->recordSentBytes(...),
+ operationMode: $this->operationMode,
+ fileName: $fileName,
+ startOffset: $this->offset,
+ compressionMethod: $compressionMethod ?? $this->defaultCompressionMethod,
+ comment: $comment,
+ deflateLevel: $deflateLevel ?? $this->defaultDeflateLevel,
+ lastModificationDateTime: $lastModificationDateTime ?? new DateTimeImmutable(),
+ maxSize: $maxSize,
+ exactSize: $exactSize,
+ enableZip64: $this->enableZip64,
+ enableZeroHeader: $enableZeroHeader ?? $this->defaultEnableZeroHeader,
+ );
+
+ if ($this->operationMode !== OperationMode::NORMAL) {
+ $this->recordedSimulation[] = $file;
+ }
+
+ $this->centralDirectoryRecords[] = $file->process();
+ }
+
+ /**
+ * Add a directory to the archive.
+ *
+ * ##### File Options
+ *
+ * See {@see addFileFromPsr7Stream()}
+ *
+ * ##### Examples
+ *
+ * ```php
+ * // add a directory named 'world/'
+ * $zip->addDirectory(fileName: 'world/');
+ * ```
+ */
+ public function addDirectory(
+ string $fileName,
+ string $comment = '',
+ ?DateTimeInterface $lastModificationDateTime = null,
+ ): void {
+ if (!str_ends_with($fileName, '/')) {
+ $fileName .= '/';
+ }
+
+ $this->addFile(
+ fileName: $fileName,
+ data: '',
+ comment: $comment,
+ compressionMethod: CompressionMethod::STORE,
+ deflateLevel: null,
+ lastModificationDateTime: $lastModificationDateTime,
+ maxSize: 0,
+ exactSize: 0,
+ enableZeroHeader: false,
+ );
+ }
+
+ /**
+ * Executes a previously calculated simulation.
+ *
+ * ##### Example
+ *
+ * ```php
+ * $zip = new ZipStream(
+ * outputName: 'foo.zip',
+ * operationMode: OperationMode::SIMULATE_STRICT,
+ * );
+ *
+ * $zip->addFile('test.txt', 'Hello World');
+ *
+ * $size = $zip->finish();
+ *
+ * header('Content-Length: '. $size);
+ *
+ * $zip->executeSimulation();
+ * ```
+ */
+ public function executeSimulation(): void
+ {
+ if ($this->operationMode !== OperationMode::NORMAL) {
+ throw new RuntimeException('Zip simulation is not finished.');
+ }
+
+ foreach ($this->recordedSimulation as $file) {
+ $this->centralDirectoryRecords[] = $file->cloneSimulationExecution()->process();
+ }
+
+ $this->finish();
+ }
+
+ /**
+ * Write zip footer to stream.
+ *
+ * The clase is left in an unusable state after `finish`.
+ *
+ * ##### Example
+ *
+ * ```php
+ * // write footer to stream
+ * $zip->finish();
+ * ```
+ */
+ public function finish(): int
+ {
+ $centralDirectoryStartOffsetOnDisk = $this->offset;
+ $sizeOfCentralDirectory = 0;
+
+ // add trailing cdr file records
+ foreach ($this->centralDirectoryRecords as $centralDirectoryRecord) {
+ $this->send($centralDirectoryRecord);
+ $sizeOfCentralDirectory += strlen($centralDirectoryRecord);
+ }
+
+ // Add 64bit headers (if applicable)
+ if (count($this->centralDirectoryRecords) >= 0xFFFF ||
+ $centralDirectoryStartOffsetOnDisk > 0xFFFFFFFF ||
+ $sizeOfCentralDirectory > 0xFFFFFFFF) {
+ if (!$this->enableZip64) {
+ throw new OverflowException();
+ }
+
+ $this->send(Zip64\EndOfCentralDirectory::generate(
+ versionMadeBy: self::ZIP_VERSION_MADE_BY,
+ versionNeededToExtract: Version::ZIP64->value,
+ numberOfThisDisk: 0,
+ numberOfTheDiskWithCentralDirectoryStart: 0,
+ numberOfCentralDirectoryEntriesOnThisDisk: count($this->centralDirectoryRecords),
+ numberOfCentralDirectoryEntries: count($this->centralDirectoryRecords),
+ sizeOfCentralDirectory: $sizeOfCentralDirectory,
+ centralDirectoryStartOffsetOnDisk: $centralDirectoryStartOffsetOnDisk,
+ extensibleDataSector: '',
+ ));
+
+ $this->send(Zip64\EndOfCentralDirectoryLocator::generate(
+ numberOfTheDiskWithZip64CentralDirectoryStart: 0x00,
+ zip64centralDirectoryStartOffsetOnDisk: $centralDirectoryStartOffsetOnDisk + $sizeOfCentralDirectory,
+ totalNumberOfDisks: 1,
+ ));
+ }
+
+ // add trailing cdr eof record
+ $numberOfCentralDirectoryEntries = min(count($this->centralDirectoryRecords), 0xFFFF);
+ $this->send(EndOfCentralDirectory::generate(
+ numberOfThisDisk: 0x00,
+ numberOfTheDiskWithCentralDirectoryStart: 0x00,
+ numberOfCentralDirectoryEntriesOnThisDisk: $numberOfCentralDirectoryEntries,
+ numberOfCentralDirectoryEntries: $numberOfCentralDirectoryEntries,
+ sizeOfCentralDirectory: min($sizeOfCentralDirectory, 0xFFFFFFFF),
+ centralDirectoryStartOffsetOnDisk: min($centralDirectoryStartOffsetOnDisk, 0xFFFFFFFF),
+ zipFileComment: $this->comment,
+ ));
+
+ $size = $this->offset;
+
+ // The End
+ $this->clear();
+
+ return $size;
+ }
+
+ /**
+ * @param StreamInterface|resource|null $outputStream
+ * @return resource
+ */
+ private static function normalizeStream($outputStream)
+ {
+ if ($outputStream instanceof StreamInterface) {
+ return StreamWrapper::getResource($outputStream);
+ }
+ if (is_resource($outputStream)) {
+ return $outputStream;
+ }
+ return fopen('php://output', 'wb');
+ }
+
+ /**
+ * Record sent bytes
+ */
+ private function recordSentBytes(int $sentBytes): void
+ {
+ $this->offset += $sentBytes;
+ }
+
+ /**
+ * Send string, sending HTTP headers if necessary.
+ * Flush output after write if configure option is set.
+ */
+ private function send(string $data): void
+ {
+ if (!$this->ready) {
+ throw new RuntimeException('Archive is already finished');
+ }
+
+ if ($this->operationMode === OperationMode::NORMAL && $this->sendHttpHeaders) {
+ $this->sendHttpHeaders();
+ $this->sendHttpHeaders = false;
+ }
+
+ $this->recordSentBytes(strlen($data));
+
+ if ($this->operationMode === OperationMode::NORMAL) {
+ if (fwrite($this->outputStream, $data) === false) {
+ throw new ResourceActionException('fwrite', $this->outputStream);
+ }
+
+ if ($this->flushOutput) {
+ // flush output buffer if it is on and flushable
+ $status = ob_get_status();
+ if (isset($status['flags']) && is_int($status['flags']) && ($status['flags'] & PHP_OUTPUT_HANDLER_FLUSHABLE)) {
+ ob_flush();
+ }
+
+ // Flush system buffers after flushing userspace output buffer
+ flush();
+ }
+ }
+ }
+
+ /**
+ * Send HTTP headers for this stream.
+ */
+ private function sendHttpHeaders(): void
+ {
+ // grab content disposition
+ $disposition = $this->contentDisposition;
+
+ if ($this->outputName !== null) {
+ // Various different browsers dislike various characters here. Strip them all for safety.
+ $safeOutput = trim(str_replace(['"', "'", '\\', ';', "\n", "\r"], '', $this->outputName));
+
+ // Check if we need to UTF-8 encode the filename
+ $urlencoded = rawurlencode($safeOutput);
+ $disposition .= "; filename*=UTF-8''{$urlencoded}";
+ }
+
+ $headers = [
+ 'Content-Type' => $this->contentType,
+ 'Content-Disposition' => $disposition,
+ 'Pragma' => 'public',
+ 'Cache-Control' => 'public, must-revalidate',
+ 'Content-Transfer-Encoding' => 'binary',
+ ];
+
+ foreach ($headers as $key => $val) {
+ ($this->httpHeaderCallback)("$key: $val");
+ }
+ }
+
+ /**
+ * Clear all internal variables. Note that the stream object is not
+ * usable after this.
+ */
+ private function clear(): void
+ {
+ $this->centralDirectoryRecords = [];
+ $this->offset = 0;
+
+ if ($this->operationMode === OperationMode::NORMAL) {
+ $this->ready = false;
+ $this->recordedSimulation = [];
+ } else {
+ $this->operationMode = OperationMode::NORMAL;
+ }
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php b/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php
new file mode 100644
index 000000000..bf621bc09
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/src/Zs/ExtendedInformationExtraField.php
@@ -0,0 +1,23 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Zs;
+
+use ZipStream\PackField;
+
+/**
+ * @internal
+ */
+abstract class ExtendedInformationExtraField
+{
+ private const TAG = 0x5653;
+
+ public static function generate(): string
+ {
+ return PackField::pack(
+ new PackField(format: 'v', value: self::TAG),
+ new PackField(format: 'v', value: 0x0000),
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/Assertions.php b/vendor/maennchen/zipstream-php/test/Assertions.php
new file mode 100644
index 000000000..8d7670eff
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/Assertions.php
@@ -0,0 +1,49 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+trait Assertions
+{
+ protected function assertFileContains(string $filePath, string $needle): void
+ {
+ $last = '';
+
+ $handle = fopen($filePath, 'r');
+ while (!feof($handle)) {
+ $line = fgets($handle, 1024);
+
+ if (str_contains($last . $line, $needle)) {
+ fclose($handle);
+ return;
+ }
+
+ $last = $line;
+ }
+
+ fclose($handle);
+
+ $this->fail("File {$filePath} must contain {$needle}");
+ }
+
+ protected function assertFileDoesNotContain(string $filePath, string $needle): void
+ {
+ $last = '';
+
+ $handle = fopen($filePath, 'r');
+ while (!feof($handle)) {
+ $line = fgets($handle, 1024);
+
+ if (str_contains($last . $line, $needle)) {
+ fclose($handle);
+
+ $this->fail("File {$filePath} must not contain {$needle}");
+ }
+
+ $last = $line;
+ }
+
+ fclose($handle);
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php b/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php
new file mode 100644
index 000000000..5457b4f44
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/CentralDirectoryFileHeaderTest.php
@@ -0,0 +1,60 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use DateTimeImmutable;
+use PHPUnit\Framework\TestCase;
+use ZipStream\CentralDirectoryFileHeader;
+use ZipStream\CompressionMethod;
+
+class CentralDirectoryFileHeaderTest extends TestCase
+{
+ public function testSerializesCorrectly(): void
+ {
+ $dateTime = new DateTimeImmutable('2022-01-01 01:01:01Z');
+
+ $header = CentralDirectoryFileHeader::generate(
+ versionMadeBy: 0x603,
+ versionNeededToExtract: 0x002D,
+ generalPurposeBitFlag: 0x2222,
+ compressionMethod: CompressionMethod::DEFLATE,
+ lastModificationDateTime: $dateTime,
+ crc32: 0x11111111,
+ compressedSize: 0x77777777,
+ uncompressedSize: 0x99999999,
+ fileName: 'test.png',
+ extraField: 'some content',
+ fileComment: 'some comment',
+ diskNumberStart: 0,
+ internalFileAttributes: 0,
+ externalFileAttributes: 32,
+ relativeOffsetOfLocalHeader: 0x1234,
+ );
+
+ $this->assertSame(
+ bin2hex($header),
+ '504b0102' . // 4 bytes; central file header signature
+ '0306' . // 2 bytes; version made by
+ '2d00' . // 2 bytes; version needed to extract
+ '2222' . // 2 bytes; general purpose bit flag
+ '0800' . // 2 bytes; compression method
+ '2008' . // 2 bytes; last mod file time
+ '2154' . // 2 bytes; last mod file date
+ '11111111' . // 4 bytes; crc-32
+ '77777777' . // 4 bytes; compressed size
+ '99999999' . // 4 bytes; uncompressed size
+ '0800' . // 2 bytes; file name length (n)
+ '0c00' . // 2 bytes; extra field length (m)
+ '0c00' . // 2 bytes; file comment length (o)
+ '0000' . // 2 bytes; disk number start
+ '0000' . // 2 bytes; internal file attributes
+ '20000000' . // 4 bytes; external file attributes
+ '34120000' . // 4 bytes; relative offset of local header
+ '746573742e706e67' . // n bytes; file name
+ '736f6d6520636f6e74656e74' . // m bytes; extra field
+ '736f6d6520636f6d6d656e74' // o bytes; file comment
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php b/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php
new file mode 100644
index 000000000..cc886c74b
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/DataDescriptorTest.php
@@ -0,0 +1,26 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use PHPUnit\Framework\TestCase;
+use ZipStream\DataDescriptor;
+
+class DataDescriptorTest extends TestCase
+{
+ public function testSerializesCorrectly(): void
+ {
+ $this->assertSame(
+ bin2hex(DataDescriptor::generate(
+ crc32UncompressedData: 0x11111111,
+ compressedSize: 0x77777777,
+ uncompressedSize: 0x99999999,
+ )),
+ '504b0708' . // 4 bytes; Optional data descriptor signature = 0x08074b50
+ '11111111' . // 4 bytes; CRC-32 of uncompressed data
+ '77777777' . // 4 bytes; Compressed size
+ '99999999' // 4 bytes; Uncompressed size
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php b/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php
new file mode 100644
index 000000000..be0a90743
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/EndOfCentralDirectoryTest.php
@@ -0,0 +1,35 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use PHPUnit\Framework\TestCase;
+use ZipStream\EndOfCentralDirectory;
+
+class EndOfCentralDirectoryTest extends TestCase
+{
+ public function testSerializesCorrectly(): void
+ {
+ $this->assertSame(
+ bin2hex(EndOfCentralDirectory::generate(
+ numberOfThisDisk: 0x00,
+ numberOfTheDiskWithCentralDirectoryStart: 0x00,
+ numberOfCentralDirectoryEntriesOnThisDisk: 0x10,
+ numberOfCentralDirectoryEntries: 0x10,
+ sizeOfCentralDirectory: 0x22,
+ centralDirectoryStartOffsetOnDisk: 0x33,
+ zipFileComment: 'foo',
+ )),
+ '504b0506' . // 4 bytes; end of central dir signature 0x06054b50
+ '0000' . // 2 bytes; number of this disk
+ '0000' . // 2 bytes; number of the disk with the start of the central directory
+ '1000' . // 2 bytes; total number of entries in the central directory on this disk
+ '1000' . // 2 bytes; total number of entries in the central directory
+ '22000000' . // 4 bytes; size of the central directory
+ '33000000' . // 4 bytes; offset of start of central directory with respect to the starting disk number
+ '0300' . // 2 bytes; .ZIP file comment length
+ bin2hex('foo')
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php b/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php
new file mode 100644
index 000000000..d9e7df1fb
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/EndlessCycleStream.php
@@ -0,0 +1,104 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use Psr\Http\Message\StreamInterface;
+use RuntimeException;
+
+class EndlessCycleStream implements StreamInterface
+{
+ private int $offset = 0;
+
+ public function __construct(private readonly string $toRepeat = '0') {}
+
+ public function __toString(): string
+ {
+ throw new RuntimeException('Infinite Stream!');
+ }
+
+ public function close(): void
+ {
+ $this->detach();
+ }
+
+ /**
+ * @return null
+ */
+ public function detach()
+ {
+ return;
+ }
+
+ public function getSize(): ?int
+ {
+ return null;
+ }
+
+ public function tell(): int
+ {
+ return $this->offset;
+ }
+
+ public function eof(): bool
+ {
+ return false;
+ }
+
+ public function isSeekable(): bool
+ {
+ return true;
+ }
+
+ public function seek(int $offset, int $whence = SEEK_SET): void
+ {
+ switch ($whence) {
+ case SEEK_SET:
+ $this->offset = $offset;
+ break;
+ case SEEK_CUR:
+ $this->offset += $offset;
+ break;
+ case SEEK_END:
+ throw new RuntimeException('Infinite Stream!');
+ break;
+ }
+ }
+
+ public function rewind(): void
+ {
+ $this->seek(0);
+ }
+
+ public function isWritable(): bool
+ {
+ return false;
+ }
+
+ public function write(string $string): int
+ {
+ throw new RuntimeException('Not writeable');
+ }
+
+ public function isReadable(): bool
+ {
+ return true;
+ }
+
+ public function read(int $length): string
+ {
+ $this->offset += $length;
+ return substr(str_repeat($this->toRepeat, (int) ceil($length / strlen($this->toRepeat))), 0, $length);
+ }
+
+ public function getContents(): string
+ {
+ throw new RuntimeException('Infinite Stream!');
+ }
+
+ public function getMetadata(?string $key = null): array|null
+ {
+ return $key !== null ? null : [];
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php b/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php
new file mode 100644
index 000000000..3d4440e8a
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/FaultInjectionResource.php
@@ -0,0 +1,141 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+class FaultInjectionResource
+{
+ public const NAME = 'zipstream-php-test-broken-resource';
+
+ /** @var resource */
+ public $context;
+
+ private array $injectFaults;
+
+ private string $mode;
+
+ /**
+ * @return resource
+ */
+ public static function getResource(array $injectFaults)
+ {
+ self::register();
+
+ return fopen(self::NAME . '://foobar', 'rw+', false, self::createStreamContext($injectFaults));
+ }
+
+ public function stream_open(string $path, string $mode, int $options, string &$opened_path = null): bool
+ {
+ $options = stream_context_get_options($this->context);
+
+ if (!isset($options[self::NAME]['injectFaults'])) {
+ return false;
+ }
+
+ $this->mode = $mode;
+ $this->injectFaults = $options[self::NAME]['injectFaults'];
+
+ if ($this->shouldFail(__FUNCTION__)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function stream_write(string $data)
+ {
+ if ($this->shouldFail(__FUNCTION__)) {
+ return false;
+ }
+ return true;
+ }
+
+ public function stream_eof()
+ {
+ return true;
+ }
+
+ public function stream_seek(int $offset, int $whence): bool
+ {
+ if ($this->shouldFail(__FUNCTION__)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ public function stream_tell(): int
+ {
+ if ($this->shouldFail(__FUNCTION__)) {
+ return false;
+ }
+
+ return 0;
+ }
+
+ public static function register(): void
+ {
+ if (!in_array(self::NAME, stream_get_wrappers(), true)) {
+ stream_wrapper_register(self::NAME, __CLASS__);
+ }
+ }
+
+ public function stream_stat(): array
+ {
+ static $modeMap = [
+ 'r' => 33060,
+ 'rb' => 33060,
+ 'r+' => 33206,
+ 'w' => 33188,
+ 'wb' => 33188,
+ ];
+
+ return [
+ 'dev' => 0,
+ 'ino' => 0,
+ 'mode' => $modeMap[$this->mode],
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => 0,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ 'blksize' => 0,
+ 'blocks' => 0,
+ ];
+ }
+
+ public function url_stat(string $path, int $flags): array
+ {
+ return [
+ 'dev' => 0,
+ 'ino' => 0,
+ 'mode' => 0,
+ 'nlink' => 0,
+ 'uid' => 0,
+ 'gid' => 0,
+ 'rdev' => 0,
+ 'size' => 0,
+ 'atime' => 0,
+ 'mtime' => 0,
+ 'ctime' => 0,
+ 'blksize' => 0,
+ 'blocks' => 0,
+ ];
+ }
+
+ private static function createStreamContext(array $injectFaults)
+ {
+ return stream_context_create([
+ self::NAME => ['injectFaults' => $injectFaults],
+ ]);
+ }
+
+ private function shouldFail(string $function): bool
+ {
+ return in_array($function, $this->injectFaults, true);
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php b/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php
new file mode 100644
index 000000000..196dd0fe3
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/LocalFileHeaderTest.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use DateTimeImmutable;
+use PHPUnit\Framework\TestCase;
+use ZipStream\CompressionMethod;
+use ZipStream\LocalFileHeader;
+
+class LocalFileHeaderTest extends TestCase
+{
+ public function testSerializesCorrectly(): void
+ {
+ $dateTime = new DateTimeImmutable('2022-01-01 01:01:01Z');
+
+ $header = LocalFileHeader::generate(
+ versionNeededToExtract: 0x002D,
+ generalPurposeBitFlag: 0x2222,
+ compressionMethod: CompressionMethod::DEFLATE,
+ lastModificationDateTime: $dateTime,
+ crc32UncompressedData: 0x11111111,
+ compressedSize: 0x77777777,
+ uncompressedSize: 0x99999999,
+ fileName: 'test.png',
+ extraField: 'some content'
+ );
+
+ $this->assertSame(
+ bin2hex((string) $header),
+ '504b0304' . // 4 bytes; Local file header signature
+ '2d00' . // 2 bytes; Version needed to extract (minimum)
+ '2222' . // 2 bytes; General purpose bit flag
+ '0800' . // 2 bytes; Compression method; e.g. none = 0, DEFLATE = 8
+ '2008' . // 2 bytes; File last modification time
+ '2154' . // 2 bytes; File last modification date
+ '11111111' . // 4 bytes; CRC-32 of uncompressed data
+ '77777777' . // 4 bytes; Compressed size (or 0xffffffff for ZIP64)
+ '99999999' . // 4 bytes; Uncompressed size (or 0xffffffff for ZIP64)
+ '0800' . // 2 bytes; File name length (n)
+ '0c00' . // 2 bytes; Extra field length (m)
+ '746573742e706e67' . // n bytes; File name
+ '736f6d6520636f6e74656e74' // m bytes; Extra field
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/PackFieldTest.php b/vendor/maennchen/zipstream-php/test/PackFieldTest.php
new file mode 100644
index 000000000..ecd66bac7
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/PackFieldTest.php
@@ -0,0 +1,42 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use PHPUnit\Framework\TestCase;
+use RuntimeException;
+use ZipStream\PackField;
+
+class PackFieldTest extends TestCase
+{
+ public function testPacksFields(): void
+ {
+ $this->assertSame(
+ bin2hex(PackField::pack(new PackField(format: 'v', value: 0x1122))),
+ '2211',
+ );
+ }
+
+ public function testOverflow2(): void
+ {
+ $this->expectException(RuntimeException::class);
+
+ PackField::pack(new PackField(format: 'v', value: 0xFFFFF));
+ }
+
+ public function testOverflow4(): void
+ {
+ $this->expectException(RuntimeException::class);
+
+ PackField::pack(new PackField(format: 'V', value: 0xFFFFFFFFF));
+ }
+
+ public function testUnknownOperator(): void
+ {
+ $this->assertSame(
+ bin2hex(PackField::pack(new PackField(format: 'a', value: 0x1122))),
+ '34',
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/ResourceStream.php b/vendor/maennchen/zipstream-php/test/ResourceStream.php
new file mode 100644
index 000000000..752a1a357
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/ResourceStream.php
@@ -0,0 +1,159 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use Psr\Http\Message\StreamInterface;
+use RuntimeException;
+
+/**
+ * @internal
+ */
+class ResourceStream implements StreamInterface
+{
+ public function __construct(
+ /**
+ * @var resource
+ */
+ private $stream
+ ) {}
+
+ public function __toString(): string
+ {
+ if ($this->isSeekable()) {
+ $this->seek(0);
+ }
+ return (string) stream_get_contents($this->stream);
+ }
+
+ public function close(): void
+ {
+ $stream = $this->detach();
+ if ($stream) {
+ fclose($stream);
+ }
+ }
+
+ public function detach()
+ {
+ $result = $this->stream;
+ // According to the interface, the stream is left in an unusable state;
+ /** @psalm-suppress PossiblyNullPropertyAssignmentValue */
+ $this->stream = null;
+ return $result;
+ }
+
+ public function seek(int $offset, int $whence = SEEK_SET): void
+ {
+ if (!$this->isSeekable()) {
+ throw new RuntimeException();
+ }
+ if (fseek($this->stream, $offset, $whence) !== 0) {
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException();
+ // @codeCoverageIgnoreEnd
+ }
+ }
+
+ public function isSeekable(): bool
+ {
+ return (bool) $this->getMetadata('seekable');
+ }
+
+ public function getMetadata(?string $key = null)
+ {
+ $metadata = stream_get_meta_data($this->stream);
+ return $key !== null ? @$metadata[$key] : $metadata;
+ }
+
+ public function getSize(): ?int
+ {
+ $stats = fstat($this->stream);
+ return $stats['size'];
+ }
+
+ public function tell(): int
+ {
+ $position = ftell($this->stream);
+ if ($position === false) {
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException();
+ // @codeCoverageIgnoreEnd
+ }
+ return $position;
+ }
+
+ public function eof(): bool
+ {
+ return feof($this->stream);
+ }
+
+ public function rewind(): void
+ {
+ $this->seek(0);
+ }
+
+ public function write(string $string): int
+ {
+ if (!$this->isWritable()) {
+ throw new RuntimeException();
+ }
+ if (fwrite($this->stream, $string) === false) {
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException();
+ // @codeCoverageIgnoreEnd
+ }
+ return strlen($string);
+ }
+
+ public function isWritable(): bool
+ {
+ $mode = $this->getMetadata('mode');
+ if (!is_string($mode)) {
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException('Could not get stream mode from metadata!');
+ // @codeCoverageIgnoreEnd
+ }
+ return preg_match('/[waxc+]/', $mode) === 1;
+ }
+
+ public function read(int $length): string
+ {
+ if (!$this->isReadable()) {
+ throw new RuntimeException();
+ }
+ $result = fread($this->stream, $length);
+ if ($result === false) {
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException();
+ // @codeCoverageIgnoreEnd
+ }
+ return $result;
+ }
+
+ public function isReadable(): bool
+ {
+ $mode = $this->getMetadata('mode');
+ if (!is_string($mode)) {
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException('Could not get stream mode from metadata!');
+ // @codeCoverageIgnoreEnd
+ }
+ return preg_match('/[r+]/', $mode) === 1;
+ }
+
+ public function getContents(): string
+ {
+ if (!$this->isReadable()) {
+ throw new RuntimeException();
+ }
+ $result = stream_get_contents($this->stream);
+ if ($result === false) {
+ // @codeCoverageIgnoreStart
+ throw new RuntimeException();
+ // @codeCoverageIgnoreEnd
+ }
+ return $result;
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/Tempfile.php b/vendor/maennchen/zipstream-php/test/Tempfile.php
new file mode 100644
index 000000000..7ef9c61f9
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/Tempfile.php
@@ -0,0 +1,42 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+trait Tempfile
+{
+ protected string|null $tempfile;
+
+ /**
+ * @var resource
+ */
+ protected $tempfileStream;
+
+ protected function setUp(): void
+ {
+ [$tempfile, $tempfileStream] = $this->getTmpFileStream();
+
+ $this->tempfile = $tempfile;
+ $this->tempfileStream = $tempfileStream;
+ }
+
+ protected function tearDown(): void
+ {
+ unlink($this->tempfile);
+ if (is_resource($this->tempfileStream)) {
+ fclose($this->tempfileStream);
+ }
+
+ $this->tempfile = null;
+ $this->tempfileStream = null;
+ }
+
+ protected function getTmpFileStream(): array
+ {
+ $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest');
+ $stream = fopen($tmp, 'wb+');
+
+ return [$tmp, $stream];
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/TimeTest.php b/vendor/maennchen/zipstream-php/test/TimeTest.php
new file mode 100644
index 000000000..61cfe0388
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/TimeTest.php
@@ -0,0 +1,44 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use DateTimeImmutable;
+use PHPUnit\Framework\TestCase;
+use ZipStream\Exception\DosTimeOverflowException;
+use ZipStream\Time;
+
+class TimeTest extends TestCase
+{
+ public function testNormalDateToDosTime(): void
+ {
+ $this->assertSame(
+ Time::dateTimeToDosTime(new DateTimeImmutable('2014-11-17T17:46:08Z')),
+ 1165069764
+ );
+
+ // January 1 1980 - DOS Epoch.
+ $this->assertSame(
+ Time::dateTimeToDosTime(new DateTimeImmutable('1980-01-01T00:00:00+00:00')),
+ 2162688
+ );
+
+ // Local timezone different than UTC.
+ $prevLocalTimezone = date_default_timezone_get();
+ date_default_timezone_set('Europe/Berlin');
+ $this->assertSame(
+ Time::dateTimeToDosTime(new DateTimeImmutable('1980-01-01T00:00:00+00:00')),
+ 2162688
+ );
+ date_default_timezone_set($prevLocalTimezone);
+ }
+
+ public function testTooEarlyDateToDosTime(): void
+ {
+ $this->expectException(DosTimeOverflowException::class);
+
+ // January 1 1980 is the minimum DOS Epoch.
+ Time::dateTimeToDosTime(new DateTimeImmutable('1970-01-01T00:00:00+00:00'));
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/Util.php b/vendor/maennchen/zipstream-php/test/Util.php
new file mode 100644
index 000000000..86592b429
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/Util.php
@@ -0,0 +1,127 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use function fgets;
+use function pclose;
+use function popen;
+use function preg_match;
+
+use RecursiveDirectoryIterator;
+use RecursiveIteratorIterator;
+
+use function strtolower;
+
+use ZipArchive;
+
+trait Util
+{
+ protected function cmdExists(string $command): bool
+ {
+ if (strtolower(\substr(PHP_OS, 0, 3)) === 'win') {
+ $fp = popen("where $command", 'r');
+ $result = fgets($fp, 255);
+ $exists = !preg_match('#Could not find files#', $result);
+ pclose($fp);
+ } else { // non-Windows
+ $fp = popen("which $command", 'r');
+ $result = fgets($fp, 255);
+ $exists = !empty($result);
+ pclose($fp);
+ }
+
+ return $exists;
+ }
+
+ protected function dumpZipContents(string $path): string
+ {
+ if (!$this->cmdExists('hexdump')) {
+ return '';
+ }
+
+ $output = [];
+
+ if (!exec("hexdump -C \"$path\" | head -n 50", $output)) {
+ return '';
+ }
+
+ return "\nHexdump:\n" . implode("\n", $output);
+ }
+
+ protected function validateAndExtractZip(string $zipPath): string
+ {
+ $tmpDir = $this->getTmpDir();
+
+ $zipArchive = new ZipArchive();
+ $result = $zipArchive->open($zipPath);
+
+ if ($result !== true) {
+ $codeName = $this->zipArchiveOpenErrorCodeName($result);
+ $debugInformation = $this->dumpZipContents($zipPath);
+
+ $this->fail("Failed to open {$zipPath}. Code: $result ($codeName)$debugInformation");
+
+ return $tmpDir;
+ }
+
+ $this->assertSame(0, $zipArchive->status);
+ $this->assertSame(0, $zipArchive->statusSys);
+
+ $zipArchive->extractTo($tmpDir);
+ $zipArchive->close();
+
+ return $tmpDir;
+ }
+
+ protected function zipArchiveOpenErrorCodeName(int $code): string
+ {
+ switch ($code) {
+ case ZipArchive::ER_EXISTS: return 'ER_EXISTS';
+ case ZipArchive::ER_INCONS: return 'ER_INCONS';
+ case ZipArchive::ER_INVAL: return 'ER_INVAL';
+ case ZipArchive::ER_MEMORY: return 'ER_MEMORY';
+ case ZipArchive::ER_NOENT: return 'ER_NOENT';
+ case ZipArchive::ER_NOZIP: return 'ER_NOZIP';
+ case ZipArchive::ER_OPEN: return 'ER_OPEN';
+ case ZipArchive::ER_READ: return 'ER_READ';
+ case ZipArchive::ER_SEEK: return 'ER_SEEK';
+ default: return 'unknown';
+ }
+ }
+
+ protected function getTmpDir(): string
+ {
+ $tmp = tempnam(sys_get_temp_dir(), 'zipstreamtest');
+ unlink($tmp);
+ mkdir($tmp) or $this->fail('Failed to make directory');
+
+ return $tmp;
+ }
+
+ /**
+ * @return string[]
+ */
+ protected function getRecursiveFileList(string $path, bool $includeDirectories = false): array
+ {
+ $data = [];
+ $path = (string) realpath($path);
+ $files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path));
+
+ $pathLen = strlen($path);
+ foreach ($files as $file) {
+ $filePath = $file->getRealPath();
+
+ if (is_dir($filePath) && !$includeDirectories) {
+ continue;
+ }
+
+ $data[] = substr($filePath, $pathLen + 1);
+ }
+
+ sort($data);
+
+ return $data;
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php b/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php
new file mode 100644
index 000000000..49fb2ccb2
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/Zip64/DataDescriptorTest.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test\Zip64;
+
+use PHPUnit\Framework\TestCase;
+use ZipStream\Zip64\DataDescriptor;
+
+class DataDescriptorTest extends TestCase
+{
+ public function testSerializesCorrectly(): void
+ {
+ $descriptor = DataDescriptor::generate(
+ crc32UncompressedData: 0x11111111,
+ compressedSize: (0x77777777 << 32) + 0x66666666,
+ uncompressedSize: (0x99999999 << 32) + 0x88888888,
+ );
+
+ $this->assertSame(
+ bin2hex($descriptor),
+ '504b0708' . // 4 bytes; Optional data descriptor signature = 0x08074b50
+ '11111111' . // 4 bytes; CRC-32 of uncompressed data
+ '6666666677777777' . // 8 bytes; Compressed size
+ '8888888899999999' // 8 bytes; Uncompressed size
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php b/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php
new file mode 100644
index 000000000..271a29862
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryLocatorTest.php
@@ -0,0 +1,28 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test\Zip64;
+
+use PHPUnit\Framework\TestCase;
+use ZipStream\Zip64\EndOfCentralDirectoryLocator;
+
+class EndOfCentralDirectoryLocatorTest extends TestCase
+{
+ public function testSerializesCorrectly(): void
+ {
+ $descriptor = EndOfCentralDirectoryLocator::generate(
+ numberOfTheDiskWithZip64CentralDirectoryStart: 0x11111111,
+ zip64centralDirectoryStartOffsetOnDisk: (0x22222222 << 32) + 0x33333333,
+ totalNumberOfDisks: 0x44444444,
+ );
+
+ $this->assertSame(
+ bin2hex($descriptor),
+ '504b0607' . // 4 bytes; zip64 end of central dir locator signature - 0x07064b50
+ '11111111' . // 4 bytes; number of the disk with the start of the zip64 end of central directory
+ '3333333322222222' . // 28 bytes; relative offset of the zip64 end of central directory record
+ '44444444' // 4 bytes;total number of disks
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php b/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php
new file mode 100644
index 000000000..b86fb1781
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/Zip64/EndOfCentralDirectoryTest.php
@@ -0,0 +1,41 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test\Zip64;
+
+use PHPUnit\Framework\TestCase;
+use ZipStream\Zip64\EndOfCentralDirectory;
+
+class EndOfCentralDirectoryTest extends TestCase
+{
+ public function testSerializesCorrectly(): void
+ {
+ $descriptor = EndOfCentralDirectory::generate(
+ versionMadeBy: 0x3333,
+ versionNeededToExtract: 0x4444,
+ numberOfThisDisk: 0x55555555,
+ numberOfTheDiskWithCentralDirectoryStart: 0x66666666,
+ numberOfCentralDirectoryEntriesOnThisDisk: (0x77777777 << 32) + 0x88888888,
+ numberOfCentralDirectoryEntries: (0x99999999 << 32) + 0xAAAAAAAA,
+ sizeOfCentralDirectory: (0xBBBBBBBB << 32) + 0xCCCCCCCC,
+ centralDirectoryStartOffsetOnDisk: (0xDDDDDDDD << 32) + 0xEEEEEEEE,
+ extensibleDataSector: 'foo',
+ );
+
+ $this->assertSame(
+ bin2hex($descriptor),
+ '504b0606' . // 4 bytes;zip64 end of central dir signature - 0x06064b50
+ '2f00000000000000' . // 8 bytes; size of zip64 end of central directory record
+ '3333' . // 2 bytes; version made by
+ '4444' . // 2 bytes; version needed to extract
+ '55555555' . // 4 bytes; number of this disk
+ '66666666' . // 4 bytes; number of the disk with the start of the central directory
+ '8888888877777777' . // 8 bytes; total number of entries in the central directory on this disk
+ 'aaaaaaaa99999999' . // 8 bytes; total number of entries in the central directory
+ 'ccccccccbbbbbbbb' . // 8 bytes; size of the central directory
+ 'eeeeeeeedddddddd' . // 8 bytes; offset of start of central directory with respect to the starting disk number
+ bin2hex('foo')
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php b/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php
new file mode 100644
index 000000000..904783d86
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/Zip64/ExtendedInformationExtraFieldTest.php
@@ -0,0 +1,42 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test\Zip64;
+
+use PHPUnit\Framework\TestCase;
+use ZipStream\Zip64\ExtendedInformationExtraField;
+
+class ExtendedInformationExtraFieldTest extends TestCase
+{
+ public function testSerializesCorrectly(): void
+ {
+ $extraField = ExtendedInformationExtraField::generate(
+ originalSize: (0x77777777 << 32) + 0x66666666,
+ compressedSize: (0x99999999 << 32) + 0x88888888,
+ relativeHeaderOffset: (0x22222222 << 32) + 0x11111111,
+ diskStartNumber: 0x33333333,
+ );
+
+ $this->assertSame(
+ bin2hex($extraField),
+ '0100' . // 2 bytes; Tag for this "extra" block type
+ '1c00' . // 2 bytes; Size of this "extra" block
+ '6666666677777777' . // 8 bytes; Original uncompressed file size
+ '8888888899999999' . // 8 bytes; Size of compressed data
+ '1111111122222222' . // 8 bytes; Offset of local header record
+ '33333333' // 4 bytes; Number of the disk on which this file starts
+ );
+ }
+
+ public function testSerializesEmptyCorrectly(): void
+ {
+ $extraField = ExtendedInformationExtraField::generate();
+
+ $this->assertSame(
+ bin2hex($extraField),
+ '0100' . // 2 bytes; Tag for this "extra" block type
+ '0000' // 2 bytes; Size of this "extra" block
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/ZipStreamTest.php b/vendor/maennchen/zipstream-php/test/ZipStreamTest.php
new file mode 100644
index 000000000..9b10ba65d
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/ZipStreamTest.php
@@ -0,0 +1,1195 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test;
+
+use DateTimeImmutable;
+use GuzzleHttp\Psr7\Response;
+use GuzzleHttp\Psr7\StreamWrapper;
+use org\bovigo\vfs\vfsStream;
+use PHPUnit\Framework\TestCase;
+use Psr\Http\Message\StreamInterface;
+use RuntimeException;
+use ZipArchive;
+use ZipStream\CompressionMethod;
+use ZipStream\Exception\FileNotFoundException;
+use ZipStream\Exception\FileNotReadableException;
+use ZipStream\Exception\FileSizeIncorrectException;
+use ZipStream\Exception\OverflowException;
+use ZipStream\Exception\ResourceActionException;
+use ZipStream\Exception\SimulationFileUnknownException;
+use ZipStream\Exception\StreamNotReadableException;
+use ZipStream\Exception\StreamNotSeekableException;
+use ZipStream\OperationMode;
+use ZipStream\PackField;
+use ZipStream\ZipStream;
+
+class ZipStreamTest extends TestCase
+{
+ use Util;
+ use Assertions;
+ use Tempfile;
+
+ public function testAddFile(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data');
+ $zip->addFile('test/sample.txt', 'More Simple Sample Data');
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files);
+
+ $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data');
+ $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data');
+ }
+
+ public function testAddFileUtf8NameComment(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $name = 'árvíztűrő tükörfúrógép.txt';
+ $content = 'Sample String Data';
+ $comment =
+ 'Filename has every special characters ' .
+ 'from Hungarian language in lowercase. ' .
+ 'In uppercase: ÁÍŰŐÜÖÚÓÉ';
+
+ $zip->addFile(fileName: $name, data: $content, comment: $comment);
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame([$name], $files);
+ $this->assertStringEqualsFile($tmpDir . '/' . $name, $content);
+
+ $zipArchive = new ZipArchive();
+ $zipArchive->open($this->tempfile);
+ $this->assertSame($comment, $zipArchive->getCommentName($name));
+ }
+
+ public function testAddFileUtf8NameNonUtfComment(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $name = 'á.txt';
+ $content = 'any';
+ $comment = mb_convert_encoding('á', 'ISO-8859-2', 'UTF-8');
+
+ // @see https://libzip.org/documentation/zip_file_get_comment.html
+ //
+ // mb_convert_encoding hasn't CP437.
+ // nearly CP850 (DOS-Latin-1)
+ $guessComment = mb_convert_encoding($comment, 'UTF-8', 'CP850');
+
+ $zip->addFile(fileName: $name, data: $content, comment: $comment);
+
+ $zip->finish();
+
+ $zipArch = new ZipArchive();
+ $zipArch->open($this->tempfile);
+ $this->assertSame($guessComment, $zipArch->getCommentName($name));
+ $this->assertSame($comment, $zipArch->getCommentName($name, ZipArchive::FL_ENC_RAW));
+ }
+
+ public function testAddFileWithStorageMethod(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $zip->addFile(fileName: 'sample.txt', data: 'Sample String Data', compressionMethod: CompressionMethod::STORE);
+ $zip->addFile(fileName: 'test/sample.txt', data: 'More Simple Sample Data');
+ $zip->finish();
+
+ $zipArchive = new ZipArchive();
+ $zipArchive->open($this->tempfile);
+
+ $sample1 = $zipArchive->statName('sample.txt');
+ $sample12 = $zipArchive->statName('test/sample.txt');
+ $this->assertSame($sample1['comp_method'], CompressionMethod::STORE->value);
+ $this->assertSame($sample12['comp_method'], CompressionMethod::DEFLATE->value);
+
+ $zipArchive->close();
+ }
+
+ public function testAddFileFromPath(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ [$tmpExample, $streamExample] = $this->getTmpFileStream();
+ fwrite($streamExample, 'Sample String Data');
+ fclose($streamExample);
+ $zip->addFileFromPath(fileName: 'sample.txt', path: $tmpExample);
+
+ [$tmpExample, $streamExample] = $this->getTmpFileStream();
+ fwrite($streamExample, 'More Simple Sample Data');
+ fclose($streamExample);
+ $zip->addFileFromPath(fileName: 'test/sample.txt', path: $tmpExample);
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files);
+
+ $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data');
+ $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data');
+
+ unlink($tmpExample);
+ }
+
+ public function testAddFileFromPathFileNotFoundException(): void
+ {
+ $this->expectException(FileNotFoundException::class);
+
+ // Get ZipStream Object
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ // Trigger error by adding a file which doesn't exist
+ $zip->addFileFromPath(fileName: 'foobar.php', path: '/foo/bar/foobar.php');
+ }
+
+ public function testAddFileFromPathFileNotReadableException(): void
+ {
+ $this->expectException(FileNotReadableException::class);
+
+ // create new virtual filesystem
+ $root = vfsStream::setup('vfs');
+ // create a virtual file with no permissions
+ $file = vfsStream::newFile('foo.txt', 0)->at($root)->setContent('bar');
+
+ // Get ZipStream Object
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $zip->addFileFromPath('foo.txt', $file->url());
+ }
+
+ public function testAddFileFromPathWithStorageMethod(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ [$tmpExample, $streamExample] = $this->getTmpFileStream();
+ fwrite($streamExample, 'Sample String Data');
+ fclose($streamExample);
+ $zip->addFileFromPath(fileName: 'sample.txt', path: $tmpExample, compressionMethod: CompressionMethod::STORE);
+
+ [$tmpExample, $streamExample] = $this->getTmpFileStream();
+ fwrite($streamExample, 'More Simple Sample Data');
+ fclose($streamExample);
+ $zip->addFileFromPath('test/sample.txt', $tmpExample);
+
+ $zip->finish();
+
+ $zipArchive = new ZipArchive();
+ $zipArchive->open($this->tempfile);
+
+ $sample1 = $zipArchive->statName('sample.txt');
+ $this->assertSame(CompressionMethod::STORE->value, $sample1['comp_method']);
+
+ $sample2 = $zipArchive->statName('test/sample.txt');
+ $this->assertSame(CompressionMethod::DEFLATE->value, $sample2['comp_method']);
+
+ $zipArchive->close();
+ }
+
+ public function testAddLargeFileFromPath(): void
+ {
+ foreach ([CompressionMethod::DEFLATE, CompressionMethod::STORE] as $compressionMethod) {
+ foreach ([false, true] as $zeroHeader) {
+ foreach ([false, true] as $zip64) {
+ if ($zeroHeader && $compressionMethod === CompressionMethod::DEFLATE) {
+ continue;
+ }
+ $this->addLargeFileFileFromPath(
+ compressionMethod: $compressionMethod,
+ zeroHeader: $zeroHeader,
+ zip64: $zip64
+ );
+ }
+ }
+ }
+ }
+
+ public function testAddFileFromStream(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ // In this test we can't use temporary stream to feed data
+ // because zlib.deflate filter gives empty string before PHP 7
+ // it works fine with file stream
+ $streamExample = fopen(__FILE__, 'rb');
+ $zip->addFileFromStream('sample.txt', $streamExample);
+ fclose($streamExample);
+
+ $streamExample2 = fopen('php://temp', 'wb+');
+ fwrite($streamExample2, 'More Simple Sample Data');
+ rewind($streamExample2); // move the pointer back to the beginning of file.
+ $zip->addFileFromStream('test/sample.txt', $streamExample2); //, $fileOptions);
+ fclose($streamExample2);
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files);
+
+ $this->assertStringEqualsFile(__FILE__, file_get_contents($tmpDir . '/sample.txt'));
+ $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data');
+ }
+
+ public function testAddFileFromStreamUnreadableInput(): void
+ {
+ $this->expectException(StreamNotReadableException::class);
+
+ [$tmpInput] = $this->getTmpFileStream();
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $streamUnreadable = fopen($tmpInput, 'w');
+
+ $zip->addFileFromStream('sample.json', $streamUnreadable);
+ }
+
+ public function testAddFileFromStreamBrokenOutputWrite(): void
+ {
+ $this->expectException(ResourceActionException::class);
+
+ $outputStream = FaultInjectionResource::getResource(['stream_write']);
+
+ $zip = new ZipStream(
+ outputStream: $outputStream,
+ sendHttpHeaders: false,
+ );
+
+ $zip->addFile('sample.txt', 'foobar');
+ }
+
+ public function testAddFileFromStreamBrokenInputRewind(): void
+ {
+ $this->expectException(ResourceActionException::class);
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ defaultEnableZeroHeader: false,
+ );
+
+ $fileStream = FaultInjectionResource::getResource(['stream_seek']);
+
+ $zip->addFileFromStream('sample.txt', $fileStream, maxSize: 0);
+ }
+
+ public function testAddFileFromStreamUnseekableInputWithoutZeroHeader(): void
+ {
+ $this->expectException(StreamNotSeekableException::class);
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ defaultEnableZeroHeader: false,
+ );
+
+ if (file_exists('/dev/null')) {
+ $streamUnseekable = fopen('/dev/null', 'w+');
+ } elseif (file_exists('NUL')) {
+ $streamUnseekable = fopen('NUL', 'w+');
+ } else {
+ $this->markTestSkipped('Needs file /dev/null');
+ }
+
+ $zip->addFileFromStream('sample.txt', $streamUnseekable, maxSize: 2);
+ }
+
+ public function testAddFileFromStreamUnseekableInputWithZeroHeader(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ defaultEnableZeroHeader: true,
+ defaultCompressionMethod: CompressionMethod::STORE,
+ );
+
+ $streamUnseekable = StreamWrapper::getResource(new class ('test') extends EndlessCycleStream {
+ public function isSeekable(): bool
+ {
+ return false;
+ }
+
+ public function seek(int $offset, int $whence = SEEK_SET): void
+ {
+ throw new RuntimeException('Not seekable');
+ }
+ });
+
+ $zip->addFileFromStream('sample.txt', $streamUnseekable, maxSize: 7);
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample.txt'], $files);
+
+ $this->assertSame(filesize($tmpDir . '/sample.txt'), 7);
+ }
+
+ public function testAddFileFromStreamWithStorageMethod(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $streamExample = fopen('php://temp', 'wb+');
+ fwrite($streamExample, 'Sample String Data');
+ rewind($streamExample); // move the pointer back to the beginning of file.
+ $zip->addFileFromStream('sample.txt', $streamExample, compressionMethod: CompressionMethod::STORE);
+ fclose($streamExample);
+
+ $streamExample2 = fopen('php://temp', 'bw+');
+ fwrite($streamExample2, 'More Simple Sample Data');
+ rewind($streamExample2); // move the pointer back to the beginning of file.
+ $zip->addFileFromStream('test/sample.txt', $streamExample2, compressionMethod: CompressionMethod::DEFLATE);
+ fclose($streamExample2);
+
+ $zip->finish();
+
+ $zipArchive = new ZipArchive();
+ $zipArchive->open($this->tempfile);
+
+ $sample1 = $zipArchive->statName('sample.txt');
+ $this->assertSame(CompressionMethod::STORE->value, $sample1['comp_method']);
+
+ $sample2 = $zipArchive->statName('test/sample.txt');
+ $this->assertSame(CompressionMethod::DEFLATE->value, $sample2['comp_method']);
+
+ $zipArchive->close();
+ }
+
+ public function testAddFileFromPsr7Stream(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $body = 'Sample String Data';
+ $response = new Response(200, [], $body);
+
+ $zip->addFileFromPsr7Stream('sample.json', $response->getBody());
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample.json'], $files);
+ $this->assertStringEqualsFile($tmpDir . '/sample.json', $body);
+ }
+
+ /**
+ * @group slow
+ */
+ public function testAddLargeFileFromPsr7Stream(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ enableZip64: true,
+ );
+
+ $zip->addFileFromPsr7Stream(
+ fileName: 'sample.json',
+ stream: new EndlessCycleStream('0'),
+ maxSize: 0x100000000,
+ compressionMethod: CompressionMethod::STORE,
+ lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'),
+ );
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample.json'], $files);
+ $this->assertFileIsReadable($tmpDir . '/sample.json');
+ $this->assertStringStartsWith('000000', file_get_contents(filename: $tmpDir . '/sample.json', length: 20));
+ }
+
+ public function testContinueFinishedZip(): void
+ {
+ $this->expectException(RuntimeException::class);
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+ $zip->finish();
+
+ $zip->addFile('sample.txt', '1234');
+ }
+
+ /**
+ * @group slow
+ */
+ public function testManyFilesWithoutZip64(): void
+ {
+ $this->expectException(OverflowException::class);
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ enableZip64: false,
+ );
+
+ for ($i = 0; $i <= 0xFFFF; $i++) {
+ $zip->addFile('sample' . $i, '');
+ }
+
+ $zip->finish();
+ }
+
+ /**
+ * @group slow
+ */
+ public function testManyFilesWithZip64(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ enableZip64: true,
+ );
+
+ for ($i = 0; $i <= 0xFFFF; $i++) {
+ $zip->addFile('sample' . $i, '');
+ }
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+
+ $this->assertSame(count($files), 0x10000);
+ }
+
+ /**
+ * @group slow
+ */
+ public function testLongZipWithout64(): void
+ {
+ $this->expectException(OverflowException::class);
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ enableZip64: false,
+ defaultCompressionMethod: CompressionMethod::STORE,
+ );
+
+ for ($i = 0; $i < 4; $i++) {
+ $zip->addFileFromPsr7Stream(
+ fileName: 'sample' . $i,
+ stream: new EndlessCycleStream('0'),
+ maxSize: 0xFFFFFFFF,
+ compressionMethod: CompressionMethod::STORE,
+ lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'),
+ );
+ }
+ }
+
+ /**
+ * @group slow
+ */
+ public function testLongZipWith64(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ enableZip64: true,
+ defaultCompressionMethod: CompressionMethod::STORE,
+ );
+
+ for ($i = 0; $i < 4; $i++) {
+ $zip->addFileFromPsr7Stream(
+ fileName: 'sample' . $i,
+ stream: new EndlessCycleStream('0'),
+ maxSize: 0x5FFFFFFF,
+ compressionMethod: CompressionMethod::STORE,
+ lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'),
+ );
+ }
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample0', 'sample1', 'sample2', 'sample3'], $files);
+ }
+
+ /**
+ * @group slow
+ */
+ public function testAddLargeFileWithoutZip64WithZeroHeader(): void
+ {
+ $this->expectException(OverflowException::class);
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ enableZip64: false,
+ defaultEnableZeroHeader: true,
+ );
+
+ $zip->addFileFromPsr7Stream(
+ fileName: 'sample.json',
+ stream: new EndlessCycleStream('0'),
+ maxSize: 0x100000000,
+ compressionMethod: CompressionMethod::STORE,
+ lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'),
+ );
+ }
+
+ /**
+ * @group slow
+ */
+ public function testAddsZip64HeaderWhenNeeded(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ enableZip64: true,
+ defaultEnableZeroHeader: false,
+ );
+
+ $zip->addFileFromPsr7Stream(
+ fileName: 'sample.json',
+ stream: new EndlessCycleStream('0'),
+ maxSize: 0x100000000,
+ compressionMethod: CompressionMethod::STORE,
+ lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'),
+ );
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+ $files = $this->getRecursiveFileList($tmpDir);
+
+ $this->assertSame(['sample.json'], $files);
+ $this->assertFileContains($this->tempfile, PackField::pack(
+ new PackField(format: 'V', value: 0x06064b50)
+ ));
+ }
+
+ /**
+ * @group slow
+ */
+ public function testDoesNotAddZip64HeaderWhenNotNeeded(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ enableZip64: true,
+ defaultEnableZeroHeader: false,
+ );
+
+ $zip->addFileFromPsr7Stream(
+ fileName: 'sample.json',
+ stream: new EndlessCycleStream('0'),
+ maxSize: 0x10,
+ compressionMethod: CompressionMethod::STORE,
+ lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'),
+ );
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+ $files = $this->getRecursiveFileList($tmpDir);
+
+ $this->assertSame(['sample.json'], $files);
+ $this->assertFileDoesNotContain($this->tempfile, PackField::pack(
+ new PackField(format: 'V', value: 0x06064b50)
+ ));
+ }
+
+ /**
+ * @group slow
+ */
+ public function testAddLargeFileWithoutZip64WithoutZeroHeader(): void
+ {
+ $this->expectException(OverflowException::class);
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ enableZip64: false,
+ defaultEnableZeroHeader: false,
+ );
+
+ $zip->addFileFromPsr7Stream(
+ fileName: 'sample.json',
+ stream: new EndlessCycleStream('0'),
+ maxSize: 0x100000000,
+ compressionMethod: CompressionMethod::STORE,
+ lastModificationDateTime: new DateTimeImmutable('2022-01-01 01:01:01Z'),
+ );
+ }
+
+ public function testAddFileFromPsr7StreamWithOutputToPsr7Stream(): void
+ {
+ $psr7OutputStream = new ResourceStream($this->tempfileStream);
+
+ $zip = new ZipStream(
+ outputStream: $psr7OutputStream,
+ sendHttpHeaders: false,
+ );
+
+ $body = 'Sample String Data';
+ $response = new Response(200, [], $body);
+
+ $zip->addFileFromPsr7Stream(
+ fileName: 'sample.json',
+ stream: $response->getBody(),
+ compressionMethod: CompressionMethod::STORE,
+ );
+ $zip->finish();
+ $psr7OutputStream->close();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+ $files = $this->getRecursiveFileList($tmpDir);
+
+ $this->assertSame(['sample.json'], $files);
+ $this->assertStringEqualsFile($tmpDir . '/sample.json', $body);
+ }
+
+ public function testAddFileFromPsr7StreamWithFileSizeSet(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $body = 'Sample String Data';
+ $fileSize = strlen($body);
+ // Add fake padding
+ $fakePadding = "\0\0\0\0\0\0";
+ $response = new Response(200, [], $body . $fakePadding);
+
+ $zip->addFileFromPsr7Stream(
+ fileName: 'sample.json',
+ stream: $response->getBody(),
+ compressionMethod: CompressionMethod::STORE,
+ maxSize: $fileSize
+ );
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample.json'], $files);
+ $this->assertStringEqualsFile($tmpDir . '/sample.json', $body);
+ }
+
+ public function testCreateArchiveHeaders(): void
+ {
+ $headers = [];
+
+ $httpHeaderCallback = function (string $header) use (&$headers) {
+ $headers[] = $header;
+ };
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: true,
+ outputName: 'example.zip',
+ httpHeaderCallback: $httpHeaderCallback,
+ );
+
+ $zip->addFile(
+ fileName: 'sample.json',
+ data: 'foo',
+ );
+ $zip->finish();
+
+ $this->assertContains('Content-Type: application/x-zip', $headers);
+ $this->assertContains("Content-Disposition: attachment; filename*=UTF-8''example.zip", $headers);
+ $this->assertContains('Pragma: public', $headers);
+ $this->assertContains('Cache-Control: public, must-revalidate', $headers);
+ $this->assertContains('Content-Transfer-Encoding: binary', $headers);
+ }
+
+ public function testCreateArchiveWithFlushOptionSet(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ flushOutput: true,
+ sendHttpHeaders: false,
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data');
+ $zip->addFile('test/sample.txt', 'More Simple Sample Data');
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample.txt', 'test' . DIRECTORY_SEPARATOR . 'sample.txt'], $files);
+
+ $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data');
+ $this->assertStringEqualsFile($tmpDir . '/test/sample.txt', 'More Simple Sample Data');
+ }
+
+ public function testCreateArchiveWithOutputBufferingOffAndFlushOptionSet(): void
+ {
+ // WORKAROUND (1/2): remove phpunit's output buffer in order to run test without any buffering
+ ob_end_flush();
+ $this->assertSame(0, ob_get_level());
+
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ flushOutput: true,
+ sendHttpHeaders: false,
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data');
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+ $this->assertStringEqualsFile($tmpDir . '/sample.txt', 'Sample String Data');
+
+ // WORKAROUND (2/2): add back output buffering so that PHPUnit doesn't complain that it is missing
+ ob_start();
+ }
+
+ public function testAddEmptyDirectory(): void
+ {
+ $zip = new ZipStream(
+ outputStream: $this->tempfileStream,
+ sendHttpHeaders: false,
+ );
+
+ $zip->addDirectory('foo');
+
+ $zip->finish();
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir, includeDirectories: true);
+
+ $this->assertContains('foo', $files);
+
+ $this->assertFileExists($tmpDir . DIRECTORY_SEPARATOR . 'foo');
+ $this->assertDirectoryExists($tmpDir . DIRECTORY_SEPARATOR . 'foo');
+ }
+
+ public function testAddFileSimulate(): void
+ {
+ $create = function (OperationMode $operationMode): int {
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: $operationMode,
+ defaultEnableZeroHeader: true,
+ outputStream: $this->tempfileStream,
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data');
+ $zip->addFile('test/sample.txt', 'More Simple Sample Data');
+
+ return $zip->finish();
+ };
+
+
+ $sizeExpected = $create(OperationMode::NORMAL);
+ $sizeActual = $create(OperationMode::SIMULATE_LAX);
+
+ $this->assertEquals($sizeExpected, $sizeActual);
+ }
+
+ public function testAddFileSimulateWithMaxSize(): void
+ {
+ $create = function (OperationMode $operationMode): int {
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: $operationMode,
+ defaultCompressionMethod: CompressionMethod::STORE,
+ defaultEnableZeroHeader: true,
+ outputStream: $this->tempfileStream,
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data', maxSize: 0);
+
+ return $zip->finish();
+ };
+
+
+ $sizeExpected = $create(OperationMode::NORMAL);
+ $sizeActual = $create(OperationMode::SIMULATE_LAX);
+
+ $this->assertEquals($sizeExpected, $sizeActual);
+ }
+
+ public function testAddFileSimulateWithFstat(): void
+ {
+ $create = function (OperationMode $operationMode): int {
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: $operationMode,
+ defaultCompressionMethod: CompressionMethod::STORE,
+ defaultEnableZeroHeader: true,
+ outputStream: $this->tempfileStream,
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data');
+ $zip->addFile('test/sample.txt', 'More Simple Sample Data');
+
+ return $zip->finish();
+ };
+
+
+ $sizeExpected = $create(OperationMode::NORMAL);
+ $sizeActual = $create(OperationMode::SIMULATE_LAX);
+
+ $this->assertEquals($sizeExpected, $sizeActual);
+ }
+
+ public function testAddFileSimulateWithExactSizeZero(): void
+ {
+ $create = function (OperationMode $operationMode): int {
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: $operationMode,
+ defaultCompressionMethod: CompressionMethod::STORE,
+ defaultEnableZeroHeader: true,
+ outputStream: $this->tempfileStream,
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data', exactSize: 18);
+
+ return $zip->finish();
+ };
+
+
+ $sizeExpected = $create(OperationMode::NORMAL);
+ $sizeActual = $create(OperationMode::SIMULATE_LAX);
+
+ $this->assertEquals($sizeExpected, $sizeActual);
+ }
+
+ public function testAddFileSimulateWithExactSizeInitial(): void
+ {
+ $create = function (OperationMode $operationMode): int {
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: $operationMode,
+ defaultCompressionMethod: CompressionMethod::STORE,
+ defaultEnableZeroHeader: false,
+ outputStream: $this->tempfileStream,
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data', exactSize: 18);
+
+ return $zip->finish();
+ };
+
+ $sizeExpected = $create(OperationMode::NORMAL);
+ $sizeActual = $create(OperationMode::SIMULATE_LAX);
+
+ $this->assertEquals($sizeExpected, $sizeActual);
+ }
+
+ public function testAddFileSimulateWithZeroSizeInFstat(): void
+ {
+ $create = function (OperationMode $operationMode): int {
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: $operationMode,
+ defaultCompressionMethod: CompressionMethod::STORE,
+ defaultEnableZeroHeader: false,
+ outputStream: $this->tempfileStream,
+ );
+
+ $zip->addFileFromPsr7Stream('sample.txt', new class implements StreamInterface {
+ public $pos = 0;
+
+ public function __toString(): string
+ {
+ return 'test';
+ }
+
+ public function close(): void {}
+
+ public function detach() {}
+
+ public function getSize(): ?int
+ {
+ return null;
+ }
+
+ public function tell(): int
+ {
+ return $this->pos;
+ }
+
+ public function eof(): bool
+ {
+ return $this->pos >= 4;
+ }
+
+ public function isSeekable(): bool
+ {
+ return true;
+ }
+
+ public function seek(int $offset, int $whence = SEEK_SET): void
+ {
+ $this->pos = $offset;
+ }
+
+ public function rewind(): void
+ {
+ $this->pos = 0;
+ }
+
+ public function isWritable(): bool
+ {
+ return false;
+ }
+
+ public function write(string $string): int
+ {
+ return 0;
+ }
+
+ public function isReadable(): bool
+ {
+ return true;
+ }
+
+ public function read(int $length): string
+ {
+ $data = substr('test', $this->pos, $length);
+ $this->pos += strlen($data);
+ return $data;
+ }
+
+ public function getContents(): string
+ {
+ return $this->read(4);
+ }
+
+ public function getMetadata(?string $key = null)
+ {
+ return $key !== null ? null : [];
+ }
+ });
+
+ return $zip->finish();
+ };
+
+ $sizeExpected = $create(OperationMode::NORMAL);
+ $sizeActual = $create(OperationMode::SIMULATE_LAX);
+
+
+ $this->assertEquals($sizeExpected, $sizeActual);
+ }
+
+ public function testAddFileSimulateWithWrongExactSize(): void
+ {
+ $this->expectException(FileSizeIncorrectException::class);
+
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: OperationMode::SIMULATE_LAX,
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data', exactSize: 1000);
+ }
+
+ public function testAddFileSimulateStrictZero(): void
+ {
+ $this->expectException(SimulationFileUnknownException::class);
+
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: OperationMode::SIMULATE_STRICT,
+ defaultEnableZeroHeader: true
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data');
+ }
+
+ public function testAddFileSimulateStrictInitial(): void
+ {
+ $this->expectException(SimulationFileUnknownException::class);
+
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: OperationMode::SIMULATE_STRICT,
+ defaultEnableZeroHeader: false
+ );
+
+ $zip->addFile('sample.txt', 'Sample String Data');
+ }
+
+ public function testAddFileCallbackStrict(): void
+ {
+ $this->expectException(SimulationFileUnknownException::class);
+
+ $zip = new ZipStream(
+ sendHttpHeaders: false,
+ operationMode: OperationMode::SIMULATE_STRICT,
+ defaultEnableZeroHeader: false
+ );
+
+ $zip->addFileFromCallback('sample.txt', callback: function () {
+ return '';
+ });
+ }
+
+ public function testAddFileCallbackLax(): void
+ {
+ $zip = new ZipStream(
+ operationMode: OperationMode::SIMULATE_LAX,
+ defaultEnableZeroHeader: false,
+ sendHttpHeaders: false,
+ );
+
+ $zip->addFileFromCallback('sample.txt', callback: function () {
+ return 'Sample String Data';
+ });
+
+ $size = $zip->finish();
+
+ $this->assertEquals($size, 142);
+ }
+
+ public function testExecuteSimulation(): void
+ {
+ $zip = new ZipStream(
+ operationMode: OperationMode::SIMULATE_STRICT,
+ defaultCompressionMethod: CompressionMethod::STORE,
+ defaultEnableZeroHeader: false,
+ sendHttpHeaders: false,
+ outputStream: $this->tempfileStream,
+ );
+
+ $zip->addFileFromCallback(
+ 'sample.txt',
+ exactSize: 18,
+ callback: function () {
+ return 'Sample String Data';
+ }
+ );
+
+ $zip->addFileFromCallback(
+ '.gitkeep',
+ exactSize: 0,
+ callback: function () {
+ return '';
+ }
+ );
+
+ $size = $zip->finish();
+
+ $this->assertEquals(filesize($this->tempfile), 0);
+
+ $zip->executeSimulation();
+
+ clearstatcache();
+
+ $this->assertEquals(filesize($this->tempfile), $size);
+
+ $tmpDir = $this->validateAndExtractZip($this->tempfile);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['.gitkeep', 'sample.txt'], $files);
+ }
+
+ public function testExecuteSimulationBeforeFinish(): void
+ {
+ $this->expectException(RuntimeException::class);
+
+ $zip = new ZipStream(
+ operationMode: OperationMode::SIMULATE_LAX,
+ defaultEnableZeroHeader: false,
+ sendHttpHeaders: false,
+ outputStream: $this->tempfileStream,
+ );
+
+ $zip->executeSimulation();
+ }
+
+ private function addLargeFileFileFromPath(CompressionMethod $compressionMethod, $zeroHeader, $zip64): void
+ {
+ [$tmp, $stream] = $this->getTmpFileStream();
+
+ $zip = new ZipStream(
+ outputStream: $stream,
+ sendHttpHeaders: false,
+ defaultEnableZeroHeader: $zeroHeader,
+ enableZip64: $zip64,
+ );
+
+ [$tmpExample, $streamExample] = $this->getTmpFileStream();
+ for ($i = 0; $i <= 10000; $i++) {
+ fwrite($streamExample, sha1((string) $i));
+ if ($i % 100 === 0) {
+ fwrite($streamExample, "\n");
+ }
+ }
+ fclose($streamExample);
+ $shaExample = sha1_file($tmpExample);
+ $zip->addFileFromPath('sample.txt', $tmpExample);
+ unlink($tmpExample);
+
+ $zip->finish();
+ fclose($stream);
+
+ $tmpDir = $this->validateAndExtractZip($tmp);
+
+ $files = $this->getRecursiveFileList($tmpDir);
+ $this->assertSame(['sample.txt'], $files);
+
+ $this->assertSame(sha1_file($tmpDir . '/sample.txt'), $shaExample, "SHA-1 Mismatch Method: {$compressionMethod->value}");
+
+ unlink($tmp);
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php b/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php
new file mode 100644
index 000000000..2b8dbed4a
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/Zs/ExtendedInformationExtraFieldTest.php
@@ -0,0 +1,22 @@
+<?php
+
+declare(strict_types=1);
+
+namespace ZipStream\Test\Zs;
+
+use PHPUnit\Framework\TestCase;
+use ZipStream\Zs\ExtendedInformationExtraField;
+
+class ExtendedInformationExtraFieldTest extends TestCase
+{
+ public function testSerializesCorrectly(): void
+ {
+ $extraField = ExtendedInformationExtraField::generate();
+
+ $this->assertSame(
+ bin2hex((string) $extraField),
+ '5356' . // 2 bytes; Tag for this "extra" block type
+ '0000' // 2 bytes; TODO: Document
+ );
+ }
+}
diff --git a/vendor/maennchen/zipstream-php/test/bootstrap.php b/vendor/maennchen/zipstream-php/test/bootstrap.php
new file mode 100644
index 000000000..13c7a0e6c
--- /dev/null
+++ b/vendor/maennchen/zipstream-php/test/bootstrap.php
@@ -0,0 +1,7 @@
+<?php
+
+declare(strict_types=1);
+
+date_default_timezone_set('UTC');
+
+require __DIR__ . '/../vendor/autoload.php';
diff --git a/vendor/mikespub/php-epub-meta/.gitignore b/vendor/mikespub/php-epub-meta/.gitignore
new file mode 100644
index 000000000..d46f612cd
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/.gitignore
@@ -0,0 +1,8 @@
+coverage/
+vendor/
+clover.xml
+*.cache
+.pnp.cjs
+.yarn/
+yarn.lock
+.yarnrc.yml
diff --git a/vendor/mikespub/php-epub-meta/LICENSE b/vendor/mikespub/php-epub-meta/LICENSE
new file mode 100644
index 000000000..1b10fcb17
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2012 Andreas Gohr <andi@splitbrain.org>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/mikespub/php-epub-meta/README.md b/vendor/mikespub/php-epub-meta/README.md
new file mode 100644
index 000000000..2e5d76967
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/README.md
@@ -0,0 +1,54 @@
+PHP EPub Meta
+=============
+
+## Prerequisites for this fork
+
+- PHP 8.x with DOM, Json, XML, XMLWriter and ZLib support (PHP 8.1 or later recommended)
+- Release 2.x.x will only work with PHP >= 8.1 - typical for most source code & docker image installs in 2023 and later. *Note: updating .epub files for metadata or cover requires a 64-bit platform*
+- Release 1.x.x still works with PHP 7.4 if necessary - earlier PHP 7.x (or 5.x) versions are *not* supported with this fork
+
+This package is used by [mikespub/seblucas-cops](https://packagist.org/packages/mikespub/seblucas-cops) and [mikespub/epub-loader](https://packagist.org/packages/mikespub/epub-loader) with the same PHP version restrictions for 1.x and 2.x releases
+
+## PHP EPub Meta (original)
+
+This project aims to create a PHP class for reading and writing metadata
+included in the EPub ebook format.
+
+It also includes a very basic web interface to edit book metadata.
+
+Please see the issue tracker for what's missing.
+
+Forks and pull requests welcome.
+
+
+About the EPub Manager Web Interface
+------------------------------------
+
+The manager expects your ebooks in a single flat directory (no subfolders). The
+location of that directory has to be configured at the top of the index.php file.
+
+All the epubs need to be read- and writable by the webserver.
+
+The manager also makes some assumption on how the files should be named. The
+format is: `<Author file-as>-<Title>.epub`. Commas will be replaced by `__` and
+spaces are replaced by `_`.
+
+Note that the manager will **RENAME** your files to that form when saving.
+
+Using the "Lookup Book Data" link will open a dialog that searches the book at
+Google Books you can use the found data using the "fill in" and "replace"
+buttons. The former will only fill empty fields, while the latter will replace
+all data. Author filling is missing currently.
+
+
+Installing via Composer
+=======================
+
+You can use this package in your projects with [Composer](https://getcomposer.org/). Just
+add these lines to your project's `composer.json`:
+
+```
+ "require": {
+ "mikespub/php-epub-meta": "dev-main",
+ }
+```
diff --git a/vendor/mikespub/php-epub-meta/app/index.php b/vendor/mikespub/php-epub-meta/app/index.php
new file mode 100644
index 000000000..da8b369f4
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/app/index.php
@@ -0,0 +1,23 @@
+<?php
+/**
+ * PHP EPub Meta - App public entrypoint
+ *
+ * @author mikespub
+ */
+
+require_once dirname(__DIR__) . '/vendor/autoload.php';
+
+use SebLucas\EPubMeta\App\Handler;
+
+// modify this to point to your book directory
+$bookdir = '/home/andi/Dropbox/ebooks/';
+$bookdir = dirname(__DIR__) . '/test/data/';
+
+$handler = new Handler($bookdir);
+try {
+ $handler->handle();
+} catch (Throwable $e) {
+ error_log($e);
+ echo $e->getMessage();
+}
+return;
diff --git a/vendor/mikespub/php-epub-meta/assets/css/cleditor/images/buttons.gif b/vendor/mikespub/php-epub-meta/assets/css/cleditor/images/buttons.gif
new file mode 100644
index 000000000..2e464d0c8
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/cleditor/images/buttons.gif
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/cleditor/images/toolbar.gif b/vendor/mikespub/php-epub-meta/assets/css/cleditor/images/toolbar.gif
new file mode 100644
index 000000000..e6eb2da55
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/cleditor/images/toolbar.gif
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/cleditor/jquery.cleditor-1.4.5.css b/vendor/mikespub/php-epub-meta/assets/css/cleditor/jquery.cleditor-1.4.5.css
new file mode 100644
index 000000000..fa4481dcb
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/cleditor/jquery.cleditor-1.4.5.css
@@ -0,0 +1,26 @@
+.cleditorMain {border:1px solid #999; padding:0 1px 1px; background-color:white}
+.cleditorMain,
+.cleditorPopup,
+.cleditorMain * {-moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box}
+.cleditorMain iframe {border:none; margin:0; padding:0}
+.cleditorMain textarea {overflow-y:scroll; font:10pt Arial,Verdana; resize:none; outline:none}
+.cleditorToolbar {background: url('images/toolbar.gif') repeat}
+.cleditorGroup {float:left; height:26px}
+.cleditorButton {float:left; width:24px; height:24px; margin:1px 0 1px 0; background: url('images/buttons.gif')}
+.cleditorDisabled {opacity:0.3; filter:alpha(opacity=30)}
+.cleditorDivider {float:left; width:1px; height:23px; margin:1px 0 1px 0; background:#CCC}
+.cleditorPopup {border:solid 1px #999; background-color:white; color:#333333; position:absolute; font:10pt Arial,Verdana; cursor:default; z-index:10000}
+.cleditorList div {padding:2px 4px 2px 4px}
+.cleditorList p,
+.cleditorList h1,
+.cleditorList h2,
+.cleditorList h3,
+.cleditorList h4,
+.cleditorList h5,
+.cleditorList h6,
+.cleditorList font {padding:0; margin:0; background-color:Transparent}
+.cleditorColor {width:150px; padding:1px 0 0 1px}
+.cleditorColor div {float:left; width:14px; height:14px; margin:0 1px 1px 0}
+.cleditorPrompt {background-color:#F6F7F9; padding:8px; font-size:8.5pt}
+.cleditorPrompt label {padding-bottom:8px}
+.cleditorMsg {background-color:#FDFCEE; width:150px; padding:4px; font-size:8.5pt} \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 000000000..5b5dab2ab
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 000000000..ac8b229af
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 000000000..b8ed4fc24
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 000000000..c63ffb3f3
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 000000000..4303689ec
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 000000000..47cf83124
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 000000000..b0415457b
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 000000000..484447c14
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_222222_256x240.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_222222_256x240.png
new file mode 100644
index 000000000..2da698181
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_222222_256x240.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_2e83ff_256x240.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 000000000..22cd38e92
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_2e83ff_256x240.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_454545_256x240.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_454545_256x240.png
new file mode 100644
index 000000000..b1bcb2b69
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_454545_256x240.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_888888_256x240.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_888888_256x240.png
new file mode 100644
index 000000000..33ca2bea5
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_888888_256x240.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_cd0a0a_256x240.png b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 000000000..fa4ea8671
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/images/ui-icons_cd0a0a_256x240.png
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/assets/css/smoothness/jquery-ui-1.13.2.custom.min.css b/vendor/mikespub/php-epub-meta/assets/css/smoothness/jquery-ui-1.13.2.custom.min.css
new file mode 100644
index 000000000..5a8ca4a8c
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/smoothness/jquery-ui-1.13.2.custom.min.css
@@ -0,0 +1,7 @@
+/*! jQuery UI - v1.13.2 - 2023-09-10
+* http://jqueryui.com
+* Includes: draggable.css, core.css, resizable.css, selectable.css, sortable.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, progressbar.css, selectmenu.css, slider.css, spinner.css, tabs.css, tooltip.css, theme.css
+* To view and modify this theme, visit http://jqueryui.com/themeroller/?scope=&folderName=smoothness&cornerRadiusShadow=8px&offsetLeftShadow=-8px&offsetTopShadow=-8px&thicknessShadow=8px&opacityShadow=30&bgImgOpacityShadow=0&bgTextureShadow=flat&bgColorShadow=aaaaaa&opacityOverlay=30&bgImgOpacityOverlay=0&bgTextureOverlay=flat&bgColorOverlay=aaaaaa&iconColorError=cd0a0a&fcError=cd0a0a&borderColorError=cd0a0a&bgImgOpacityError=95&bgTextureError=glass&bgColorError=fef1ec&iconColorHighlight=2e83ff&fcHighlight=363636&borderColorHighlight=fcefa1&bgImgOpacityHighlight=55&bgTextureHighlight=glass&bgColorHighlight=fbf9ee&iconColorActive=454545&fcActive=212121&borderColorActive=aaaaaa&bgImgOpacityActive=65&bgTextureActive=glass&bgColorActive=ffffff&iconColorHover=454545&fcHover=212121&borderColorHover=999999&bgImgOpacityHover=75&bgTextureHover=glass&bgColorHover=dadada&iconColorDefault=888888&fcDefault=555555&borderColorDefault=d3d3d3&bgImgOpacityDefault=75&bgTextureDefault=glass&bgColorDefault=e6e6e6&iconColorContent=222222&fcContent=222222&borderColorContent=aaaaaa&bgImgOpacityContent=75&bgTextureContent=flat&bgColorContent=ffffff&iconColorHeader=222222&fcHeader=222222&borderColorHeader=aaaaaa&bgImgOpacityHeader=75&bgTextureHeader=highlight_soft&bgColorHeader=cccccc&cornerRadius=4px&fsDefault=1.1em&fwDefault=normal&ffDefault=Verdana%2CArial%2Csans-serif
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;-ms-filter:"alpha(opacity=0)"}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important;pointer-events:none}.ui-icon{display:inline-block;vertical-align:middle;margin-top:-.25em;position:relative;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-icon-block{left:50%;margin-left:-8px;display:block}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;font-size:100%}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:0}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{margin:0;cursor:pointer;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-item-wrapper{position:relative;padding:3px 1em 3px .4em}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item-wrapper{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-button{padding:.4em 1em;display:inline-block;position:relative;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2em;box-sizing:border-box;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-button-icon-only{text-indent:0}.ui-button-icon-only .ui-icon{position:absolute;top:50%;left:50%;margin-top:-8px;margin-left:-8px}.ui-button.ui-icon-notext .ui-icon{padding:0;width:2.1em;height:2.1em;text-indent:-9999px;white-space:nowrap}input.ui-button.ui-icon-notext .ui-icon{width:auto;height:auto;text-indent:0;white-space:normal;padding:.4em 1em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-controlgroup{vertical-align:middle;display:inline-block}.ui-controlgroup > .ui-controlgroup-item{float:left;margin-left:0;margin-right:0}.ui-controlgroup > .ui-controlgroup-item:focus,.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus{z-index:9999}.ui-controlgroup-vertical > .ui-controlgroup-item{display:block;float:none;width:100%;margin-top:0;margin-bottom:0;text-align:left}.ui-controlgroup-vertical .ui-controlgroup-item{box-sizing:border-box}.ui-controlgroup .ui-controlgroup-label{padding:.4em 1em}.ui-controlgroup .ui-controlgroup-label span{font-size:80%}.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item{border-left:none}.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item{border-top:none}.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content{border-right:none}.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content{border-bottom:none}.ui-controlgroup-vertical .ui-spinner-input{width:75%;width:calc( 100% - 2.4em )}.ui-controlgroup-vertical .ui-spinner .ui-spinner-up{border-top-style:solid}.ui-checkboxradio-label .ui-icon-background{box-shadow:inset 1px 1px 1px #ccc;border-radius:.12em;border:none}.ui-checkboxradio-radio-label .ui-icon-background{width:16px;height:16px;border-radius:1em;overflow:visible;border:none}.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon{background-image:none;width:8px;height:8px;border-width:4px;border-style:solid}.ui-checkboxradio-disabled{pointer-events:none}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:45%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:bold;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em .6em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-datepicker .ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat;left:.5em;top:.3em}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-n{height:2px;top:0}.ui-dialog .ui-resizable-e{width:2px;right:0}.ui-dialog .ui-resizable-s{height:2px;bottom:0}.ui-dialog .ui-resizable-w{width:2px;left:0}.ui-dialog .ui-resizable-se,.ui-dialog .ui-resizable-sw,.ui-dialog .ui-resizable-ne,.ui-dialog .ui-resizable-nw{width:7px;height:7px}.ui-dialog .ui-resizable-se{right:0;bottom:0}.ui-dialog .ui-resizable-sw{left:0;bottom:0}.ui-dialog .ui-resizable-ne{right:0;top:0}.ui-dialog .ui-resizable-nw{left:0;top:0}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;-ms-filter:"alpha(opacity=25)";opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-text{display:block;margin-right:20px;overflow:hidden;text-overflow:ellipsis}.ui-selectmenu-button.ui-button{text-align:left;white-space:nowrap;width:14em}.ui-selectmenu-icon.ui-icon{float:right;margin-top:0}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:pointer;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:.222em 0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:2em}.ui-spinner-button{width:1.6em;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top-style:none;border-bottom-style:none;border-right-style:none}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget.ui-widget-content{border:1px solid #d3d3d3}.ui-widget-content{border:1px solid #aaa;background:#fff;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,.ui-button,html .ui-button.ui-state-disabled:hover,html .ui-button.ui-state-disabled:active{border:1px solid #d3d3d3;background:#e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited,a.ui-button,a:link.ui-button,a:visited.ui-button,.ui-button{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus,.ui-button:hover,.ui-button:focus{border:1px solid #999;background:#dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited,.ui-state-focus a,.ui-state-focus a:hover,.ui-state-focus a:link,.ui-state-focus a:visited,a.ui-button:hover,a.ui-button:focus{color:#212121;text-decoration:none}.ui-visual-focus{box-shadow:0 0 3px 1px rgb(94,158,214)}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active,a.ui-button:active,.ui-button:active,.ui-button.ui-state-active:hover{border:1px solid #aaa;background:#fff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-icon-background,.ui-state-active .ui-icon-background{border:#aaa;background-color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x;color:#363636}.ui-state-checked{border:1px solid #fcefa1;background:#fbf9ee}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;-ms-filter:"alpha(opacity=70)";font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;-ms-filter:"alpha(opacity=35)";background-image:none}.ui-state-disabled .ui-icon{-ms-filter:"alpha(opacity=35)"}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-widget-header .ui-icon{background-image:url("images/ui-icons_222222_256x240.png")}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon,.ui-button:hover .ui-icon,.ui-button:focus .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-active .ui-icon,.ui-button:active .ui-icon{background-image:url("images/ui-icons_454545_256x240.png")}.ui-state-highlight .ui-icon,.ui-button .ui-state-highlight.ui-icon{background-image:url("images/ui-icons_2e83ff_256x240.png")}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url("images/ui-icons_cd0a0a_256x240.png")}.ui-button .ui-icon{background-image:url("images/ui-icons_888888_256x240.png")}.ui-icon-blank.ui-icon-blank.ui-icon-blank{background-image:none}.ui-icon-caret-1-n{background-position:0 0}.ui-icon-caret-1-ne{background-position:-16px 0}.ui-icon-caret-1-e{background-position:-32px 0}.ui-icon-caret-1-se{background-position:-48px 0}.ui-icon-caret-1-s{background-position:-65px 0}.ui-icon-caret-1-sw{background-position:-80px 0}.ui-icon-caret-1-w{background-position:-96px 0}.ui-icon-caret-1-nw{background-position:-112px 0}.ui-icon-caret-2-n-s{background-position:-128px 0}.ui-icon-caret-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-65px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-65px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:1px -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa;opacity:.3;-ms-filter:Alpha(Opacity=30)}.ui-widget-shadow{-webkit-box-shadow:-8px -8px 8px #aaa;box-shadow:-8px -8px 8px #aaa} \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/assets/css/style.css b/vendor/mikespub/php-epub-meta/assets/css/style.css
new file mode 100644
index 000000000..0e46dd1b0
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/css/style.css
@@ -0,0 +1,180 @@
+body, td, th, input, textarea {
+ font-family: "Arial", sans-serif;
+ color: #333;
+ font-size: 15px;
+}
+
+a {
+ color: #4183C4;
+ text-decoration: none;
+}
+
+a:hover,
+a:active {
+ background-color: #efefef;
+}
+
+#wrapper {
+ height: 95%;
+ width: 920px;
+ margin: auto;
+ padding: 0;
+ border: 1px solid #ccc;
+}
+
+#booklist {
+ float: left;
+ width: 300px;
+ height: 100%;
+ overflow: auto;
+ list-style-type: none;
+ padding: 0;
+ margin: 0 25px 0 0;
+ font-size: 13px;
+}
+
+#booklist li {
+ padding: 5px;
+}
+
+#booklist li:hover {
+ background-color: #efefef;
+}
+
+#booklist li span {
+ display: block;
+}
+#booklist li span.author {
+ padding-left: 5px;
+ font-size: 11px;
+}
+
+#booklist li.active {
+ background-color: #4183C4;
+}
+#booklist li.active a,
+#booklist li.active a:hover,
+#booklist li.active a:active {
+ color: #efefef;
+ background-color: #4183C4;
+}
+
+
+#bookpanel {
+ float: left;
+ width: 590px;
+ height: 100%;
+ overflow: auto;
+}
+
+.center {
+ text-align: center;
+}
+
+table {
+ margin-bottom: 20px;
+}
+
+table th,
+table td {
+ vertical-align: top;
+ padding: 0 0 5px 0;
+}
+
+table th {
+ text-align: right;
+ font-weight: bold;
+ padding: 3px;
+ padding-right: 20px;
+}
+
+table td textarea,
+table td input {
+ width: 450px;
+ border: none;
+ padding: 3px;
+ margin: 0;
+ border-bottom: solid 1px #dfdfdf;
+}
+
+table td .cleditormain {
+ border: solid 1px #dfdfdf;
+}
+
+table td textarea {
+ height: 250px;
+}
+
+table td p {
+ margin: 0;
+ padding: 0;
+}
+
+table td p input {
+ width: 200px;
+}
+
+table td textarea:focus,
+table td input:focus {
+ border: 1px solid #4183C4;
+}
+
+table th img {
+ margin-top: 20px;
+}
+
+a.addauthor {
+ margin-top: -20px;
+ float: right;
+}
+
+div.license {
+ font-size: 11px;
+ margin-top: 300px;
+}
+
+#bookapi-s {
+ float: left;
+}
+
+#bookapi-q {
+ width: 600px;
+}
+
+#bookapi {
+ font-size: 12px;
+}
+
+#bookapi div.head {
+ margin-bottom: 10px;
+}
+
+#bookapi div.result {
+ clear: both;
+ margin-bottom: 10px;
+ border-bottom: 1px solid #ccc;
+ min-height: 130px;
+}
+
+#bookapi div.result div {
+ margin-left: 70px;
+}
+
+#bookapi div.result div.buttons {
+ float: right;
+ text-align: right;
+}
+
+#bookapi img {
+ margin-top: 30px;
+ width: 60px;
+ float: left;
+}
+
+#bookapi h1.title {
+ font-size: 14px;
+}
+
+#bookapi span.subjects {
+ font-style: italic;
+}
diff --git a/vendor/mikespub/php-epub-meta/assets/js/jquery-3.7.1.min.js b/vendor/mikespub/php-epub-meta/assets/js/jquery-3.7.1.min.js
new file mode 100644
index 000000000..7f37b5d99
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/js/jquery-3.7.1.min.js
@@ -0,0 +1,2 @@
+/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */
+!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}function fe(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}ce.fn=ce.prototype={jquery:t,constructor:ce,length:0,toArray:function(){return ae.call(this)},get:function(e){return null==e?ae.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=ce.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return ce.each(this,e)},map:function(n){return this.pushStack(ce.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(ae.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(ce.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(ce.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:s,sort:oe.sort,splice:oe.splice},ce.extend=ce.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||v(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(ce.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||ce.isPlainObject(n)?n:{},i=!1,a[t]=ce.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},ce.extend({expando:"jQuery"+(t+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==i.call(e))&&(!(t=r(e))||"function"==typeof(n=ue.call(t,"constructor")&&t.constructor)&&o.call(n)===a)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){m(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(c(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},text:function(e){var t,n="",r=0,i=e.nodeType;if(!i)while(t=e[r++])n+=ce.text(t);return 1===i||11===i?e.textContent:9===i?e.documentElement.textContent:3===i||4===i?e.nodeValue:n},makeArray:function(e,t){var n=t||[];return null!=e&&(c(Object(e))?ce.merge(n,"string"==typeof e?[e]:e):s.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:se.call(t,e,n)},isXMLDoc:function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!l.test(t||n&&n.nodeName||"HTML")},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(c(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:le}),"function"==typeof Symbol&&(ce.fn[Symbol.iterator]=oe[Symbol.iterator]),ce.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var pe=oe.pop,de=oe.sort,he=oe.splice,ge="[\\x20\\t\\r\\n\\f]",ve=new RegExp("^"+ge+"+|((?:^|[^\\\\])(?:\\\\.)*)"+ge+"+$","g");ce.contains=function(e,t){var n=t&&t.parentNode;return e===n||!(!n||1!==n.nodeType||!(e.contains?e.contains(n):e.compareDocumentPosition&&16&e.compareDocumentPosition(n)))};var f=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;function p(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e}ce.escapeSelector=function(e){return(e+"").replace(f,p)};var ye=C,me=s;!function(){var e,b,w,o,a,T,r,C,d,i,k=me,S=ce.expando,E=0,n=0,s=W(),c=W(),u=W(),h=W(),l=function(e,t){return e===t&&(a=!0),0},f="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",t="(?:\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",p="\\["+ge+"*("+t+")(?:"+ge+"*([*^$|!~]?=)"+ge+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+t+"))|)"+ge+"*\\]",g=":("+t+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+p+")*)|.*)\\)|)",v=new RegExp(ge+"+","g"),y=new RegExp("^"+ge+"*,"+ge+"*"),m=new RegExp("^"+ge+"*([>+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="<a id='"+S+"' href='' disabled='disabled'></a><select id='"+S+"-\r\\' disabled='disabled'><option selected=''></option></select>",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0<I(t,T,null,[e]).length},I.contains=function(e,t){return(e.ownerDocument||e)!=T&&V(e),ce.contains(e,t)},I.attr=function(e,t){(e.ownerDocument||e)!=T&&V(e);var n=b.attrHandle[t.toLowerCase()],r=n&&ue.call(b.attrHandle,t.toLowerCase())?n(e,t,!C):void 0;return void 0!==r?r:e.getAttribute(t)},I.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},ce.uniqueSort=function(e){var t,n=[],r=0,i=0;if(a=!le.sortStable,o=!le.sortStable&&ae.call(e,0),de.call(e,l),a){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)he.call(e,n[r],1)}return o=null,e},ce.fn.uniqueSort=function(){return this.pushStack(ce.uniqueSort(ae.apply(this)))},(b=ce.expr={cacheLength:50,createPseudo:F,match:D,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(v," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(d,e,t,h,g){var v="nth"!==d.slice(0,3),y="last"!==d.slice(-4),m="of-type"===e;return 1===h&&0===g?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u=v!==y?"nextSibling":"previousSibling",l=e.parentNode,c=m&&e.nodeName.toLowerCase(),f=!n&&!m,p=!1;if(l){if(v){while(u){o=e;while(o=o[u])if(m?fe(o,c):1===o.nodeType)return!1;s=u="only"===d&&!s&&"nextSibling"}return!0}if(s=[y?l.firstChild:l.lastChild],y&&f){p=(a=(r=(i=l[S]||(l[S]={}))[d]||[])[0]===E&&r[1])&&r[2],o=a&&l.childNodes[a];while(o=++a&&o&&o[u]||(p=a=0)||s.pop())if(1===o.nodeType&&++p&&o===e){i[d]=[E,a,p];break}}else if(f&&(p=a=(r=(i=e[S]||(e[S]={}))[d]||[])[0]===E&&r[1]),!1===p)while(o=++a&&o&&o[u]||(p=a=0)||s.pop())if((m?fe(o,c):1===o.nodeType)&&++p&&(f&&((i=o[S]||(o[S]={}))[d]=[E,p]),o===e))break;return(p-=g)===h||p%h==0&&0<=p/h}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||I.error("unsupported pseudo: "+e);return a[S]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?F(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=se.call(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:F(function(e){var r=[],i=[],s=ne(e.replace(ve,"$1"));return s[S]?F(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:F(function(t){return function(e){return 0<I(t,e).length}}),contains:F(function(t){return t=t.replace(O,P),function(e){return-1<(e.textContent||ce.text(e)).indexOf(t)}}),lang:F(function(n){return A.test(n||"")||I.error("unsupported lang: "+n),n=n.replace(O,P).toLowerCase(),function(e){var t;do{if(t=C?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=ie.location&&ie.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===r},focus:function(e){return e===function(){try{return T.activeElement}catch(e){}}()&&T.hasFocus()&&!!(e.type||e.href||~e.tabIndex)},enabled:z(!1),disabled:z(!0),checked:function(e){return fe(e,"input")&&!!e.checked||fe(e,"option")&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return q.test(e.nodeName)},input:function(e){return N.test(e.nodeName)},button:function(e){return fe(e,"input")&&"button"===e.type||fe(e,"button")},text:function(e){var t;return fe(e,"input")&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:X(function(){return[0]}),last:X(function(e,t){return[t-1]}),eq:X(function(e,t,n){return[n<0?n+t:n]}),even:X(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:X(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:X(function(e,t,n){var r;for(r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:X(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=B(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=_(e);function G(){}function Y(e,t){var n,r,i,o,a,s,u,l=c[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=y.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=m.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace(ve," ")}),a=a.slice(n.length)),b.filter)!(r=D[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?I.error(e):c(e,s).slice(0)}function Q(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function J(a,e,t){var s=e.dir,u=e.next,l=u||s,c=t&&"parentNode"===l,f=n++;return e.first?function(e,t,n){while(e=e[s])if(1===e.nodeType||c)return a(e,t,n);return!1}:function(e,t,n){var r,i,o=[E,f];if(n){while(e=e[s])if((1===e.nodeType||c)&&a(e,t,n))return!0}else while(e=e[s])if(1===e.nodeType||c)if(i=e[S]||(e[S]={}),u&&fe(e,u))e=e[s]||e;else{if((r=i[l])&&r[0]===E&&r[1]===f)return o[2]=r[2];if((i[l]=o)[2]=a(e,t,n))return!0}return!1}}function K(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Z(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function ee(d,h,g,v,y,e){return v&&!v[S]&&(v=ee(v)),y&&!y[S]&&(y=ee(y,e)),F(function(e,t,n,r){var i,o,a,s,u=[],l=[],c=t.length,f=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)I(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),p=!d||!e&&h?f:Z(f,u,d,n,r);if(g?g(p,s=y||(e?d:c||v)?[]:t,n,r):s=p,v){i=Z(s,l),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(s[l[o]]=!(p[l[o]]=a))}if(e){if(y||d){if(y){i=[],o=s.length;while(o--)(a=s[o])&&i.push(p[o]=a);y(null,s=[],i,r)}o=s.length;while(o--)(a=s[o])&&-1<(i=y?se.call(e,a):u[o])&&(e[i]=!(t[i]=a))}}else s=Z(s===t?s.splice(c,s.length):s),y?y(null,t,s,r):k.apply(t,s)})}function te(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=J(function(e){return e===i},a,!0),l=J(function(e){return-1<se.call(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!=w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[J(K(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[S]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return ee(1<s&&K(c),1<s&&Q(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace(ve,"$1"),t,s<n&&te(e.slice(s,n)),n<r&&te(e=e.slice(n)),n<r&&Q(e))}c.push(t)}return K(c)}function ne(e,t){var n,v,y,m,x,r,i=[],o=[],a=u[e+" "];if(!a){t||(t=Y(e)),n=t.length;while(n--)(a=te(t[n]))[S]?i.push(a):o.push(a);(a=u(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=E+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t==T||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument==T||(V(o),n=!C);while(s=v[a++])if(s(o,t||T,n)){k.call(r,o);break}i&&(E=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=pe.call(r));f=Z(f)}k.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&ce.uniqueSort(r)}return i&&(E=h,w=p),c},m?F(r):r))).selector=e}return a}function re(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&Y(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&C&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(O,P),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=D.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(O,P),H.test(o[0].type)&&U(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&Q(o)))return k.apply(n,r),n;break}}}return(l||ne(e,c))(r,t,!C,n,!t||H.test(e)&&U(t.parentNode)||t),n}G.prototype=b.filters=b.pseudos,b.setFilters=new G,le.sortStable=S.split("").sort(l).join("")===S,V(),le.sortDetached=$(function(e){return 1&e.compareDocumentPosition(T.createElement("fieldset"))}),ce.find=I,ce.expr[":"]=ce.expr.pseudos,ce.unique=ce.uniqueSort,I.compile=ne,I.select=re,I.setDocument=V,I.tokenize=Y,I.escape=ce.escapeSelector,I.getText=ce.text,I.isXML=ce.isXMLDoc,I.selectors=ce.expr,I.support=ce.support,I.uniqueSort=ce.uniqueSort}();var d=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&ce(e).is(n))break;r.push(e)}return r},h=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},b=ce.expr.match.needsContext,w=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1<se.call(n,e)!==r}):ce.filter(n,e,r)}ce.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?ce.find.matchesSelector(r,e)?[r]:[]:ce.find.matches(e,ce.grep(t,function(e){return 1===e.nodeType}))},ce.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(ce(e).filter(function(){for(t=0;t<r;t++)if(ce.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)ce.find(e,i[t],n);return 1<r?ce.uniqueSort(n):n},filter:function(e){return this.pushStack(T(this,e||[],!1))},not:function(e){return this.pushStack(T(this,e||[],!0))},is:function(e){return!!T(this,"string"==typeof e&&b.test(e)?ce(e):e||[],!1).length}});var k,S=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(ce.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&ce(e);if(!b.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&ce.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?ce.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?se.call(ce(e),this[0]):se.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(ce.uniqueSort(ce.merge(this.get(),ce(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),ce.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return d(e,"parentNode")},parentsUntil:function(e,t,n){return d(e,"parentNode",n)},next:function(e){return A(e,"nextSibling")},prev:function(e){return A(e,"previousSibling")},nextAll:function(e){return d(e,"nextSibling")},prevAll:function(e){return d(e,"previousSibling")},nextUntil:function(e,t,n){return d(e,"nextSibling",n)},prevUntil:function(e,t,n){return d(e,"previousSibling",n)},siblings:function(e){return h((e.parentNode||{}).firstChild,e)},children:function(e){return h(e.firstChild)},contents:function(e){return null!=e.contentDocument&&r(e.contentDocument)?e.contentDocument:(fe(e,"template")&&(e=e.content||e),ce.merge([],e.childNodes))}},function(r,i){ce.fn[r]=function(e,t){var n=ce.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=ce.filter(t,n)),1<this.length&&(j[r]||ce.uniqueSort(n),E.test(r)&&n.reverse()),this.pushStack(n)}});var D=/[^\x20\t\r\n\f]+/g;function N(e){return e}function q(e){throw e}function L(e,t,n,r){var i;try{e&&v(i=e.promise)?i.call(e).done(t).fail(n):e&&v(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}ce.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},ce.each(e.match(D)||[],function(e,t){n[t]=!0}),n):ce.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){ce.each(e,function(e,t){v(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==x(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return ce.each(arguments,function(e,t){var n;while(-1<(n=ce.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<ce.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},ce.extend({Deferred:function(e){var o=[["notify","progress",ce.Callbacks("memory"),ce.Callbacks("memory"),2],["resolve","done",ce.Callbacks("once memory"),ce.Callbacks("once memory"),0,"resolved"],["reject","fail",ce.Callbacks("once memory"),ce.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return ce.Deferred(function(r){ce.each(o,function(e,t){var n=v(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&v(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,v(t)?s?t.call(e,l(u,o,N,s),l(u,o,q,s)):(u++,t.call(e,l(u,o,N,s),l(u,o,q,s),l(u,o,N,o.notifyWith))):(a!==N&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){ce.Deferred.exceptionHook&&ce.Deferred.exceptionHook(e,t.error),u<=i+1&&(a!==q&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(ce.Deferred.getErrorHook?t.error=ce.Deferred.getErrorHook():ce.Deferred.getStackHook&&(t.error=ce.Deferred.getStackHook()),ie.setTimeout(t))}}return ce.Deferred(function(e){o[0][3].add(l(0,e,v(r)?r:N,e.notifyWith)),o[1][3].add(l(0,e,v(t)?t:N)),o[2][3].add(l(0,e,v(n)?n:q))}).promise()},promise:function(e){return null!=e?ce.extend(e,a):a}},s={};return ce.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=ae.call(arguments),o=ce.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?ae.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(L(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||v(i[t]&&i[t].then)))return o.then();while(t--)L(i[t],a(t),o.reject);return o.promise()}});var H=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;ce.Deferred.exceptionHook=function(e,t){ie.console&&ie.console.warn&&e&&H.test(e.name)&&ie.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},ce.readyException=function(e){ie.setTimeout(function(){throw e})};var O=ce.Deferred();function P(){C.removeEventListener("DOMContentLoaded",P),ie.removeEventListener("load",P),ce.ready()}ce.fn.ready=function(e){return O.then(e)["catch"](function(e){ce.readyException(e)}),this},ce.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--ce.readyWait:ce.isReady)||(ce.isReady=!0)!==e&&0<--ce.readyWait||O.resolveWith(C,[ce])}}),ce.ready.then=O.then,"complete"===C.readyState||"loading"!==C.readyState&&!C.documentElement.doScroll?ie.setTimeout(ce.ready):(C.addEventListener("DOMContentLoaded",P),ie.addEventListener("load",P));var M=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===x(n))for(s in i=!0,n)M(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,v(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(ce(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},R=/^-ms-/,I=/-([a-z])/g;function W(e,t){return t.toUpperCase()}function F(e){return e.replace(R,"ms-").replace(I,W)}var $=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function B(){this.expando=ce.expando+B.uid++}B.uid=1,B.prototype={cache:function(e){var t=e[this.expando];return t||(t={},$(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[F(t)]=n;else for(r in t)i[F(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][F(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(F):(t=F(t))in r?[t]:t.match(D)||[]).length;while(n--)delete r[t[n]]}(void 0===t||ce.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!ce.isEmptyObject(t)}};var _=new B,z=new B,X=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,U=/[A-Z]/g;function V(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(U,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:X.test(i)?JSON.parse(i):i)}catch(e){}z.set(e,t,n)}else n=void 0;return n}ce.extend({hasData:function(e){return z.hasData(e)||_.hasData(e)},data:function(e,t,n){return z.access(e,t,n)},removeData:function(e,t){z.remove(e,t)},_data:function(e,t,n){return _.access(e,t,n)},_removeData:function(e,t){_.remove(e,t)}}),ce.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=z.get(o),1===o.nodeType&&!_.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=F(r.slice(5)),V(o,r,i[r]));_.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){z.set(this,n)}):M(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=z.get(o,n))?t:void 0!==(t=V(o,n))?t:void 0;this.each(function(){z.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){z.remove(this,e)})}}),ce.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=_.get(e,t),n&&(!r||Array.isArray(n)?r=_.access(e,t,ce.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=ce.queue(e,t),r=n.length,i=n.shift(),o=ce._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){ce.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return _.get(e,n)||_.access(e,n,{empty:ce.Callbacks("once memory").add(function(){_.remove(e,[t+"queue",n])})})}}),ce.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?ce.queue(this[0],t):void 0===n?this:this.each(function(){var e=ce.queue(this,t,n);ce._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&ce.dequeue(this,t)})},dequeue:function(e){return this.each(function(){ce.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=ce.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=_.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var G=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,Y=new RegExp("^(?:([+-])=|)("+G+")([a-z%]*)$","i"),Q=["Top","Right","Bottom","Left"],J=C.documentElement,K=function(e){return ce.contains(e.ownerDocument,e)},Z={composed:!0};J.getRootNode&&(K=function(e){return ce.contains(e.ownerDocument,e)||e.getRootNode(Z)===e.ownerDocument});var ee=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&K(e)&&"none"===ce.css(e,"display")};function te(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return ce.css(e,t,"")},u=s(),l=n&&n[3]||(ce.cssNumber[t]?"":"px"),c=e.nodeType&&(ce.cssNumber[t]||"px"!==l&&+u)&&Y.exec(ce.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)ce.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,ce.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ne={};function re(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=_.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&ee(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ne[s])||(o=a.body.appendChild(a.createElement(s)),u=ce.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ne[s]=u)))):"none"!==n&&(l[c]="none",_.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}ce.fn.extend({show:function(){return re(this,!0)},hide:function(){return re(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ee(this)?ce(this).show():ce(this).hide()})}});var xe,be,we=/^(?:checkbox|radio)$/i,Te=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="<textarea>x</textarea>",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="<option></option>",le.option=!!xe.lastChild;var ke={thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n<r;n++)_.set(e[n],"globalEval",!t||_.get(t[n],"globalEval"))}ke.tbody=ke.tfoot=ke.colgroup=ke.caption=ke.thead,ke.th=ke.td,le.option||(ke.optgroup=ke.option=[1,"<select multiple='multiple'>","</select>"]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===x(o))ce.merge(p,o.nodeType?[o]:o);else if(je.test(o)){a=a||f.appendChild(t.createElement("div")),s=(Te.exec(o)||["",""])[1].toLowerCase(),u=ke[s]||ke._default,a.innerHTML=u[1]+ce.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;ce.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<ce.inArray(o,r))i&&i.push(o);else if(l=K(o),a=Se(f.appendChild(o),"script"),l&&Ee(a),n){c=0;while(o=a[c++])Ce.test(o.type||"")&&n.push(o)}return f}var De=/^([^.]*)(?:\.(.+)|)/;function Ne(){return!0}function qe(){return!1}function Le(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)Le(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=qe;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return ce().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=ce.guid++)),e.each(function(){ce.event.add(this,t,i,r,n)})}function He(e,r,t){t?(_.set(e,r,!1),ce.event.add(e,r,{namespace:!1,handler:function(e){var t,n=_.get(this,r);if(1&e.isTrigger&&this[r]){if(n)(ce.event.special[r]||{}).delegateType&&e.stopPropagation();else if(n=ae.call(arguments),_.set(this,r,n),this[r](),t=_.get(this,r),_.set(this,r,!1),n!==t)return e.stopImmediatePropagation(),e.preventDefault(),t}else n&&(_.set(this,r,ce.event.trigger(n[0],n.slice(1),this)),e.stopPropagation(),e.isImmediatePropagationStopped=Ne)}})):void 0===_.get(e,r)&&ce.event.add(e,r,Ne)}ce.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=_.get(t);if($(t)){n.handler&&(n=(o=n).handler,i=o.selector),i&&ce.find.matchesSelector(J,i),n.guid||(n.guid=ce.guid++),(u=v.events)||(u=v.events=Object.create(null)),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof ce&&ce.event.triggered!==e.type?ce.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(D)||[""]).length;while(l--)d=g=(s=De.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=ce.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=ce.event.special[d]||{},c=ce.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&ce.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),ce.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=_.hasData(e)&&_.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(D)||[""]).length;while(l--)if(d=g=(s=De.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=ce.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||ce.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)ce.event.remove(e,d+t[l],n,r,!0);ce.isEmptyObject(u)&&_.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=new Array(arguments.length),u=ce.event.fix(e),l=(_.get(this,"events")||Object.create(null))[u.type]||[],c=ce.event.special[u.type]||{};for(s[0]=u,t=1;t<arguments.length;t++)s[t]=arguments[t];if(u.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,u)){a=ce.event.handlers.call(this,u,l),t=0;while((i=a[t++])&&!u.isPropagationStopped()){u.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!u.isImmediatePropagationStopped())u.rnamespace&&!1!==o.namespace&&!u.rnamespace.test(o.namespace)||(u.handleObj=o,u.data=o.data,void 0!==(r=((ce.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s))&&!1===(u.result=r)&&(u.preventDefault(),u.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,u),u.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<ce(i,this).index(l):ce.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(ce.Event.prototype,t,{enumerable:!0,configurable:!0,get:v(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[ce.expando]?e:new ce.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return we.test(t.type)&&t.click&&fe(t,"input")&&He(t,"click",!0),!1},trigger:function(e){var t=this||e;return we.test(t.type)&&t.click&&fe(t,"input")&&He(t,"click"),!0},_default:function(e){var t=e.target;return we.test(t.type)&&t.click&&fe(t,"input")&&_.get(t,"click")||fe(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},ce.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},ce.Event=function(e,t){if(!(this instanceof ce.Event))return new ce.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ne:qe,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&ce.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[ce.expando]=!0},ce.Event.prototype={constructor:ce.Event,isDefaultPrevented:qe,isPropagationStopped:qe,isImmediatePropagationStopped:qe,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ne,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ne,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ne,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},ce.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:!0},ce.event.addProp),ce.each({focus:"focusin",blur:"focusout"},function(r,i){function o(e){if(C.documentMode){var t=_.get(this,"handle"),n=ce.event.fix(e);n.type="focusin"===e.type?"focus":"blur",n.isSimulated=!0,t(e),n.target===n.currentTarget&&t(n)}else ce.event.simulate(i,e.target,ce.event.fix(e))}ce.event.special[r]={setup:function(){var e;if(He(this,r,!0),!C.documentMode)return!1;(e=_.get(this,i))||this.addEventListener(i,o),_.set(this,i,(e||0)+1)},trigger:function(){return He(this,r),!0},teardown:function(){var e;if(!C.documentMode)return!1;(e=_.get(this,i)-1)?_.set(this,i,e):(this.removeEventListener(i,o),_.remove(this,i))},_default:function(e){return _.get(e.target,r)},delegateType:i},ce.event.special[i]={setup:function(){var e=this.ownerDocument||this.document||this,t=C.documentMode?this:e,n=_.get(t,i);n||(C.documentMode?this.addEventListener(i,o):e.addEventListener(r,o,!0)),_.set(t,i,(n||0)+1)},teardown:function(){var e=this.ownerDocument||this.document||this,t=C.documentMode?this:e,n=_.get(t,i)-1;n?_.set(t,i,n):(C.documentMode?this.removeEventListener(i,o):e.removeEventListener(r,o,!0),_.remove(t,i))}}}),ce.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){ce.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||ce.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),ce.fn.extend({on:function(e,t,n,r){return Le(this,e,t,n,r)},one:function(e,t,n,r){return Le(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,ce(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=qe),this.each(function(){ce.event.remove(this,e,n,t)})}});var Oe=/<script|<style|<link/i,Pe=/checked\s*(?:[^=]|=\s*.checked.)/i,Me=/^\s*<!\[CDATA\[|\]\]>\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n<r;n++)ce.event.add(t,i,s[i][n]);z.hasData(e)&&(o=z.access(e),a=ce.extend({},o),z.set(t,a))}}function $e(n,r,i,o){r=g(r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=v(d);if(h||1<f&&"string"==typeof d&&!le.checkClone&&Pe.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),$e(t,r,i,o)});if(f&&(t=(e=Ae(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=ce.map(Se(e,"script"),Ie)).length;c<f;c++)u=e,c!==p&&(u=ce.clone(u,!0,!0),s&&ce.merge(a,Se(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,ce.map(a,We),c=0;c<s;c++)u=a[c],Ce.test(u.type||"")&&!_.access(u,"globalEval")&&ce.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?ce._evalUrl&&!u.noModule&&ce._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")},l):m(u.textContent.replace(Me,""),u,l))}return n}function Be(e,t,n){for(var r,i=t?ce.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||ce.cleanData(Se(r)),r.parentNode&&(n&&K(r)&&Ee(Se(r,"script")),r.parentNode.removeChild(r));return e}ce.extend({htmlPrefilter:function(e){return e},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=K(e);if(!(le.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||ce.isXMLDoc(e)))for(a=Se(c),r=0,i=(o=Se(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&we.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||Se(e),a=a||Se(c),r=0,i=o.length;r<i;r++)Fe(o[r],a[r]);else Fe(e,c);return 0<(a=Se(c,"script")).length&&Ee(a,!f&&Se(e,"script")),c},cleanData:function(e){for(var t,n,r,i=ce.event.special,o=0;void 0!==(n=e[o]);o++)if($(n)){if(t=n[_.expando]){if(t.events)for(r in t.events)i[r]?ce.event.remove(n,r):ce.removeEvent(n,r,t.handle);n[_.expando]=void 0}n[z.expando]&&(n[z.expando]=void 0)}}}),ce.fn.extend({detach:function(e){return Be(this,e,!0)},remove:function(e){return Be(this,e)},text:function(e){return M(this,function(e){return void 0===e?ce.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return $e(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||Re(this,e).appendChild(e)})},prepend:function(){return $e(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Re(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return $e(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return $e(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(ce.cleanData(Se(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return ce.clone(this,e,t)})},html:function(e){return M(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Oe.test(e)&&!ke[(Te.exec(e)||["",""])[1].toLowerCase()]){e=ce.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(ce.cleanData(Se(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return $e(this,arguments,function(e){var t=this.parentNode;ce.inArray(this,n)<0&&(ce.cleanData(Se(this)),t&&t.replaceChild(e,this))},n)}}),ce.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){ce.fn[e]=function(e){for(var t,n=[],r=ce(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),ce(r[o])[a](t),s.apply(n,t.get());return this.pushStack(n)}});var _e=new RegExp("^("+G+")(?!px)[a-z%]+$","i"),ze=/^--/,Xe=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=ie),t.getComputedStyle(e)},Ue=function(e,t,n){var r,i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.call(e),t)e.style[i]=o[i];return r},Ve=new RegExp(Q.join("|"),"i");function Ge(e,t,n){var r,i,o,a,s=ze.test(t),u=e.style;return(n=n||Xe(e))&&(a=n.getPropertyValue(t)||n[t],s&&a&&(a=a.replace(ve,"$1")||void 0),""!==a||K(e)||(a=ce.style(e,t)),!le.pixelBoxStyles()&&_e.test(a)&&Ve.test(t)&&(r=u.width,i=u.minWidth,o=u.maxWidth,u.minWidth=u.maxWidth=u.width=a,a=n.width,u.width=r,u.minWidth=i,u.maxWidth=o)),void 0!==a?a+"":a}function Ye(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(l){u.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",l.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",J.appendChild(u).appendChild(l);var e=ie.getComputedStyle(l);n="1%"!==e.top,s=12===t(e.marginLeft),l.style.right="60%",o=36===t(e.right),r=36===t(e.width),l.style.position="absolute",i=12===t(l.offsetWidth/3),J.removeChild(u),l=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s,u=C.createElement("div"),l=C.createElement("div");l.style&&(l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",le.clearCloneStyle="content-box"===l.style.backgroundClip,ce.extend(le,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),s},scrollboxSize:function(){return e(),i},reliableTrDimensions:function(){var e,t,n,r;return null==a&&(e=C.createElement("table"),t=C.createElement("tr"),n=C.createElement("div"),e.style.cssText="position:absolute;left:-11111px;border-collapse:separate",t.style.cssText="box-sizing:content-box;border:1px solid",t.style.height="1px",n.style.height="9px",n.style.display="block",J.appendChild(e).appendChild(t).appendChild(n),r=ie.getComputedStyle(t),a=parseInt(r.height,10)+parseInt(r.borderTopWidth,10)+parseInt(r.borderBottomWidth,10)===t.offsetHeight,J.removeChild(e)),a}}))}();var Qe=["Webkit","Moz","ms"],Je=C.createElement("div").style,Ke={};function Ze(e){var t=ce.cssProps[e]||Ke[e];return t||(e in Je?e:Ke[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=Qe.length;while(n--)if((e=Qe[n]+t)in Je)return e}(e)||e)}var et=/^(none|table(?!-c[ea]).+)/,tt={position:"absolute",visibility:"hidden",display:"block"},nt={letterSpacing:"0",fontWeight:"400"};function rt(e,t,n){var r=Y.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function it(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0,l=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(l+=ce.css(e,n+Q[a],!0,i)),r?("content"===n&&(u-=ce.css(e,"padding"+Q[a],!0,i)),"margin"!==n&&(u-=ce.css(e,"border"+Q[a]+"Width",!0,i))):(u+=ce.css(e,"padding"+Q[a],!0,i),"padding"!==n?u+=ce.css(e,"border"+Q[a]+"Width",!0,i):s+=ce.css(e,"border"+Q[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u+l}function ot(e,t,n){var r=Xe(e),i=(!le.boxSizingReliable()||n)&&"border-box"===ce.css(e,"boxSizing",!1,r),o=i,a=Ge(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if(_e.test(a)){if(!n)return a;a="auto"}return(!le.boxSizingReliable()&&i||!le.reliableTrDimensions()&&fe(e,"tr")||"auto"===a||!parseFloat(a)&&"inline"===ce.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===ce.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+it(e,t,n||(i?"border":"content"),o,r,a)+"px"}function at(e,t,n,r,i){return new at.prototype.init(e,t,n,r,i)}ce.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Ge(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,aspectRatio:!0,borderImageSlice:!0,columnCount:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,scale:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeMiterlimit:!0,strokeOpacity:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=F(t),u=ze.test(t),l=e.style;if(u||(t=Ze(s)),a=ce.cssHooks[t]||ce.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=Y.exec(n))&&i[1]&&(n=te(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(ce.cssNumber[s]?"":"px")),le.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=F(t);return ze.test(t)||(t=Ze(s)),(a=ce.cssHooks[t]||ce.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Ge(e,t,r)),"normal"===i&&t in nt&&(i=nt[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),ce.each(["height","width"],function(e,u){ce.cssHooks[u]={get:function(e,t,n){if(t)return!et.test(ce.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?ot(e,u,n):Ue(e,tt,function(){return ot(e,u,n)})},set:function(e,t,n){var r,i=Xe(e),o=!le.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===ce.css(e,"boxSizing",!1,i),s=n?it(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-it(e,u,"border",!1,i)-.5)),s&&(r=Y.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=ce.css(e,u)),rt(0,t,s)}}}),ce.cssHooks.marginLeft=Ye(le.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Ge(e,"marginLeft"))||e.getBoundingClientRect().left-Ue(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),ce.each({margin:"",padding:"",border:"Width"},function(i,o){ce.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+Q[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(ce.cssHooks[i+o].set=rt)}),ce.fn.extend({css:function(e,t){return M(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Xe(e),i=t.length;a<i;a++)o[t[a]]=ce.css(e,t[a],!1,r);return o}return void 0!==n?ce.style(e,t,n):ce.css(e,t)},e,t,1<arguments.length)}}),((ce.Tween=at).prototype={constructor:at,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||ce.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(ce.cssNumber[n]?"":"px")},cur:function(){var e=at.propHooks[this.prop];return e&&e.get?e.get(this):at.propHooks._default.get(this)},run:function(e){var t,n=at.propHooks[this.prop];return this.options.duration?this.pos=t=ce.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):at.propHooks._default.set(this),this}}).init.prototype=at.prototype,(at.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=ce.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){ce.fx.step[e.prop]?ce.fx.step[e.prop](e):1!==e.elem.nodeType||!ce.cssHooks[e.prop]&&null==e.elem.style[Ze(e.prop)]?e.elem[e.prop]=e.now:ce.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=at.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},ce.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},ce.fx=at.prototype.init,ce.fx.step={};var st,ut,lt,ct,ft=/^(?:toggle|show|hide)$/,pt=/queueHooks$/;function dt(){ut&&(!1===C.hidden&&ie.requestAnimationFrame?ie.requestAnimationFrame(dt):ie.setTimeout(dt,ce.fx.interval),ce.fx.tick())}function ht(){return ie.setTimeout(function(){st=void 0}),st=Date.now()}function gt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=Q[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function vt(e,t,n){for(var r,i=(yt.tweeners[t]||[]).concat(yt.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function yt(o,e,t){var n,a,r=0,i=yt.prefilters.length,s=ce.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=st||ht(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:ce.extend({},e),opts:ce.extend(!0,{specialEasing:{},easing:ce.easing._default},t),originalProperties:e,originalOptions:t,startTime:st||ht(),duration:t.duration,tweens:[],createTween:function(e,t){var n=ce.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=F(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=ce.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=yt.prefilters[r].call(l,o,c,l.opts))return v(n.stop)&&(ce._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return ce.map(c,vt,l),v(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),ce.fx.timer(ce.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}ce.Animation=ce.extend(yt,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return te(n.elem,e,Y.exec(t),n),n}]},tweener:function(e,t){v(e)?(t=e,e=["*"]):e=e.match(D);for(var n,r=0,i=e.length;r<i;r++)n=e[r],yt.tweeners[n]=yt.tweeners[n]||[],yt.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ee(e),v=_.get(e,"fxshow");for(r in n.queue||(null==(a=ce._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,ce.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],ft.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||ce.style(e,r)}if((u=!ce.isEmptyObject(t))||!ce.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=_.get(e,"display")),"none"===(c=ce.css(e,"display"))&&(l?c=l:(re([e],!0),l=e.style.display||l,c=ce.css(e,"display"),re([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===ce.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=_.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&re([e],!0),p.done(function(){for(r in g||re([e]),_.remove(e,"fxshow"),d)ce.style(e,r,d[r])})),u=vt(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?yt.prefilters.unshift(e):yt.prefilters.push(e)}}),ce.speed=function(e,t,n){var r=e&&"object"==typeof e?ce.extend({},e):{complete:n||!n&&t||v(e)&&e,duration:e,easing:n&&t||t&&!v(t)&&t};return ce.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in ce.fx.speeds?r.duration=ce.fx.speeds[r.duration]:r.duration=ce.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){v(r.old)&&r.old.call(this),r.queue&&ce.dequeue(this,r.queue)},r},ce.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ee).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=ce.isEmptyObject(t),o=ce.speed(e,n,r),a=function(){var e=yt(this,ce.extend({},t),o);(i||_.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=ce.timers,r=_.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&pt.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||ce.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=_.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=ce.timers,o=n?n.length:0;for(t.finish=!0,ce.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),ce.each(["toggle","show","hide"],function(e,r){var i=ce.fn[r];ce.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(gt(r,!0),e,t,n)}}),ce.each({slideDown:gt("show"),slideUp:gt("hide"),slideToggle:gt("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){ce.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),ce.timers=[],ce.fx.tick=function(){var e,t=0,n=ce.timers;for(st=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||ce.fx.stop(),st=void 0},ce.fx.timer=function(e){ce.timers.push(e),ce.fx.start()},ce.fx.interval=13,ce.fx.start=function(){ut||(ut=!0,dt())},ce.fx.stop=function(){ut=null},ce.fx.speeds={slow:600,fast:200,_default:400},ce.fn.delay=function(r,e){return r=ce.fx&&ce.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=ie.setTimeout(e,r);t.stop=function(){ie.clearTimeout(n)}})},lt=C.createElement("input"),ct=C.createElement("select").appendChild(C.createElement("option")),lt.type="checkbox",le.checkOn=""!==lt.value,le.optSelected=ct.selected,(lt=C.createElement("input")).value="t",lt.type="radio",le.radioValue="t"===lt.value;var mt,xt=ce.expr.attrHandle;ce.fn.extend({attr:function(e,t){return M(this,ce.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){ce.removeAttr(this,e)})}}),ce.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?ce.prop(e,t,n):(1===o&&ce.isXMLDoc(e)||(i=ce.attrHooks[t.toLowerCase()]||(ce.expr.match.bool.test(t)?mt:void 0)),void 0!==n?null===n?void ce.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=ce.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!le.radioValue&&"radio"===t&&fe(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(D);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),mt={set:function(e,t,n){return!1===t?ce.removeAttr(e,n):e.setAttribute(n,n),n}},ce.each(ce.expr.match.bool.source.match(/\w+/g),function(e,t){var a=xt[t]||ce.find.attr;xt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=xt[o],xt[o]=r,r=null!=a(e,t,n)?o:null,xt[o]=i),r}});var bt=/^(?:input|select|textarea|button)$/i,wt=/^(?:a|area)$/i;function Tt(e){return(e.match(D)||[]).join(" ")}function Ct(e){return e.getAttribute&&e.getAttribute("class")||""}function kt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(D)||[]}ce.fn.extend({prop:function(e,t){return M(this,ce.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[ce.propFix[e]||e]})}}),ce.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&ce.isXMLDoc(e)||(t=ce.propFix[t]||t,i=ce.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=ce.find.attr(e,"tabindex");return t?parseInt(t,10):bt.test(e.nodeName)||wt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),le.optSelected||(ce.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),ce.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){ce.propFix[this.toLowerCase()]=this}),ce.fn.extend({addClass:function(t){var e,n,r,i,o,a;return v(t)?this.each(function(e){ce(this).addClass(t.call(this,e,Ct(this)))}):(e=kt(t)).length?this.each(function(){if(r=Ct(this),n=1===this.nodeType&&" "+Tt(r)+" "){for(o=0;o<e.length;o++)i=e[o],n.indexOf(" "+i+" ")<0&&(n+=i+" ");a=Tt(n),r!==a&&this.setAttribute("class",a)}}):this},removeClass:function(t){var e,n,r,i,o,a;return v(t)?this.each(function(e){ce(this).removeClass(t.call(this,e,Ct(this)))}):arguments.length?(e=kt(t)).length?this.each(function(){if(r=Ct(this),n=1===this.nodeType&&" "+Tt(r)+" "){for(o=0;o<e.length;o++){i=e[o];while(-1<n.indexOf(" "+i+" "))n=n.replace(" "+i+" "," ")}a=Tt(n),r!==a&&this.setAttribute("class",a)}}):this:this.attr("class","")},toggleClass:function(t,n){var e,r,i,o,a=typeof t,s="string"===a||Array.isArray(t);return v(t)?this.each(function(e){ce(this).toggleClass(t.call(this,e,Ct(this),n),n)}):"boolean"==typeof n&&s?n?this.addClass(t):this.removeClass(t):(e=kt(t),this.each(function(){if(s)for(o=ce(this),i=0;i<e.length;i++)r=e[i],o.hasClass(r)?o.removeClass(r):o.addClass(r);else void 0!==t&&"boolean"!==a||((r=Ct(this))&&_.set(this,"__className__",r),this.setAttribute&&this.setAttribute("class",r||!1===t?"":_.get(this,"__className__")||""))}))},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+Tt(Ct(n))+" ").indexOf(t))return!0;return!1}});var St=/\r/g;ce.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=v(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,ce(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=ce.map(t,function(e){return null==e?"":e+""})),(r=ce.valHooks[this.type]||ce.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=ce.valHooks[t.type]||ce.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(St,""):null==e?"":e:void 0}}),ce.extend({valHooks:{option:{get:function(e){var t=ce.find.attr(e,"value");return null!=t?t:Tt(ce.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!fe(n.parentNode,"optgroup"))){if(t=ce(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=ce.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<ce.inArray(ce.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),ce.each(["radio","checkbox"],function(){ce.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<ce.inArray(ce(e).val(),t)}},le.checkOn||(ce.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Et=ie.location,jt={guid:Date.now()},At=/\?/;ce.parseXML=function(e){var t,n;if(!e||"string"!=typeof e)return null;try{t=(new ie.DOMParser).parseFromString(e,"text/xml")}catch(e){}return n=t&&t.getElementsByTagName("parsererror")[0],t&&!n||ce.error("Invalid XML: "+(n?ce.map(n.childNodes,function(e){return e.textContent}).join("\n"):e)),t};var Dt=/^(?:focusinfocus|focusoutblur)$/,Nt=function(e){e.stopPropagation()};ce.extend(ce.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||C],d=ue.call(e,"type")?e.type:e,h=ue.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||C,3!==n.nodeType&&8!==n.nodeType&&!Dt.test(d+ce.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[ce.expando]?e:new ce.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:ce.makeArray(t,[e]),c=ce.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!y(n)){for(s=c.delegateType||d,Dt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||C)&&p.push(a.defaultView||a.parentWindow||ie)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(_.get(o,"events")||Object.create(null))[e.type]&&_.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&$(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!$(n)||u&&v(n[d])&&!y(n)&&((a=n[u])&&(n[u]=null),ce.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,Nt),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,Nt),ce.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=ce.extend(new ce.Event,n,{type:e,isSimulated:!0});ce.event.trigger(r,null,t)}}),ce.fn.extend({trigger:function(e,t){return this.each(function(){ce.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return ce.event.trigger(e,t,n,!0)}});var qt=/\[\]$/,Lt=/\r?\n/g,Ht=/^(?:submit|button|image|reset|file)$/i,Ot=/^(?:input|select|textarea|keygen)/i;function Pt(n,e,r,i){var t;if(Array.isArray(e))ce.each(e,function(e,t){r||qt.test(n)?i(n,t):Pt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==x(e))i(n,e);else for(t in e)Pt(n+"["+t+"]",e[t],r,i)}ce.param=function(e,t){var n,r=[],i=function(e,t){var n=v(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!ce.isPlainObject(e))ce.each(e,function(){i(this.name,this.value)});else for(n in e)Pt(n,e[n],t,i);return r.join("&")},ce.fn.extend({serialize:function(){return ce.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=ce.prop(this,"elements");return e?ce.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!ce(this).is(":disabled")&&Ot.test(this.nodeName)&&!Ht.test(e)&&(this.checked||!we.test(e))}).map(function(e,t){var n=ce(this).val();return null==n?null:Array.isArray(n)?ce.map(n,function(e){return{name:t.name,value:e.replace(Lt,"\r\n")}}):{name:t.name,value:n.replace(Lt,"\r\n")}}).get()}});var Mt=/%20/g,Rt=/#.*$/,It=/([?&])_=[^&]*/,Wt=/^(.*?):[ \t]*([^\r\n]*)$/gm,Ft=/^(?:GET|HEAD)$/,$t=/^\/\//,Bt={},_t={},zt="*/".concat("*"),Xt=C.createElement("a");function Ut(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(D)||[];if(v(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function Vt(t,i,o,a){var s={},u=t===_t;function l(e){var r;return s[e]=!0,ce.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function Gt(e,t){var n,r,i=ce.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&ce.extend(!0,e,r),e}Xt.href=Et.href,ce.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Et.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Et.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":zt,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":ce.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?Gt(Gt(e,ce.ajaxSettings),t):Gt(ce.ajaxSettings,e)},ajaxPrefilter:Ut(Bt),ajaxTransport:Ut(_t),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=ce.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?ce(y):ce.event,x=ce.Deferred(),b=ce.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Wt.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Et.href)+"").replace($t,Et.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(D)||[""],null==v.crossDomain){r=C.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Xt.protocol+"//"+Xt.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=ce.param(v.data,v.traditional)),Vt(Bt,v,t,T),h)return T;for(i in(g=ce.event&&v.global)&&0==ce.active++&&ce.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Ft.test(v.type),f=v.url.replace(Rt,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(Mt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(At.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(It,"$1"),o=(At.test(f)?"&":"?")+"_="+jt.guid+++o),v.url=f+o),v.ifModified&&(ce.lastModified[f]&&T.setRequestHeader("If-Modified-Since",ce.lastModified[f]),ce.etag[f]&&T.setRequestHeader("If-None-Match",ce.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+zt+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=Vt(_t,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=ie.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&ie.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),!i&&-1<ce.inArray("script",v.dataTypes)&&ce.inArray("json",v.dataTypes)<0&&(v.converters["text script"]=function(){}),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(ce.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(ce.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--ce.active||ce.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return ce.get(e,t,n,"json")},getScript:function(e,t){return ce.get(e,void 0,t,"script")}}),ce.each(["get","post"],function(e,i){ce[i]=function(e,t,n,r){return v(t)&&(r=r||n,n=t,t=void 0),ce.ajax(ce.extend({url:e,type:i,dataType:r,data:t,success:n},ce.isPlainObject(e)&&e))}}),ce.ajaxPrefilter(function(e){var t;for(t in e.headers)"content-type"===t.toLowerCase()&&(e.contentType=e.headers[t]||"")}),ce._evalUrl=function(e,t,n){return ce.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){ce.globalEval(e,t,n)}})},ce.fn.extend({wrapAll:function(e){var t;return this[0]&&(v(e)&&(e=e.call(this[0])),t=ce(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return v(n)?this.each(function(e){ce(this).wrapInner(n.call(this,e))}):this.each(function(){var e=ce(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=v(t);return this.each(function(e){ce(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){ce(this).replaceWith(this.childNodes)}),this}}),ce.expr.pseudos.hidden=function(e){return!ce.expr.pseudos.visible(e)},ce.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},ce.ajaxSettings.xhr=function(){try{return new ie.XMLHttpRequest}catch(e){}};var Yt={0:200,1223:204},Qt=ce.ajaxSettings.xhr();le.cors=!!Qt&&"withCredentials"in Qt,le.ajax=Qt=!!Qt,ce.ajaxTransport(function(i){var o,a;if(le.cors||Qt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(Yt[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&ie.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),ce.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),ce.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return ce.globalEval(e),e}}}),ce.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),ce.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=ce("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=Tt(e.slice(s)),e=e.slice(0,s)),v(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&ce.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?ce("<div>").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}});var en=/^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g;ce.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),v(e))return r=ae.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(ae.call(arguments)))}).guid=e.guid=e.guid||ce.guid++,i},ce.holdReady=function(e){e?ce.readyWait++:ce.ready(!0)},ce.isArray=Array.isArray,ce.parseJSON=JSON.parse,ce.nodeName=fe,ce.isFunction=v,ce.isWindow=y,ce.camelCase=F,ce.type=x,ce.now=Date.now,ce.isNumeric=function(e){var t=ce.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},ce.trim=function(e){return null==e?"":(e+"").replace(en,"$1")},"function"==typeof define&&define.amd&&define("jquery",[],function(){return ce});var tn=ie.jQuery,nn=ie.$;return ce.noConflict=function(e){return ie.$===ce&&(ie.$=nn),e&&ie.jQuery===ce&&(ie.jQuery=tn),ce},"undefined"==typeof e&&(ie.jQuery=ie.$=ce),ce});
diff --git a/vendor/mikespub/php-epub-meta/assets/js/jquery-ui-1.13.2.custom.min.js b/vendor/mikespub/php-epub-meta/assets/js/jquery-ui-1.13.2.custom.min.js
new file mode 100644
index 000000000..79273ab47
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/js/jquery-ui-1.13.2.custom.min.js
@@ -0,0 +1,6 @@
+/*! jQuery UI - v1.13.2 - 2023-09-10
+* http://jqueryui.com
+* Includes: widget.js, position.js, data.js, disable-selection.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/draggable.js, widgets/droppable.js, widgets/resizable.js, widgets/selectable.js, widgets/sortable.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/selectmenu.js, widgets/slider.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)}(function(V){"use strict";V.ui=V.ui||{};V.ui.version="1.13.2";var n,i=0,a=Array.prototype.hasOwnProperty,r=Array.prototype.slice;V.cleanData=(n=V.cleanData,function(t){for(var e,i,s=0;null!=(i=t[s]);s++)(e=V._data(i,"events"))&&e.remove&&V(i).triggerHandler("remove");n(t)}),V.widget=function(t,i,e){var s,n,o,a={},r=t.split(".")[0],l=r+"-"+(t=t.split(".")[1]);return e||(e=i,i=V.Widget),Array.isArray(e)&&(e=V.extend.apply(null,[{}].concat(e))),V.expr.pseudos[l.toLowerCase()]=function(t){return!!V.data(t,l)},V[r]=V[r]||{},s=V[r][t],n=V[r][t]=function(t,e){if(!this||!this._createWidget)return new n(t,e);arguments.length&&this._createWidget(t,e)},V.extend(n,s,{version:e.version,_proto:V.extend({},e),_childConstructors:[]}),(o=new i).options=V.widget.extend({},o.options),V.each(e,function(e,s){function n(){return i.prototype[e].apply(this,arguments)}function o(t){return i.prototype[e].apply(this,t)}a[e]="function"==typeof s?function(){var t,e=this._super,i=this._superApply;return this._super=n,this._superApply=o,t=s.apply(this,arguments),this._super=e,this._superApply=i,t}:s}),n.prototype=V.widget.extend(o,{widgetEventPrefix:s&&o.widgetEventPrefix||t},a,{constructor:n,namespace:r,widgetName:t,widgetFullName:l}),s?(V.each(s._childConstructors,function(t,e){var i=e.prototype;V.widget(i.namespace+"."+i.widgetName,n,e._proto)}),delete s._childConstructors):i._childConstructors.push(n),V.widget.bridge(t,n),n},V.widget.extend=function(t){for(var e,i,s=r.call(arguments,1),n=0,o=s.length;n<o;n++)for(e in s[n])i=s[n][e],a.call(s[n],e)&&void 0!==i&&(V.isPlainObject(i)?t[e]=V.isPlainObject(t[e])?V.widget.extend({},t[e],i):V.widget.extend({},i):t[e]=i);return t},V.widget.bridge=function(o,e){var a=e.prototype.widgetFullName||o;V.fn[o]=function(i){var t="string"==typeof i,s=r.call(arguments,1),n=this;return t?this.length||"instance"!==i?this.each(function(){var t,e=V.data(this,a);return"instance"===i?(n=e,!1):e?"function"!=typeof e[i]||"_"===i.charAt(0)?V.error("no such method '"+i+"' for "+o+" widget instance"):(t=e[i].apply(e,s))!==e&&void 0!==t?(n=t&&t.jquery?n.pushStack(t.get()):t,!1):void 0:V.error("cannot call methods on "+o+" prior to initialization; attempted to call method '"+i+"'")}):n=void 0:(s.length&&(i=V.widget.extend.apply(null,[i].concat(s))),this.each(function(){var t=V.data(this,a);t?(t.option(i||{}),t._init&&t._init()):V.data(this,a,new e(i,this))})),n}},V.Widget=function(){},V.Widget._childConstructors=[],V.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{classes:{},disabled:!1,create:null},_createWidget:function(t,e){e=V(e||this.defaultElement||this)[0],this.element=V(e),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.bindings=V(),this.hoverable=V(),this.focusable=V(),this.classesElementLookup={},e!==this&&(V.data(e,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===e&&this.destroy()}}),this.document=V(e.style?e.ownerDocument:e.document||e),this.window=V(this.document[0].defaultView||this.document[0].parentWindow)),this.options=V.widget.extend({},this.options,this._getCreateOptions(),t),this._create(),this.options.disabled&&this._setOptionDisabled(this.options.disabled),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:function(){return{}},_getCreateEventData:V.noop,_create:V.noop,_init:V.noop,destroy:function(){var i=this;this._destroy(),V.each(this.classesElementLookup,function(t,e){i._removeClass(e,t)}),this.element.off(this.eventNamespace).removeData(this.widgetFullName),this.widget().off(this.eventNamespace).removeAttr("aria-disabled"),this.bindings.off(this.eventNamespace)},_destroy:V.noop,widget:function(){return this.element},option:function(t,e){var i,s,n,o=t;if(0===arguments.length)return V.widget.extend({},this.options);if("string"==typeof t)if(o={},t=(i=t.split(".")).shift(),i.length){for(s=o[t]=V.widget.extend({},this.options[t]),n=0;n<i.length-1;n++)s[i[n]]=s[i[n]]||{},s=s[i[n]];if(t=i.pop(),1===arguments.length)return void 0===s[t]?null:s[t];s[t]=e}else{if(1===arguments.length)return void 0===this.options[t]?null:this.options[t];o[t]=e}return this._setOptions(o),this},_setOptions:function(t){for(var e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return"classes"===t&&this._setOptionClasses(e),this.options[t]=e,"disabled"===t&&this._setOptionDisabled(e),this},_setOptionClasses:function(t){var e,i,s;for(e in t)s=this.classesElementLookup[e],t[e]!==this.options.classes[e]&&s&&s.length&&(i=V(s.get()),this._removeClass(s,e),i.addClass(this._classes({element:i,keys:e,classes:t,add:!0})))},_setOptionDisabled:function(t){this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!!t),t&&(this._removeClass(this.hoverable,null,"ui-state-hover"),this._removeClass(this.focusable,null,"ui-state-focus"))},enable:function(){return this._setOptions({disabled:!1})},disable:function(){return this._setOptions({disabled:!0})},_classes:function(n){var o=[],a=this;function t(t,e){for(var i,s=0;s<t.length;s++)i=a.classesElementLookup[t[s]]||V(),i=n.add?(function(){var i=[];n.element.each(function(t,e){V.map(a.classesElementLookup,function(t){return t}).some(function(t){return t.is(e)})||i.push(e)}),a._on(V(i),{remove:"_untrackClassesElement"})}(),V(V.uniqueSort(i.get().concat(n.element.get())))):V(i.not(n.element).get()),a.classesElementLookup[t[s]]=i,o.push(t[s]),e&&n.classes[t[s]]&&o.push(n.classes[t[s]])}return(n=V.extend({element:this.element,classes:this.options.classes||{}},n)).keys&&t(n.keys.match(/\S+/g)||[],!0),n.extra&&t(n.extra.match(/\S+/g)||[]),o.join(" ")},_untrackClassesElement:function(i){var s=this;V.each(s.classesElementLookup,function(t,e){-1!==V.inArray(i.target,e)&&(s.classesElementLookup[t]=V(e.not(i.target).get()))}),this._off(V(i.target))},_removeClass:function(t,e,i){return this._toggleClass(t,e,i,!1)},_addClass:function(t,e,i){return this._toggleClass(t,e,i,!0)},_toggleClass:function(t,e,i,s){var n="string"==typeof t||null===t,i={extra:n?e:i,keys:n?t:e,element:n?this.element:t,add:s="boolean"==typeof s?s:i};return i.element.toggleClass(this._classes(i),s),this},_on:function(n,o,t){var a,r=this;"boolean"!=typeof n&&(t=o,o=n,n=!1),t?(o=a=V(o),this.bindings=this.bindings.add(o)):(t=o,o=this.element,a=this.widget()),V.each(t,function(t,e){function i(){if(n||!0!==r.options.disabled&&!V(this).hasClass("ui-state-disabled"))return("string"==typeof e?r[e]:e).apply(r,arguments)}"string"!=typeof e&&(i.guid=e.guid=e.guid||i.guid||V.guid++);var s=t.match(/^([\w:-]*)\s*(.*)$/),t=s[1]+r.eventNamespace,s=s[2];s?a.on(t,s,i):o.on(t,i)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.off(e),this.bindings=V(this.bindings.not(t).get()),this.focusable=V(this.focusable.not(t).get()),this.hoverable=V(this.hoverable.not(t).get())},_delay:function(t,e){var i=this;return setTimeout(function(){return("string"==typeof t?i[t]:t).apply(i,arguments)},e||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){this._addClass(V(t.currentTarget),null,"ui-state-hover")},mouseleave:function(t){this._removeClass(V(t.currentTarget),null,"ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){this._addClass(V(t.currentTarget),null,"ui-state-focus")},focusout:function(t){this._removeClass(V(t.currentTarget),null,"ui-state-focus")}})},_trigger:function(t,e,i){var s,n,o=this.options[t];if(i=i||{},(e=V.Event(e)).type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),e.target=this.element[0],n=e.originalEvent)for(s in n)s in e||(e[s]=n[s]);return this.element.trigger(e,i),!("function"==typeof o&&!1===o.apply(this.element[0],[e].concat(i))||e.isDefaultPrevented())}},V.each({show:"fadeIn",hide:"fadeOut"},function(o,a){V.Widget.prototype["_"+o]=function(e,t,i){var s,n=(t="string"==typeof t?{effect:t}:t)?!0!==t&&"number"!=typeof t&&t.effect||a:o;"number"==typeof(t=t||{})?t={duration:t}:!0===t&&(t={}),s=!V.isEmptyObject(t),t.complete=i,t.delay&&e.delay(t.delay),s&&V.effects&&V.effects.effect[n]?e[o](t):n!==o&&e[n]?e[n](t.duration,t.easing,i):e.queue(function(t){V(this)[o](),i&&i.call(e[0]),t()})}});var s,x,k,o,l,h,c,u,C;V.widget;function D(t,e,i){return[parseFloat(t[0])*(u.test(t[0])?e/100:1),parseFloat(t[1])*(u.test(t[1])?i/100:1)]}function I(t,e){return parseInt(V.css(t,e),10)||0}function T(t){return null!=t&&t===t.window}x=Math.max,k=Math.abs,o=/left|center|right/,l=/top|center|bottom/,h=/[\+\-]\d+(\.[\d]+)?%?/,c=/^\w+/,u=/%$/,C=V.fn.position,V.position={scrollbarWidth:function(){if(void 0!==s)return s;var t,e=V("<div style='display:block;position:absolute;width:200px;height:200px;overflow:hidden;'><div style='height:300px;width:auto;'></div></div>"),i=e.children()[0];return V("body").append(e),t=i.offsetWidth,e.css("overflow","scroll"),t===(i=i.offsetWidth)&&(i=e[0].clientWidth),e.remove(),s=t-i},getScrollInfo:function(t){var e=t.isWindow||t.isDocument?"":t.element.css("overflow-x"),i=t.isWindow||t.isDocument?"":t.element.css("overflow-y"),e="scroll"===e||"auto"===e&&t.width<t.element[0].scrollWidth;return{width:"scroll"===i||"auto"===i&&t.height<t.element[0].scrollHeight?V.position.scrollbarWidth():0,height:e?V.position.scrollbarWidth():0}},getWithinInfo:function(t){var e=V(t||window),i=T(e[0]),s=!!e[0]&&9===e[0].nodeType;return{element:e,isWindow:i,isDocument:s,offset:!i&&!s?V(t).offset():{left:0,top:0},scrollLeft:e.scrollLeft(),scrollTop:e.scrollTop(),width:e.outerWidth(),height:e.outerHeight()}}},V.fn.position=function(u){if(!u||!u.of)return C.apply(this,arguments);var d,p,f,g,m,t,_="string"==typeof(u=V.extend({},u)).of?V(document).find(u.of):V(u.of),v=V.position.getWithinInfo(u.within),b=V.position.getScrollInfo(v),y=(u.collision||"flip").split(" "),w={},e=9===(t=(e=_)[0]).nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:T(t)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:t.preventDefault?{width:0,height:0,offset:{top:t.pageY,left:t.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()};return _[0].preventDefault&&(u.at="left top"),p=e.width,f=e.height,m=V.extend({},g=e.offset),V.each(["my","at"],function(){var t,e,i=(u[this]||"").split(" ");(i=1===i.length?o.test(i[0])?i.concat(["center"]):l.test(i[0])?["center"].concat(i):["center","center"]:i)[0]=o.test(i[0])?i[0]:"center",i[1]=l.test(i[1])?i[1]:"center",t=h.exec(i[0]),e=h.exec(i[1]),w[this]=[t?t[0]:0,e?e[0]:0],u[this]=[c.exec(i[0])[0],c.exec(i[1])[0]]}),1===y.length&&(y[1]=y[0]),"right"===u.at[0]?m.left+=p:"center"===u.at[0]&&(m.left+=p/2),"bottom"===u.at[1]?m.top+=f:"center"===u.at[1]&&(m.top+=f/2),d=D(w.at,p,f),m.left+=d[0],m.top+=d[1],this.each(function(){var i,t,a=V(this),r=a.outerWidth(),l=a.outerHeight(),e=I(this,"marginLeft"),s=I(this,"marginTop"),n=r+e+I(this,"marginRight")+b.width,o=l+s+I(this,"marginBottom")+b.height,h=V.extend({},m),c=D(w.my,a.outerWidth(),a.outerHeight());"right"===u.my[0]?h.left-=r:"center"===u.my[0]&&(h.left-=r/2),"bottom"===u.my[1]?h.top-=l:"center"===u.my[1]&&(h.top-=l/2),h.left+=c[0],h.top+=c[1],i={marginLeft:e,marginTop:s},V.each(["left","top"],function(t,e){V.ui.position[y[t]]&&V.ui.position[y[t]][e](h,{targetWidth:p,targetHeight:f,elemWidth:r,elemHeight:l,collisionPosition:i,collisionWidth:n,collisionHeight:o,offset:[d[0]+c[0],d[1]+c[1]],my:u.my,at:u.at,within:v,elem:a})}),u.using&&(t=function(t){var e=g.left-h.left,i=e+p-r,s=g.top-h.top,n=s+f-l,o={target:{element:_,left:g.left,top:g.top,width:p,height:f},element:{element:a,left:h.left,top:h.top,width:r,height:l},horizontal:i<0?"left":0<e?"right":"center",vertical:n<0?"top":0<s?"bottom":"middle"};p<r&&k(e+i)<p&&(o.horizontal="center"),f<l&&k(s+n)<f&&(o.vertical="middle"),x(k(e),k(i))>x(k(s),k(n))?o.important="horizontal":o.important="vertical",u.using.call(this,t,o)}),a.offset(V.extend(h,{using:t}))})},V.ui.position={fit:{left:function(t,e){var i=e.within,s=i.isWindow?i.scrollLeft:i.offset.left,n=i.width,o=t.left-e.collisionPosition.marginLeft,a=s-o,r=o+e.collisionWidth-n-s;e.collisionWidth>n?0<a&&r<=0?(i=t.left+a+e.collisionWidth-n-s,t.left+=a-i):t.left=!(0<r&&a<=0)&&r<a?s+n-e.collisionWidth:s:0<a?t.left+=a:0<r?t.left-=r:t.left=x(t.left-o,t.left)},top:function(t,e){var i=e.within,s=i.isWindow?i.scrollTop:i.offset.top,n=e.within.height,o=t.top-e.collisionPosition.marginTop,a=s-o,r=o+e.collisionHeight-n-s;e.collisionHeight>n?0<a&&r<=0?(i=t.top+a+e.collisionHeight-n-s,t.top+=a-i):t.top=!(0<r&&a<=0)&&r<a?s+n-e.collisionHeight:s:0<a?t.top+=a:0<r?t.top-=r:t.top=x(t.top-o,t.top)}},flip:{left:function(t,e){var i=e.within,s=i.offset.left+i.scrollLeft,n=i.width,o=i.isWindow?i.scrollLeft:i.offset.left,a=t.left-e.collisionPosition.marginLeft,r=a-o,l=a+e.collisionWidth-n-o,h="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,i="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,a=-2*e.offset[0];r<0?((s=t.left+h+i+a+e.collisionWidth-n-s)<0||s<k(r))&&(t.left+=h+i+a):0<l&&(0<(o=t.left-e.collisionPosition.marginLeft+h+i+a-o)||k(o)<l)&&(t.left+=h+i+a)},top:function(t,e){var i=e.within,s=i.offset.top+i.scrollTop,n=i.height,o=i.isWindow?i.scrollTop:i.offset.top,a=t.top-e.collisionPosition.marginTop,r=a-o,l=a+e.collisionHeight-n-o,h="top"===e.my[1]?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,i="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,a=-2*e.offset[1];r<0?((s=t.top+h+i+a+e.collisionHeight-n-s)<0||s<k(r))&&(t.top+=h+i+a):0<l&&(0<(o=t.top-e.collisionPosition.marginTop+h+i+a-o)||k(o)<l)&&(t.top+=h+i+a)}},flipfit:{left:function(){V.ui.position.flip.left.apply(this,arguments),V.ui.position.fit.left.apply(this,arguments)},top:function(){V.ui.position.flip.top.apply(this,arguments),V.ui.position.fit.top.apply(this,arguments)}}};var t;V.ui.position,V.extend(V.expr.pseudos,{data:V.expr.createPseudo?V.expr.createPseudo(function(e){return function(t){return!!V.data(t,e)}}):function(t,e,i){return!!V.data(t,i[3])}}),V.fn.extend({disableSelection:(t="onselectstart"in document.createElement("div")?"selectstart":"mousedown",function(){return this.on(t+".ui-disableSelection",function(t){t.preventDefault()})}),enableSelection:function(){return this.off(".ui-disableSelection")}});V.ui.focusable=function(t,e){var i,s,n,o,a=t.nodeName.toLowerCase();return"area"===a?(s=(i=t.parentNode).name,!(!t.href||!s||"map"!==i.nodeName.toLowerCase())&&(0<(s=V("img[usemap='#"+s+"']")).length&&s.is(":visible"))):(/^(input|select|textarea|button|object)$/.test(a)?(n=!t.disabled)&&(o=V(t).closest("fieldset")[0])&&(n=!o.disabled):n="a"===a&&t.href||e,n&&V(t).is(":visible")&&function(t){var e=t.css("visibility");for(;"inherit"===e;)t=t.parent(),e=t.css("visibility");return"visible"===e}(V(t)))},V.extend(V.expr.pseudos,{focusable:function(t){return V.ui.focusable(t,null!=V.attr(t,"tabindex"))}});var e,d;V.ui.focusable,V.fn._form=function(){return"string"==typeof this[0].form?this.closest("form"):V(this[0].form)},V.ui.formResetMixin={_formResetHandler:function(){var e=V(this);setTimeout(function(){var t=e.data("ui-form-reset-instances");V.each(t,function(){this.refresh()})})},_bindFormResetHandler:function(){var t;this.form=this.element._form(),this.form.length&&((t=this.form.data("ui-form-reset-instances")||[]).length||this.form.on("reset.ui-form-reset",this._formResetHandler),t.push(this),this.form.data("ui-form-reset-instances",t))},_unbindFormResetHandler:function(){var t;this.form.length&&((t=this.form.data("ui-form-reset-instances")).splice(V.inArray(this,t),1),t.length?this.form.data("ui-form-reset-instances",t):this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset"))}};V.expr.pseudos||(V.expr.pseudos=V.expr[":"]),V.uniqueSort||(V.uniqueSort=V.unique),V.escapeSelector||(e=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g,d=function(t,e){return e?"\0"===t?"�":t.slice(0,-1)+"\\"+t.charCodeAt(t.length-1).toString(16)+" ":"\\"+t},V.escapeSelector=function(t){return(t+"").replace(e,d)}),V.fn.even&&V.fn.odd||V.fn.extend({even:function(){return this.filter(function(t){return t%2==0})},odd:function(){return this.filter(function(t){return t%2==1})}});V.ui.keyCode={BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38},V.fn.labels=function(){var t,e,i;return this.length?this[0].labels&&this[0].labels.length?this.pushStack(this[0].labels):(e=this.eq(0).parents("label"),(t=this.attr("id"))&&(i=(i=this.eq(0).parents().last()).add((i.length?i:this).siblings()),t="label[for='"+V.escapeSelector(t)+"']",e=e.add(i.find(t).addBack(t))),this.pushStack(e)):this.pushStack([])},V.fn.scrollParent=function(t){var e=this.css("position"),i="absolute"===e,s=t?/(auto|scroll|hidden)/:/(auto|scroll)/,t=this.parents().filter(function(){var t=V(this);return(!i||"static"!==t.css("position"))&&s.test(t.css("overflow")+t.css("overflow-y")+t.css("overflow-x"))}).eq(0);return"fixed"!==e&&t.length?t:V(this[0].ownerDocument||document)},V.extend(V.expr.pseudos,{tabbable:function(t){var e=V.attr(t,"tabindex"),i=null!=e;return(!i||0<=e)&&V.ui.focusable(t,i)}}),V.fn.extend({uniqueId:(p=0,function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++p)})}),removeUniqueId:function(){return this.each(function(){/^ui-id-\d+$/.test(this.id)&&V(this).removeAttr("id")})}}),V.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());var p,f=!1;V(document).on("mouseup",function(){f=!1});V.widget("ui.mouse",{version:"1.13.2",options:{cancel:"input, textarea, button, select, option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.on("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).on("click."+this.widgetName,function(t){if(!0===V.data(t.target,e.widgetName+".preventClickEvent"))return V.removeData(t.target,e.widgetName+".preventClickEvent"),t.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.off("."+this.widgetName),this._mouseMoveDelegate&&this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(!f){this._mouseMoved=!1,this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var e=this,i=1===t.which,s=!("string"!=typeof this.options.cancel||!t.target.nodeName)&&V(t.target).closest(this.options.cancel).length;return i&&!s&&this._mouseCapture(t)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){e.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=!1!==this._mouseStart(t),!this._mouseStarted)?(t.preventDefault(),!0):(!0===V.data(t.target,this.widgetName+".preventClickEvent")&&V.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return e._mouseMove(t)},this._mouseUpDelegate=function(t){return e._mouseUp(t)},this.document.on("mousemove."+this.widgetName,this._mouseMoveDelegate).on("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),f=!0)):!0}},_mouseMove:function(t){if(this._mouseMoved){if(V.ui.ie&&(!document.documentMode||document.documentMode<9)&&!t.button)return this._mouseUp(t);if(!t.which)if(t.originalEvent.altKey||t.originalEvent.ctrlKey||t.originalEvent.metaKey||t.originalEvent.shiftKey)this.ignoreMissingWhich=!0;else if(!this.ignoreMissingWhich)return this._mouseUp(t)}return(t.which||t.button)&&(this._mouseMoved=!0),this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=!1!==this._mouseStart(this._mouseDownEvent,t),this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){this.document.off("mousemove."+this.widgetName,this._mouseMoveDelegate).off("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&V.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),this._mouseDelayTimer&&(clearTimeout(this._mouseDelayTimer),delete this._mouseDelayTimer),this.ignoreMissingWhich=!1,f=!1,t.preventDefault()},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}}),V.ui.plugin={add:function(t,e,i){var s,n=V.ui[t].prototype;for(s in i)n.plugins[s]=n.plugins[s]||[],n.plugins[s].push([e,i[s]])},call:function(t,e,i,s){var n,o=t.plugins[e];if(o&&(s||t.element[0].parentNode&&11!==t.element[0].parentNode.nodeType))for(n=0;n<o.length;n++)t.options[o[n][0]]&&o[n][1].apply(t.element,i)}},V.ui.safeActiveElement=function(e){var i;try{i=e.activeElement}catch(t){i=e.body}return i=!(i=i||e.body).nodeName?e.body:i},V.ui.safeBlur=function(t){t&&"body"!==t.nodeName.toLowerCase()&&V(t).trigger("blur")};V.widget("ui.draggable",V.ui.mouse,{version:"1.13.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"===this.options.helper&&this._setPositionRelative(),this.options.addClasses&&this._addClass("ui-draggable"),this._setHandleClassName(),this._mouseInit()},_setOption:function(t,e){this._super(t,e),"handle"===t&&(this._removeHandleClassName(),this._setHandleClassName())},_destroy:function(){(this.helper||this.element).is(".ui-draggable-dragging")?this.destroyOnClear=!0:(this._removeHandleClassName(),this._mouseDestroy())},_mouseCapture:function(t){var e=this.options;return!(this.helper||e.disabled||0<V(t.target).closest(".ui-resizable-handle").length)&&(this.handle=this._getHandle(t),!!this.handle&&(this._blurActiveElement(t),this._blockFrames(!0===e.iframeFix?"iframe":e.iframeFix),!0))},_blockFrames:function(t){this.iframeBlocks=this.document.find(t).map(function(){var t=V(this);return V("<div>").css("position","absolute").appendTo(t.parent()).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_blurActiveElement:function(t){var e=V.ui.safeActiveElement(this.document[0]);V(t.target).closest(e).length||V.ui.safeBlur(e)},_mouseStart:function(t){var e=this.options;return this.helper=this._createHelper(t),this._addClass(this.helper,"ui-draggable-dragging"),this._cacheHelperProportions(),V.ui.ddmanager&&(V.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(!0),this.offsetParent=this.helper.offsetParent(),this.hasFixedAncestor=0<this.helper.parents().filter(function(){return"fixed"===V(this).css("position")}).length,this.positionAbs=this.element.offset(),this._refreshOffsets(t),this.originalPosition=this.position=this._generatePosition(t,!1),this.originalPageX=t.pageX,this.originalPageY=t.pageY,e.cursorAt&&this._adjustOffsetFromHelper(e.cursorAt),this._setContainment(),!1===this._trigger("start",t)?(this._clear(),!1):(this._cacheHelperProportions(),V.ui.ddmanager&&!e.dropBehaviour&&V.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),V.ui.ddmanager&&V.ui.ddmanager.dragStart(this,t),!0)},_refreshOffsets:function(t){this.offset={top:this.positionAbs.top-this.margins.top,left:this.positionAbs.left-this.margins.left,scroll:!1,parent:this._getParentOffset(),relative:this._getRelativeOffset()},this.offset.click={left:t.pageX-this.offset.left,top:t.pageY-this.offset.top}},_mouseDrag:function(t,e){if(this.hasFixedAncestor&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t,!0),this.positionAbs=this._convertPositionTo("absolute"),!e){e=this._uiHash();if(!1===this._trigger("drag",t,e))return this._mouseUp(new V.Event("mouseup",t)),!1;this.position=e.position}return this.helper[0].style.left=this.position.left+"px",this.helper[0].style.top=this.position.top+"px",V.ui.ddmanager&&V.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var e=this,i=!1;return V.ui.ddmanager&&!this.options.dropBehaviour&&(i=V.ui.ddmanager.drop(this,t)),this.dropped&&(i=this.dropped,this.dropped=!1),"invalid"===this.options.revert&&!i||"valid"===this.options.revert&&i||!0===this.options.revert||"function"==typeof this.options.revert&&this.options.revert.call(this.element,i)?V(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){!1!==e._trigger("stop",t)&&e._clear()}):!1!==this._trigger("stop",t)&&this._clear(),!1},_mouseUp:function(t){return this._unblockFrames(),V.ui.ddmanager&&V.ui.ddmanager.dragStop(this,t),this.handleElement.is(t.target)&&this.element.trigger("focus"),V.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp(new V.Event("mouseup",{target:this.element[0]})):this._clear(),this},_getHandle:function(t){return!this.options.handle||!!V(t.target).closest(this.element.find(this.options.handle)).length},_setHandleClassName:function(){this.handleElement=this.options.handle?this.element.find(this.options.handle):this.element,this._addClass(this.handleElement,"ui-draggable-handle")},_removeHandleClassName:function(){this._removeClass(this.handleElement,"ui-draggable-handle")},_createHelper:function(t){var e=this.options,i="function"==typeof e.helper,t=i?V(e.helper.apply(this.element[0],[t])):"clone"===e.helper?this.element.clone().removeAttr("id"):this.element;return t.parents("body").length||t.appendTo("parent"===e.appendTo?this.element[0].parentNode:e.appendTo),i&&t[0]===this.element[0]&&this._setPositionRelative(),t[0]===this.element[0]||/(fixed|absolute)/.test(t.css("position"))||t.css("position","absolute"),t},_setPositionRelative:function(){/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative")},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),"left"in(t=Array.isArray(t)?{left:+t[0],top:+t[1]||0}:t)&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_isRootNode:function(t){return/(html|body)/i.test(t.tagName)||t===this.document[0]},_getParentOffset:function(){var t=this.offsetParent.offset(),e=this.document[0];return"absolute"===this.cssPosition&&this.scrollParent[0]!==e&&V.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),{top:(t=this._isRootNode(this.offsetParent[0])?{top:0,left:0}:t).top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var t=this.element.position(),e=this._isRootNode(this.scrollParent[0]);return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+(e?0:this.scrollParent.scrollTop()),left:t.left-(parseInt(this.helper.css("left"),10)||0)+(e?0:this.scrollParent.scrollLeft())}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,e,i,s=this.options,n=this.document[0];this.relativeContainer=null,s.containment?"window"!==s.containment?"document"!==s.containment?s.containment.constructor!==Array?("parent"===s.containment&&(s.containment=this.helper[0].parentNode),(i=(e=V(s.containment))[0])&&(t=/(scroll|auto)/.test(e.css("overflow")),this.containment=[(parseInt(e.css("borderLeftWidth"),10)||0)+(parseInt(e.css("paddingLeft"),10)||0),(parseInt(e.css("borderTopWidth"),10)||0)+(parseInt(e.css("paddingTop"),10)||0),(t?Math.max(i.scrollWidth,i.offsetWidth):i.offsetWidth)-(parseInt(e.css("borderRightWidth"),10)||0)-(parseInt(e.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(i.scrollHeight,i.offsetHeight):i.offsetHeight)-(parseInt(e.css("borderBottomWidth"),10)||0)-(parseInt(e.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relativeContainer=e)):this.containment=s.containment:this.containment=[0,0,V(n).width()-this.helperProportions.width-this.margins.left,(V(n).height()||n.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]:this.containment=[V(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,V(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,V(window).scrollLeft()+V(window).width()-this.helperProportions.width-this.margins.left,V(window).scrollTop()+(V(window).height()||n.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]:this.containment=null},_convertPositionTo:function(t,e){e=e||this.position;var i="absolute"===t?1:-1,t=this._isRootNode(this.scrollParent[0]);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.offset.scroll.top:t?0:this.offset.scroll.top)*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.offset.scroll.left:t?0:this.offset.scroll.left)*i}},_generatePosition:function(t,e){var i,s=this.options,n=this._isRootNode(this.scrollParent[0]),o=t.pageX,a=t.pageY;return n&&this.offset.scroll||(this.offset.scroll={top:this.scrollParent.scrollTop(),left:this.scrollParent.scrollLeft()}),e&&(this.containment&&(i=this.relativeContainer?(i=this.relativeContainer.offset(),[this.containment[0]+i.left,this.containment[1]+i.top,this.containment[2]+i.left,this.containment[3]+i.top]):this.containment,t.pageX-this.offset.click.left<i[0]&&(o=i[0]+this.offset.click.left),t.pageY-this.offset.click.top<i[1]&&(a=i[1]+this.offset.click.top),t.pageX-this.offset.click.left>i[2]&&(o=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(a=i[3]+this.offset.click.top)),s.grid&&(t=s.grid[1]?this.originalPageY+Math.round((a-this.originalPageY)/s.grid[1])*s.grid[1]:this.originalPageY,a=!i||t-this.offset.click.top>=i[1]||t-this.offset.click.top>i[3]?t:t-this.offset.click.top>=i[1]?t-s.grid[1]:t+s.grid[1],t=s.grid[0]?this.originalPageX+Math.round((o-this.originalPageX)/s.grid[0])*s.grid[0]:this.originalPageX,o=!i||t-this.offset.click.left>=i[0]||t-this.offset.click.left>i[2]?t:t-this.offset.click.left>=i[0]?t-s.grid[0]:t+s.grid[0]),"y"===s.axis&&(o=this.originalPageX),"x"===s.axis&&(a=this.originalPageY)),{top:a-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.offset.scroll.top:n?0:this.offset.scroll.top),left:o-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.offset.scroll.left:n?0:this.offset.scroll.left)}},_clear:function(){this._removeClass(this.helper,"ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1,this.destroyOnClear&&this.destroy()},_trigger:function(t,e,i){return i=i||this._uiHash(),V.ui.plugin.call(this,t,[e,i,this],!0),/^(drag|start|stop)/.test(t)&&(this.positionAbs=this._convertPositionTo("absolute"),i.offset=this.positionAbs),V.Widget.prototype._trigger.call(this,t,e,i)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),V.ui.plugin.add("draggable","connectToSortable",{start:function(e,t,i){var s=V.extend({},t,{item:i.element});i.sortables=[],V(i.options.connectToSortable).each(function(){var t=V(this).sortable("instance");t&&!t.options.disabled&&(i.sortables.push(t),t.refreshPositions(),t._trigger("activate",e,s))})},stop:function(e,t,i){var s=V.extend({},t,{item:i.element});i.cancelHelperRemoval=!1,V.each(i.sortables,function(){var t=this;t.isOver?(t.isOver=0,i.cancelHelperRemoval=!0,t.cancelHelperRemoval=!1,t._storedCSS={position:t.placeholder.css("position"),top:t.placeholder.css("top"),left:t.placeholder.css("left")},t._mouseStop(e),t.options.helper=t.options._helper):(t.cancelHelperRemoval=!0,t._trigger("deactivate",e,s))})},drag:function(i,s,n){V.each(n.sortables,function(){var t=!1,e=this;e.positionAbs=n.positionAbs,e.helperProportions=n.helperProportions,e.offset.click=n.offset.click,e._intersectsWith(e.containerCache)&&(t=!0,V.each(n.sortables,function(){return this.positionAbs=n.positionAbs,this.helperProportions=n.helperProportions,this.offset.click=n.offset.click,t=this!==e&&this._intersectsWith(this.containerCache)&&V.contains(e.element[0],this.element[0])?!1:t})),t?(e.isOver||(e.isOver=1,n._parent=s.helper.parent(),e.currentItem=s.helper.appendTo(e.element).data("ui-sortable-item",!0),e.options._helper=e.options.helper,e.options.helper=function(){return s.helper[0]},i.target=e.currentItem[0],e._mouseCapture(i,!0),e._mouseStart(i,!0,!0),e.offset.click.top=n.offset.click.top,e.offset.click.left=n.offset.click.left,e.offset.parent.left-=n.offset.parent.left-e.offset.parent.left,e.offset.parent.top-=n.offset.parent.top-e.offset.parent.top,n._trigger("toSortable",i),n.dropped=e.element,V.each(n.sortables,function(){this.refreshPositions()}),n.currentItem=n.element,e.fromOutside=n),e.currentItem&&(e._mouseDrag(i),s.position=e.position)):e.isOver&&(e.isOver=0,e.cancelHelperRemoval=!0,e.options._revert=e.options.revert,e.options.revert=!1,e._trigger("out",i,e._uiHash(e)),e._mouseStop(i,!0),e.options.revert=e.options._revert,e.options.helper=e.options._helper,e.placeholder&&e.placeholder.remove(),s.helper.appendTo(n._parent),n._refreshOffsets(i),s.position=n._generatePosition(i,!0),n._trigger("fromSortable",i),n.dropped=!1,V.each(n.sortables,function(){this.refreshPositions()}))})}}),V.ui.plugin.add("draggable","cursor",{start:function(t,e,i){var s=V("body"),i=i.options;s.css("cursor")&&(i._cursor=s.css("cursor")),s.css("cursor",i.cursor)},stop:function(t,e,i){i=i.options;i._cursor&&V("body").css("cursor",i._cursor)}}),V.ui.plugin.add("draggable","opacity",{start:function(t,e,i){e=V(e.helper),i=i.options;e.css("opacity")&&(i._opacity=e.css("opacity")),e.css("opacity",i.opacity)},stop:function(t,e,i){i=i.options;i._opacity&&V(e.helper).css("opacity",i._opacity)}}),V.ui.plugin.add("draggable","scroll",{start:function(t,e,i){i.scrollParentNotHidden||(i.scrollParentNotHidden=i.helper.scrollParent(!1)),i.scrollParentNotHidden[0]!==i.document[0]&&"HTML"!==i.scrollParentNotHidden[0].tagName&&(i.overflowOffset=i.scrollParentNotHidden.offset())},drag:function(t,e,i){var s=i.options,n=!1,o=i.scrollParentNotHidden[0],a=i.document[0];o!==a&&"HTML"!==o.tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+o.offsetHeight-t.pageY<s.scrollSensitivity?o.scrollTop=n=o.scrollTop+s.scrollSpeed:t.pageY-i.overflowOffset.top<s.scrollSensitivity&&(o.scrollTop=n=o.scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+o.offsetWidth-t.pageX<s.scrollSensitivity?o.scrollLeft=n=o.scrollLeft+s.scrollSpeed:t.pageX-i.overflowOffset.left<s.scrollSensitivity&&(o.scrollLeft=n=o.scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(t.pageY-V(a).scrollTop()<s.scrollSensitivity?n=V(a).scrollTop(V(a).scrollTop()-s.scrollSpeed):V(window).height()-(t.pageY-V(a).scrollTop())<s.scrollSensitivity&&(n=V(a).scrollTop(V(a).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(t.pageX-V(a).scrollLeft()<s.scrollSensitivity?n=V(a).scrollLeft(V(a).scrollLeft()-s.scrollSpeed):V(window).width()-(t.pageX-V(a).scrollLeft())<s.scrollSensitivity&&(n=V(a).scrollLeft(V(a).scrollLeft()+s.scrollSpeed)))),!1!==n&&V.ui.ddmanager&&!s.dropBehaviour&&V.ui.ddmanager.prepareOffsets(i,t)}}),V.ui.plugin.add("draggable","snap",{start:function(t,e,i){var s=i.options;i.snapElements=[],V(s.snap.constructor!==String?s.snap.items||":data(ui-draggable)":s.snap).each(function(){var t=V(this),e=t.offset();this!==i.element[0]&&i.snapElements.push({item:this,width:t.outerWidth(),height:t.outerHeight(),top:e.top,left:e.left})})},drag:function(t,e,i){for(var s,n,o,a,r,l,h,c,u,d=i.options,p=d.snapTolerance,f=e.offset.left,g=f+i.helperProportions.width,m=e.offset.top,_=m+i.helperProportions.height,v=i.snapElements.length-1;0<=v;v--)l=(r=i.snapElements[v].left-i.margins.left)+i.snapElements[v].width,c=(h=i.snapElements[v].top-i.margins.top)+i.snapElements[v].height,g<r-p||l+p<f||_<h-p||c+p<m||!V.contains(i.snapElements[v].item.ownerDocument,i.snapElements[v].item)?(i.snapElements[v].snapping&&i.options.snap.release&&i.options.snap.release.call(i.element,t,V.extend(i._uiHash(),{snapItem:i.snapElements[v].item})),i.snapElements[v].snapping=!1):("inner"!==d.snapMode&&(s=Math.abs(h-_)<=p,n=Math.abs(c-m)<=p,o=Math.abs(r-g)<=p,a=Math.abs(l-f)<=p,s&&(e.position.top=i._convertPositionTo("relative",{top:h-i.helperProportions.height,left:0}).top),n&&(e.position.top=i._convertPositionTo("relative",{top:c,left:0}).top),o&&(e.position.left=i._convertPositionTo("relative",{top:0,left:r-i.helperProportions.width}).left),a&&(e.position.left=i._convertPositionTo("relative",{top:0,left:l}).left)),u=s||n||o||a,"outer"!==d.snapMode&&(s=Math.abs(h-m)<=p,n=Math.abs(c-_)<=p,o=Math.abs(r-f)<=p,a=Math.abs(l-g)<=p,s&&(e.position.top=i._convertPositionTo("relative",{top:h,left:0}).top),n&&(e.position.top=i._convertPositionTo("relative",{top:c-i.helperProportions.height,left:0}).top),o&&(e.position.left=i._convertPositionTo("relative",{top:0,left:r}).left),a&&(e.position.left=i._convertPositionTo("relative",{top:0,left:l-i.helperProportions.width}).left)),!i.snapElements[v].snapping&&(s||n||o||a||u)&&i.options.snap.snap&&i.options.snap.snap.call(i.element,t,V.extend(i._uiHash(),{snapItem:i.snapElements[v].item})),i.snapElements[v].snapping=s||n||o||a||u)}}),V.ui.plugin.add("draggable","stack",{start:function(t,e,i){var s,i=i.options,i=V.makeArray(V(i.stack)).sort(function(t,e){return(parseInt(V(t).css("zIndex"),10)||0)-(parseInt(V(e).css("zIndex"),10)||0)});i.length&&(s=parseInt(V(i[0]).css("zIndex"),10)||0,V(i).each(function(t){V(this).css("zIndex",s+t)}),this.css("zIndex",s+i.length))}}),V.ui.plugin.add("draggable","zIndex",{start:function(t,e,i){e=V(e.helper),i=i.options;e.css("zIndex")&&(i._zIndex=e.css("zIndex")),e.css("zIndex",i.zIndex)},stop:function(t,e,i){i=i.options;i._zIndex&&V(e.helper).css("zIndex",i._zIndex)}});V.ui.draggable;function g(t,e,i){return e<=t&&t<e+i}V.widget("ui.droppable",{version:"1.13.2",widgetEventPrefix:"drop",options:{accept:"*",addClasses:!0,greedy:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t,e=this.options,i=e.accept;this.isover=!1,this.isout=!0,this.accept="function"==typeof i?i:function(t){return t.is(i)},this.proportions=function(){if(!arguments.length)return t=t||{width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};t=arguments[0]},this._addToManager(e.scope),e.addClasses&&this._addClass("ui-droppable")},_addToManager:function(t){V.ui.ddmanager.droppables[t]=V.ui.ddmanager.droppables[t]||[],V.ui.ddmanager.droppables[t].push(this)},_splice:function(t){for(var e=0;e<t.length;e++)t[e]===this&&t.splice(e,1)},_destroy:function(){var t=V.ui.ddmanager.droppables[this.options.scope];this._splice(t)},_setOption:function(t,e){var i;"accept"===t?this.accept="function"==typeof e?e:function(t){return t.is(e)}:"scope"===t&&(i=V.ui.ddmanager.droppables[this.options.scope],this._splice(i),this._addToManager(e)),this._super(t,e)},_activate:function(t){var e=V.ui.ddmanager.current;this._addActiveClass(),e&&this._trigger("activate",t,this.ui(e))},_deactivate:function(t){var e=V.ui.ddmanager.current;this._removeActiveClass(),e&&this._trigger("deactivate",t,this.ui(e))},_over:function(t){var e=V.ui.ddmanager.current;e&&(e.currentItem||e.element)[0]!==this.element[0]&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this._addHoverClass(),this._trigger("over",t,this.ui(e)))},_out:function(t){var e=V.ui.ddmanager.current;e&&(e.currentItem||e.element)[0]!==this.element[0]&&this.accept.call(this.element[0],e.currentItem||e.element)&&(this._removeHoverClass(),this._trigger("out",t,this.ui(e)))},_drop:function(e,t){var i=t||V.ui.ddmanager.current,s=!1;return!(!i||(i.currentItem||i.element)[0]===this.element[0])&&(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var t=V(this).droppable("instance");if(t.options.greedy&&!t.options.disabled&&t.options.scope===i.options.scope&&t.accept.call(t.element[0],i.currentItem||i.element)&&V.ui.intersect(i,V.extend(t,{offset:t.element.offset()}),t.options.tolerance,e))return!(s=!0)}),!s&&(!!this.accept.call(this.element[0],i.currentItem||i.element)&&(this._removeActiveClass(),this._removeHoverClass(),this._trigger("drop",e,this.ui(i)),this.element)))},ui:function(t){return{draggable:t.currentItem||t.element,helper:t.helper,position:t.position,offset:t.positionAbs}},_addHoverClass:function(){this._addClass("ui-droppable-hover")},_removeHoverClass:function(){this._removeClass("ui-droppable-hover")},_addActiveClass:function(){this._addClass("ui-droppable-active")},_removeActiveClass:function(){this._removeClass("ui-droppable-active")}}),V.ui.intersect=function(t,e,i,s){if(!e.offset)return!1;var n=(t.positionAbs||t.position.absolute).left+t.margins.left,o=(t.positionAbs||t.position.absolute).top+t.margins.top,a=n+t.helperProportions.width,r=o+t.helperProportions.height,l=e.offset.left,h=e.offset.top,c=l+e.proportions().width,u=h+e.proportions().height;switch(i){case"fit":return l<=n&&a<=c&&h<=o&&r<=u;case"intersect":return l<n+t.helperProportions.width/2&&a-t.helperProportions.width/2<c&&h<o+t.helperProportions.height/2&&r-t.helperProportions.height/2<u;case"pointer":return g(s.pageY,h,e.proportions().height)&&g(s.pageX,l,e.proportions().width);case"touch":return(h<=o&&o<=u||h<=r&&r<=u||o<h&&u<r)&&(l<=n&&n<=c||l<=a&&a<=c||n<l&&c<a);default:return!1}},!(V.ui.ddmanager={current:null,droppables:{default:[]},prepareOffsets:function(t,e){var i,s,n=V.ui.ddmanager.droppables[t.options.scope]||[],o=e?e.type:null,a=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();t:for(i=0;i<n.length;i++)if(!(n[i].options.disabled||t&&!n[i].accept.call(n[i].element[0],t.currentItem||t.element))){for(s=0;s<a.length;s++)if(a[s]===n[i].element[0]){n[i].proportions().height=0;continue t}n[i].visible="none"!==n[i].element.css("display"),n[i].visible&&("mousedown"===o&&n[i]._activate.call(n[i],e),n[i].offset=n[i].element.offset(),n[i].proportions({width:n[i].element[0].offsetWidth,height:n[i].element[0].offsetHeight}))}},drop:function(t,e){var i=!1;return V.each((V.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&V.ui.intersect(t,this,this.options.tolerance,e)&&(i=this._drop.call(this,e)||i),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,e)))}),i},dragStart:function(t,e){t.element.parentsUntil("body").on("scroll.droppable",function(){t.options.refreshPositions||V.ui.ddmanager.prepareOffsets(t,e)})},drag:function(n,o){n.options.refreshPositions&&V.ui.ddmanager.prepareOffsets(n,o),V.each(V.ui.ddmanager.droppables[n.options.scope]||[],function(){var t,e,i,s;this.options.disabled||this.greedyChild||!this.visible||(s=!(i=V.ui.intersect(n,this,this.options.tolerance,o))&&this.isover?"isout":i&&!this.isover?"isover":null)&&(this.options.greedy&&(e=this.options.scope,(i=this.element.parents(":data(ui-droppable)").filter(function(){return V(this).droppable("instance").options.scope===e})).length&&((t=V(i[0]).droppable("instance")).greedyChild="isover"===s)),t&&"isover"===s&&(t.isover=!1,t.isout=!0,t._out.call(t,o)),this[s]=!0,this["isout"===s?"isover":"isout"]=!1,this["isover"===s?"_over":"_out"].call(this,o),t&&"isout"===s&&(t.isout=!1,t.isover=!0,t._over.call(t,o)))})},dragStop:function(t,e){t.element.parentsUntil("body").off("scroll.droppable"),t.options.refreshPositions||V.ui.ddmanager.prepareOffsets(t,e)}})!==V.uiBackCompat&&V.widget("ui.droppable",V.ui.droppable,{options:{hoverClass:!1,activeClass:!1},_addActiveClass:function(){this._super(),this.options.activeClass&&this.element.addClass(this.options.activeClass)},_removeActiveClass:function(){this._super(),this.options.activeClass&&this.element.removeClass(this.options.activeClass)},_addHoverClass:function(){this._super(),this.options.hoverClass&&this.element.addClass(this.options.hoverClass)},_removeHoverClass:function(){this._super(),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass)}});V.ui.droppable;V.widget("ui.resizable",V.ui.mouse,{version:"1.13.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,classes:{"ui-resizable-se":"ui-icon ui-icon-gripsmall-diagonal-se"},containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_num:function(t){return parseFloat(t)||0},_isNumber:function(t){return!isNaN(parseFloat(t))},_hasScroll:function(t,e){if("hidden"===V(t).css("overflow"))return!1;var i=e&&"left"===e?"scrollLeft":"scrollTop",e=!1;if(0<t[i])return!0;try{t[i]=1,e=0<t[i],t[i]=0}catch(t){}return e},_create:function(){var t,e=this.options,i=this;this._addClass("ui-resizable"),V.extend(this,{_aspectRatio:!!e.aspectRatio,aspectRatio:e.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:e.helper||e.ghost||e.animate?e.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)&&(this.element.wrap(V("<div class='ui-wrapper'></div>").css({overflow:"hidden",position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.resizable("instance")),this.elementIsWrapper=!0,t={marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom"),marginLeft:this.originalElement.css("marginLeft")},this.element.css(t),this.originalElement.css("margin",0),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css(t),this._proportionallyResize()),this._setupHandles(),e.autoHide&&V(this.element).on("mouseenter",function(){e.disabled||(i._removeClass("ui-resizable-autohide"),i._handles.show())}).on("mouseleave",function(){e.disabled||i.resizing||(i._addClass("ui-resizable-autohide"),i._handles.hide())}),this._mouseInit()},_destroy:function(){this._mouseDestroy(),this._addedHandles.remove();function t(t){V(t).removeData("resizable").removeData("ui-resizable").off(".resizable")}var e;return this.elementIsWrapper&&(t(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_setOption:function(t,e){switch(this._super(t,e),t){case"handles":this._removeHandles(),this._setupHandles();break;case"aspectRatio":this._aspectRatio=!!e}},_setupHandles:function(){var t,e,i,s,n,o=this.options,a=this;if(this.handles=o.handles||(V(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this._handles=V(),this._addedHandles=V(),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),i=this.handles.split(","),this.handles={},e=0;e<i.length;e++)s="ui-resizable-"+(t=String.prototype.trim.call(i[e])),n=V("<div>"),this._addClass(n,"ui-resizable-handle "+s),n.css({zIndex:o.zIndex}),this.handles[t]=".ui-resizable-"+t,this.element.children(this.handles[t]).length||(this.element.append(n),this._addedHandles=this._addedHandles.add(n));this._renderAxis=function(t){var e,i,s;for(e in t=t||this.element,this.handles)this.handles[e].constructor===String?this.handles[e]=this.element.children(this.handles[e]).first().show():(this.handles[e].jquery||this.handles[e].nodeType)&&(this.handles[e]=V(this.handles[e]),this._on(this.handles[e],{mousedown:a._mouseDown})),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)&&(i=V(this.handles[e],this.element),s=/sw|ne|nw|se|n|s/.test(e)?i.outerHeight():i.outerWidth(),i=["padding",/ne|nw|n/.test(e)?"Top":/se|sw|s/.test(e)?"Bottom":/^e$/.test(e)?"Right":"Left"].join(""),t.css(i,s),this._proportionallyResize()),this._handles=this._handles.add(this.handles[e])},this._renderAxis(this.element),this._handles=this._handles.add(this.element.find(".ui-resizable-handle")),this._handles.disableSelection(),this._handles.on("mouseover",function(){a.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),a.axis=n&&n[1]?n[1]:"se")}),o.autoHide&&(this._handles.hide(),this._addClass("ui-resizable-autohide"))},_removeHandles:function(){this._addedHandles.remove()},_mouseCapture:function(t){var e,i,s=!1;for(e in this.handles)(i=V(this.handles[e])[0])!==t.target&&!V.contains(i,t.target)||(s=!0);return!this.options.disabled&&s},_mouseStart:function(t){var e,i,s=this.options,n=this.element;return this.resizing=!0,this._renderProxy(),e=this._num(this.helper.css("left")),i=this._num(this.helper.css("top")),s.containment&&(e+=V(s.containment).scrollLeft()||0,i+=V(s.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:e,top:i},this.size=this._helper?{width:this.helper.width(),height:this.helper.height()}:{width:n.width(),height:n.height()},this.originalSize=this._helper?{width:n.outerWidth(),height:n.outerHeight()}:{width:n.width(),height:n.height()},this.sizeDiff={width:n.outerWidth()-n.width(),height:n.outerHeight()-n.height()},this.originalPosition={left:e,top:i},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio="number"==typeof s.aspectRatio?s.aspectRatio:this.originalSize.width/this.originalSize.height||1,s=V(".ui-resizable-"+this.axis).css("cursor"),V("body").css("cursor","auto"===s?this.axis+"-resize":s),this._addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(t){var e=this.originalMousePosition,i=this.axis,s=t.pageX-e.left||0,e=t.pageY-e.top||0,i=this._change[i];return this._updatePrevProperties(),i&&(e=i.apply(this,[t,s,e]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(e=this._updateRatio(e,t)),e=this._respectSize(e,t),this._updateCache(e),this._propagate("resize",t),e=this._applyChanges(),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),V.isEmptyObject(e)||(this._updatePrevProperties(),this._trigger("resize",t,this.ui()),this._applyChanges())),!1},_mouseStop:function(t){this.resizing=!1;var e,i,s,n=this.options,o=this;return this._helper&&(s=(e=(i=this._proportionallyResizeElements).length&&/textarea/i.test(i[0].nodeName))&&this._hasScroll(i[0],"left")?0:o.sizeDiff.height,i=e?0:o.sizeDiff.width,e={width:o.helper.width()-i,height:o.helper.height()-s},i=parseFloat(o.element.css("left"))+(o.position.left-o.originalPosition.left)||null,s=parseFloat(o.element.css("top"))+(o.position.top-o.originalPosition.top)||null,n.animate||this.element.css(V.extend(e,{top:s,left:i})),o.helper.height(o.size.height),o.helper.width(o.size.width),this._helper&&!n.animate&&this._proportionallyResize()),V("body").css("cursor","auto"),this._removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updatePrevProperties:function(){this.prevPosition={top:this.position.top,left:this.position.left},this.prevSize={width:this.size.width,height:this.size.height}},_applyChanges:function(){var t={};return this.position.top!==this.prevPosition.top&&(t.top=this.position.top+"px"),this.position.left!==this.prevPosition.left&&(t.left=this.position.left+"px"),this.size.width!==this.prevSize.width&&(t.width=this.size.width+"px"),this.size.height!==this.prevSize.height&&(t.height=this.size.height+"px"),this.helper.css(t),t},_updateVirtualBoundaries:function(t){var e,i,s=this.options,n={minWidth:this._isNumber(s.minWidth)?s.minWidth:0,maxWidth:this._isNumber(s.maxWidth)?s.maxWidth:1/0,minHeight:this._isNumber(s.minHeight)?s.minHeight:0,maxHeight:this._isNumber(s.maxHeight)?s.maxHeight:1/0};(this._aspectRatio||t)&&(e=n.minHeight*this.aspectRatio,i=n.minWidth/this.aspectRatio,s=n.maxHeight*this.aspectRatio,t=n.maxWidth/this.aspectRatio,e>n.minWidth&&(n.minWidth=e),i>n.minHeight&&(n.minHeight=i),s<n.maxWidth&&(n.maxWidth=s),t<n.maxHeight&&(n.maxHeight=t)),this._vBoundaries=n},_updateCache:function(t){this.offset=this.helper.offset(),this._isNumber(t.left)&&(this.position.left=t.left),this._isNumber(t.top)&&(this.position.top=t.top),this._isNumber(t.height)&&(this.size.height=t.height),this._isNumber(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,i=this.size,s=this.axis;return this._isNumber(t.height)?t.width=t.height*this.aspectRatio:this._isNumber(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===s&&(t.left=e.left+(i.width-t.width),t.top=null),"nw"===s&&(t.top=e.top+(i.height-t.height),t.left=e.left+(i.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,i=this.axis,s=this._isNumber(t.width)&&e.maxWidth&&e.maxWidth<t.width,n=this._isNumber(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=this._isNumber(t.width)&&e.minWidth&&e.minWidth>t.width,a=this._isNumber(t.height)&&e.minHeight&&e.minHeight>t.height,r=this.originalPosition.left+this.originalSize.width,l=this.originalPosition.top+this.originalSize.height,h=/sw|nw|w/.test(i),i=/nw|ne|n/.test(i);return o&&(t.width=e.minWidth),a&&(t.height=e.minHeight),s&&(t.width=e.maxWidth),n&&(t.height=e.maxHeight),o&&h&&(t.left=r-e.minWidth),s&&h&&(t.left=r-e.maxWidth),a&&i&&(t.top=l-e.minHeight),n&&i&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_getPaddingPlusBorderDimensions:function(t){for(var e=0,i=[],s=[t.css("borderTopWidth"),t.css("borderRightWidth"),t.css("borderBottomWidth"),t.css("borderLeftWidth")],n=[t.css("paddingTop"),t.css("paddingRight"),t.css("paddingBottom"),t.css("paddingLeft")];e<4;e++)i[e]=parseFloat(s[e])||0,i[e]+=parseFloat(n[e])||0;return{height:i[0]+i[2],width:i[1]+i[3]}},_proportionallyResize:function(){if(this._proportionallyResizeElements.length)for(var t,e=0,i=this.helper||this.element;e<this._proportionallyResizeElements.length;e++)t=this._proportionallyResizeElements[e],this.outerDimensions||(this.outerDimensions=this._getPaddingPlusBorderDimensions(t)),t.css({height:i.height()-this.outerDimensions.height||0,width:i.width()-this.outerDimensions.width||0})},_renderProxy:function(){var t=this.element,e=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||V("<div></div>").css({overflow:"hidden"}),this._addClass(this.helper,this._helper),this.helper.css({width:this.element.outerWidth(),height:this.element.outerHeight(),position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++e.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize;return{left:this.originalPosition.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize;return{top:this.originalPosition.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(t,e,i){return V.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},sw:function(t,e,i){return V.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,e,i]))},ne:function(t,e,i){return V.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,e,i]))},nw:function(t,e,i){return V.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,e,i]))}},_propagate:function(t,e){V.ui.plugin.call(this,t,[e,this.ui()]),"resize"!==t&&this._trigger(t,e,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),V.ui.plugin.add("resizable","animate",{stop:function(e){var i=V(this).resizable("instance"),t=i.options,s=i._proportionallyResizeElements,n=s.length&&/textarea/i.test(s[0].nodeName),o=n&&i._hasScroll(s[0],"left")?0:i.sizeDiff.height,a=n?0:i.sizeDiff.width,n={width:i.size.width-a,height:i.size.height-o},a=parseFloat(i.element.css("left"))+(i.position.left-i.originalPosition.left)||null,o=parseFloat(i.element.css("top"))+(i.position.top-i.originalPosition.top)||null;i.element.animate(V.extend(n,o&&a?{top:o,left:a}:{}),{duration:t.animateDuration,easing:t.animateEasing,step:function(){var t={width:parseFloat(i.element.css("width")),height:parseFloat(i.element.css("height")),top:parseFloat(i.element.css("top")),left:parseFloat(i.element.css("left"))};s&&s.length&&V(s[0]).css({width:t.width,height:t.height}),i._updateCache(t),i._propagate("resize",e)}})}}),V.ui.plugin.add("resizable","containment",{start:function(){var i,s,n=V(this).resizable("instance"),t=n.options,e=n.element,o=t.containment,a=o instanceof V?o.get(0):/parent/.test(o)?e.parent().get(0):o;a&&(n.containerElement=V(a),/document/.test(o)||o===document?(n.containerOffset={left:0,top:0},n.containerPosition={left:0,top:0},n.parentData={element:V(document),left:0,top:0,width:V(document).width(),height:V(document).height()||document.body.parentNode.scrollHeight}):(i=V(a),s=[],V(["Top","Right","Left","Bottom"]).each(function(t,e){s[t]=n._num(i.css("padding"+e))}),n.containerOffset=i.offset(),n.containerPosition=i.position(),n.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},t=n.containerOffset,e=n.containerSize.height,o=n.containerSize.width,o=n._hasScroll(a,"left")?a.scrollWidth:o,e=n._hasScroll(a)?a.scrollHeight:e,n.parentData={element:a,left:t.left,top:t.top,width:o,height:e}))},resize:function(t){var e=V(this).resizable("instance"),i=e.options,s=e.containerOffset,n=e.position,o=e._aspectRatio||t.shiftKey,a={top:0,left:0},r=e.containerElement,t=!0;r[0]!==document&&/static/.test(r.css("position"))&&(a=s),n.left<(e._helper?s.left:0)&&(e.size.width=e.size.width+(e._helper?e.position.left-s.left:e.position.left-a.left),o&&(e.size.height=e.size.width/e.aspectRatio,t=!1),e.position.left=i.helper?s.left:0),n.top<(e._helper?s.top:0)&&(e.size.height=e.size.height+(e._helper?e.position.top-s.top:e.position.top),o&&(e.size.width=e.size.height*e.aspectRatio,t=!1),e.position.top=e._helper?s.top:0),i=e.containerElement.get(0)===e.element.parent().get(0),n=/relative|absolute/.test(e.containerElement.css("position")),i&&n?(e.offset.left=e.parentData.left+e.position.left,e.offset.top=e.parentData.top+e.position.top):(e.offset.left=e.element.offset().left,e.offset.top=e.element.offset().top),n=Math.abs(e.sizeDiff.width+(e._helper?e.offset.left-a.left:e.offset.left-s.left)),s=Math.abs(e.sizeDiff.height+(e._helper?e.offset.top-a.top:e.offset.top-s.top)),n+e.size.width>=e.parentData.width&&(e.size.width=e.parentData.width-n,o&&(e.size.height=e.size.width/e.aspectRatio,t=!1)),s+e.size.height>=e.parentData.height&&(e.size.height=e.parentData.height-s,o&&(e.size.width=e.size.height*e.aspectRatio,t=!1)),t||(e.position.left=e.prevPosition.left,e.position.top=e.prevPosition.top,e.size.width=e.prevSize.width,e.size.height=e.prevSize.height)},stop:function(){var t=V(this).resizable("instance"),e=t.options,i=t.containerOffset,s=t.containerPosition,n=t.containerElement,o=V(t.helper),a=o.offset(),r=o.outerWidth()-t.sizeDiff.width,o=o.outerHeight()-t.sizeDiff.height;t._helper&&!e.animate&&/relative/.test(n.css("position"))&&V(this).css({left:a.left-s.left-i.left,width:r,height:o}),t._helper&&!e.animate&&/static/.test(n.css("position"))&&V(this).css({left:a.left-s.left-i.left,width:r,height:o})}}),V.ui.plugin.add("resizable","alsoResize",{start:function(){var t=V(this).resizable("instance").options;V(t.alsoResize).each(function(){var t=V(this);t.data("ui-resizable-alsoresize",{width:parseFloat(t.width()),height:parseFloat(t.height()),left:parseFloat(t.css("left")),top:parseFloat(t.css("top"))})})},resize:function(t,i){var e=V(this).resizable("instance"),s=e.options,n=e.originalSize,o=e.originalPosition,a={height:e.size.height-n.height||0,width:e.size.width-n.width||0,top:e.position.top-o.top||0,left:e.position.left-o.left||0};V(s.alsoResize).each(function(){var t=V(this),s=V(this).data("ui-resizable-alsoresize"),n={},e=t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];V.each(e,function(t,e){var i=(s[e]||0)+(a[e]||0);i&&0<=i&&(n[e]=i||null)}),t.css(n)})},stop:function(){V(this).removeData("ui-resizable-alsoresize")}}),V.ui.plugin.add("resizable","ghost",{start:function(){var t=V(this).resizable("instance"),e=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}),t._addClass(t.ghost,"ui-resizable-ghost"),!1!==V.uiBackCompat&&"string"==typeof t.options.ghost&&t.ghost.addClass(this.options.ghost),t.ghost.appendTo(t.helper)},resize:function(){var t=V(this).resizable("instance");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=V(this).resizable("instance");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),V.ui.plugin.add("resizable","grid",{resize:function(){var t,e=V(this).resizable("instance"),i=e.options,s=e.size,n=e.originalSize,o=e.originalPosition,a=e.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,l=r[0]||1,h=r[1]||1,c=Math.round((s.width-n.width)/l)*l,u=Math.round((s.height-n.height)/h)*h,d=n.width+c,p=n.height+u,f=i.maxWidth&&i.maxWidth<d,g=i.maxHeight&&i.maxHeight<p,m=i.minWidth&&i.minWidth>d,s=i.minHeight&&i.minHeight>p;i.grid=r,m&&(d+=l),s&&(p+=h),f&&(d-=l),g&&(p-=h),/^(se|s|e)$/.test(a)?(e.size.width=d,e.size.height=p):/^(ne)$/.test(a)?(e.size.width=d,e.size.height=p,e.position.top=o.top-u):/^(sw)$/.test(a)?(e.size.width=d,e.size.height=p,e.position.left=o.left-c):((p-h<=0||d-l<=0)&&(t=e._getPaddingPlusBorderDimensions(this)),0<p-h?(e.size.height=p,e.position.top=o.top-u):(p=h-t.height,e.size.height=p,e.position.top=o.top+n.height-p),0<d-l?(e.size.width=d,e.position.left=o.left-c):(d=l-t.width,e.size.width=d,e.position.left=o.left+n.width-d))}});V.ui.resizable,V.widget("ui.selectable",V.ui.mouse,{version:"1.13.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var i=this;this._addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){i.elementPos=V(i.element[0]).offset(),i.selectees=V(i.options.filter,i.element[0]),i._addClass(i.selectees,"ui-selectee"),i.selectees.each(function(){var t=V(this),e=t.offset(),e={left:e.left-i.elementPos.left,top:e.top-i.elementPos.top};V.data(this,"selectable-item",{element:this,$element:t,left:e.left,top:e.top,right:e.left+t.outerWidth(),bottom:e.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this._mouseInit(),this.helper=V("<div>"),this._addClass(this.helper,"ui-selectable-helper")},_destroy:function(){this.selectees.removeData("selectable-item"),this._mouseDestroy()},_mouseStart:function(i){var s=this,t=this.options;this.opos=[i.pageX,i.pageY],this.elementPos=V(this.element[0]).offset(),this.options.disabled||(this.selectees=V(t.filter,this.element[0]),this._trigger("start",i),V(t.appendTo).append(this.helper),this.helper.css({left:i.pageX,top:i.pageY,width:0,height:0}),t.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var t=V.data(this,"selectable-item");t.startselected=!0,i.metaKey||i.ctrlKey||(s._removeClass(t.$element,"ui-selected"),t.selected=!1,s._addClass(t.$element,"ui-unselecting"),t.unselecting=!0,s._trigger("unselecting",i,{unselecting:t.element}))}),V(i.target).parents().addBack().each(function(){var t,e=V.data(this,"selectable-item");if(e)return t=!i.metaKey&&!i.ctrlKey||!e.$element.hasClass("ui-selected"),s._removeClass(e.$element,t?"ui-unselecting":"ui-selected")._addClass(e.$element,t?"ui-selecting":"ui-unselecting"),e.unselecting=!t,e.selecting=t,(e.selected=t)?s._trigger("selecting",i,{selecting:e.element}):s._trigger("unselecting",i,{unselecting:e.element}),!1}))},_mouseDrag:function(s){if(this.dragged=!0,!this.options.disabled){var t,n=this,o=this.options,a=this.opos[0],r=this.opos[1],l=s.pageX,h=s.pageY;return l<a&&(t=l,l=a,a=t),h<r&&(t=h,h=r,r=t),this.helper.css({left:a,top:r,width:l-a,height:h-r}),this.selectees.each(function(){var t=V.data(this,"selectable-item"),e=!1,i={};t&&t.element!==n.element[0]&&(i.left=t.left+n.elementPos.left,i.right=t.right+n.elementPos.left,i.top=t.top+n.elementPos.top,i.bottom=t.bottom+n.elementPos.top,"touch"===o.tolerance?e=!(i.left>l||i.right<a||i.top>h||i.bottom<r):"fit"===o.tolerance&&(e=i.left>a&&i.right<l&&i.top>r&&i.bottom<h),e?(t.selected&&(n._removeClass(t.$element,"ui-selected"),t.selected=!1),t.unselecting&&(n._removeClass(t.$element,"ui-unselecting"),t.unselecting=!1),t.selecting||(n._addClass(t.$element,"ui-selecting"),t.selecting=!0,n._trigger("selecting",s,{selecting:t.element}))):(t.selecting&&((s.metaKey||s.ctrlKey)&&t.startselected?(n._removeClass(t.$element,"ui-selecting"),t.selecting=!1,n._addClass(t.$element,"ui-selected"),t.selected=!0):(n._removeClass(t.$element,"ui-selecting"),t.selecting=!1,t.startselected&&(n._addClass(t.$element,"ui-unselecting"),t.unselecting=!0),n._trigger("unselecting",s,{unselecting:t.element}))),t.selected&&(s.metaKey||s.ctrlKey||t.startselected||(n._removeClass(t.$element,"ui-selected"),t.selected=!1,n._addClass(t.$element,"ui-unselecting"),t.unselecting=!0,n._trigger("unselecting",s,{unselecting:t.element})))))}),!1}},_mouseStop:function(e){var i=this;return this.dragged=!1,V(".ui-unselecting",this.element[0]).each(function(){var t=V.data(this,"selectable-item");i._removeClass(t.$element,"ui-unselecting"),t.unselecting=!1,t.startselected=!1,i._trigger("unselected",e,{unselected:t.element})}),V(".ui-selecting",this.element[0]).each(function(){var t=V.data(this,"selectable-item");i._removeClass(t.$element,"ui-selecting")._addClass(t.$element,"ui-selected"),t.selecting=!1,t.selected=!0,t.startselected=!0,i._trigger("selected",e,{selected:t.element})}),this._trigger("stop",e),this.helper.remove(),!1}}),V.widget("ui.sortable",V.ui.mouse,{version:"1.13.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_isOverAxis:function(t,e,i){return e<=t&&t<e+i},_isFloating:function(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))},_create:function(){this.containerCache={},this._addClass("ui-sortable"),this.refresh(),this.offset=this.element.offset(),this._mouseInit(),this._setHandleClassName(),this.ready=!0},_setOption:function(t,e){this._super(t,e),"handle"===t&&this._setHandleClassName()},_setHandleClassName:function(){var t=this;this._removeClass(this.element.find(".ui-sortable-handle"),"ui-sortable-handle"),V.each(this.items,function(){t._addClass(this.instance.options.handle?this.item.find(this.instance.options.handle):this.item,"ui-sortable-handle")})},_destroy:function(){this._mouseDestroy();for(var t=this.items.length-1;0<=t;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_mouseCapture:function(t,e){var i=null,s=!1,n=this;return!this.reverting&&(!this.options.disabled&&"static"!==this.options.type&&(this._refreshItems(t),V(t.target).parents().each(function(){if(V.data(this,n.widgetName+"-item")===n)return i=V(this),!1}),!!(i=V.data(t.target,n.widgetName+"-item")===n?V(t.target):i)&&(!(this.options.handle&&!e&&(V(this.options.handle,i).find("*").addBack().each(function(){this===t.target&&(s=!0)}),!s))&&(this.currentItem=i,this._removeCurrentsFromItems(),!0))))},_mouseStart:function(t,e,i){var s,n,o=this.options;if((this.currentContainer=this).refreshPositions(),this.appendTo=V("parent"!==o.appendTo?o.appendTo:this.currentItem.parent()),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},V.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),this.scrollParent=this.placeholder.scrollParent(),V.extend(this.offset,{parent:this._getParentOffset()}),o.containment&&this._setContainment(),o.cursor&&"auto"!==o.cursor&&(n=this.document.find("body"),this.storedCursor=n.css("cursor"),n.css("cursor",o.cursor),this.storedStylesheet=V("<style>*{ cursor: "+o.cursor+" !important; }</style>").appendTo(n)),o.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",o.zIndex)),o.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",o.opacity)),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!i)for(s=this.containers.length-1;0<=s;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return V.ui.ddmanager&&(V.ui.ddmanager.current=this),V.ui.ddmanager&&!o.dropBehaviour&&V.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this._addClass(this.helper,"ui-sortable-helper"),this.helper.parent().is(this.appendTo)||(this.helper.detach().appendTo(this.appendTo),this.offset.parent=this._getParentOffset()),this.position=this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,this.lastPositionAbs=this.positionAbs=this._convertPositionTo("absolute"),this._mouseDrag(t),!0},_scroll:function(t){var e=this.options,i=!1;return this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<e.scrollSensitivity?this.scrollParent[0].scrollTop=i=this.scrollParent[0].scrollTop+e.scrollSpeed:t.pageY-this.overflowOffset.top<e.scrollSensitivity&&(this.scrollParent[0].scrollTop=i=this.scrollParent[0].scrollTop-e.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<e.scrollSensitivity?this.scrollParent[0].scrollLeft=i=this.scrollParent[0].scrollLeft+e.scrollSpeed:t.pageX-this.overflowOffset.left<e.scrollSensitivity&&(this.scrollParent[0].scrollLeft=i=this.scrollParent[0].scrollLeft-e.scrollSpeed)):(t.pageY-this.document.scrollTop()<e.scrollSensitivity?i=this.document.scrollTop(this.document.scrollTop()-e.scrollSpeed):this.window.height()-(t.pageY-this.document.scrollTop())<e.scrollSensitivity&&(i=this.document.scrollTop(this.document.scrollTop()+e.scrollSpeed)),t.pageX-this.document.scrollLeft()<e.scrollSensitivity?i=this.document.scrollLeft(this.document.scrollLeft()-e.scrollSpeed):this.window.width()-(t.pageX-this.document.scrollLeft())<e.scrollSensitivity&&(i=this.document.scrollLeft(this.document.scrollLeft()+e.scrollSpeed))),i},_mouseDrag:function(t){var e,i,s,n,o=this.options;for(this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),o.scroll&&!1!==this._scroll(t)&&(this._refreshItemPositions(!0),V.ui.ddmanager&&!o.dropBehaviour&&V.ui.ddmanager.prepareOffsets(this,t)),this.dragDirection={vertical:this._getDragVerticalDirection(),horizontal:this._getDragHorizontalDirection()},e=this.items.length-1;0<=e;e--)if(s=(i=this.items[e]).item[0],(n=this._intersectsWithPointer(i))&&i.instance===this.currentContainer&&!(s===this.currentItem[0]||this.placeholder[1===n?"next":"prev"]()[0]===s||V.contains(this.placeholder[0],s)||"semi-dynamic"===this.options.type&&V.contains(this.element[0],s))){if(this.direction=1===n?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(i))break;this._rearrange(t,i),this._trigger("change",t,this._uiHash());break}return this._contactContainers(t),V.ui.ddmanager&&V.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,e){var i,s,n,o;if(t)return V.ui.ddmanager&&!this.options.dropBehaviour&&V.ui.ddmanager.drop(this,t),this.options.revert?(s=(i=this).placeholder.offset(),o={},(n=this.options.axis)&&"x"!==n||(o.left=s.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollLeft)),n&&"y"!==n||(o.top=s.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===this.document[0].body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,V(this.helper).animate(o,parseInt(this.options.revert,10)||500,function(){i._clear(t)})):this._clear(t,e),!1},cancel:function(){if(this.dragging){this._mouseUp(new V.Event("mouseup",{target:null})),"original"===this.options.helper?(this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")):this.currentItem.show();for(var t=this.containers.length-1;0<=t;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),V.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?V(this.domPosition.prev).after(this.currentItem):V(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var t=this._getItemsAsjQuery(e&&e.connected),i=[];return e=e||{},V(t).each(function(){var t=(V(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);t&&i.push((e.key||t[1]+"[]")+"="+(e.key&&e.expression?t[1]:t[2]))}),!i.length&&e.key&&i.push(e.key+"="),i.join("&")},toArray:function(t){var e=this._getItemsAsjQuery(t&&t.connected),i=[];return t=t||{},e.each(function(){i.push(V(t.item||this).attr(t.attribute||"id")||"")}),i},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,o=t.left,a=o+t.width,r=t.top,l=r+t.height,h=this.offset.click.top,c=this.offset.click.left,h="x"===this.options.axis||r<s+h&&s+h<l,c="y"===this.options.axis||o<e+c&&e+c<a;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?h&&c:o<e+this.helperProportions.width/2&&i-this.helperProportions.width/2<a&&r<s+this.helperProportions.height/2&&n-this.helperProportions.height/2<l},_intersectsWithPointer:function(t){var e="x"===this.options.axis||this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),t="y"===this.options.axis||this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width);return!(!e||!t)&&(e=this.dragDirection.vertical,t=this.dragDirection.horizontal,this.floating?"right"===t||"down"===e?2:1:e&&("down"===e?2:1))},_intersectsWithSides:function(t){var e=this._isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),i=this._isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),s=this.dragDirection.vertical,t=this.dragDirection.horizontal;return this.floating&&t?"right"===t&&i||"left"===t&&!i:s&&("down"===s&&e||"up"===s&&!e)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!=t&&(0<t?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!=t&&(0<t?"right":"left")},refresh:function(t){return this._refreshItems(t),this._setHandleClassName(),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(t){var e,i,s,n,o=[],a=[],r=this._connectWith();if(r&&t)for(e=r.length-1;0<=e;e--)for(i=(s=V(r[e],this.document[0])).length-1;0<=i;i--)(n=V.data(s[i],this.widgetFullName))&&n!==this&&!n.options.disabled&&a.push(["function"==typeof n.options.items?n.options.items.call(n.element):V(n.options.items,n.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),n]);function l(){o.push(this)}for(a.push(["function"==typeof this.options.items?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):V(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),e=a.length-1;0<=e;e--)a[e][0].each(l);return V(o)},_removeCurrentsFromItems:function(){var i=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=V.grep(this.items,function(t){for(var e=0;e<i.length;e++)if(i[e]===t.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var e,i,s,n,o,a,r,l,h=this.items,c=[["function"==typeof this.options.items?this.options.items.call(this.element[0],t,{item:this.currentItem}):V(this.options.items,this.element),this]],u=this._connectWith();if(u&&this.ready)for(e=u.length-1;0<=e;e--)for(i=(s=V(u[e],this.document[0])).length-1;0<=i;i--)(n=V.data(s[i],this.widgetFullName))&&n!==this&&!n.options.disabled&&(c.push(["function"==typeof n.options.items?n.options.items.call(n.element[0],t,{item:this.currentItem}):V(n.options.items,n.element),n]),this.containers.push(n));for(e=c.length-1;0<=e;e--)for(o=c[e][1],l=(a=c[e][i=0]).length;i<l;i++)(r=V(a[i])).data(this.widgetName+"-item",o),h.push({item:r,instance:o,width:0,height:0,left:0,top:0})},_refreshItemPositions:function(t){for(var e,i,s=this.items.length-1;0<=s;s--)e=this.items[s],this.currentContainer&&e.instance!==this.currentContainer&&e.item[0]!==this.currentItem[0]||(i=this.options.toleranceElement?V(this.options.toleranceElement,e.item):e.item,t||(e.width=i.outerWidth(),e.height=i.outerHeight()),i=i.offset(),e.left=i.left,e.top=i.top)},refreshPositions:function(t){var e,i;if(this.floating=!!this.items.length&&("x"===this.options.axis||this._isFloating(this.items[0].item)),this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset()),this._refreshItemPositions(t),this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(e=this.containers.length-1;0<=e;e--)i=this.containers[e].element.offset(),this.containers[e].containerCache.left=i.left,this.containers[e].containerCache.top=i.top,this.containers[e].containerCache.width=this.containers[e].element.outerWidth(),this.containers[e].containerCache.height=this.containers[e].element.outerHeight();return this},_createPlaceholder:function(i){var s,n,o=(i=i||this).options;o.placeholder&&o.placeholder.constructor!==String||(s=o.placeholder,n=i.currentItem[0].nodeName.toLowerCase(),o.placeholder={element:function(){var t=V("<"+n+">",i.document[0]);return i._addClass(t,"ui-sortable-placeholder",s||i.currentItem[0].className)._removeClass(t,"ui-sortable-helper"),"tbody"===n?i._createTrPlaceholder(i.currentItem.find("tr").eq(0),V("<tr>",i.document[0]).appendTo(t)):"tr"===n?i._createTrPlaceholder(i.currentItem,t):"img"===n&&t.attr("src",i.currentItem.attr("src")),s||t.css("visibility","hidden"),t},update:function(t,e){s&&!o.forcePlaceholderSize||(e.height()&&(!o.forcePlaceholderSize||"tbody"!==n&&"tr"!==n)||e.height(i.currentItem.innerHeight()-parseInt(i.currentItem.css("paddingTop")||0,10)-parseInt(i.currentItem.css("paddingBottom")||0,10)),e.width()||e.width(i.currentItem.innerWidth()-parseInt(i.currentItem.css("paddingLeft")||0,10)-parseInt(i.currentItem.css("paddingRight")||0,10)))}}),i.placeholder=V(o.placeholder.element.call(i.element,i.currentItem)),i.currentItem.after(i.placeholder),o.placeholder.update(i,i.placeholder)},_createTrPlaceholder:function(t,e){var i=this;t.children().each(function(){V("<td>&#160;</td>",i.document[0]).attr("colspan",V(this).attr("colspan")||1).appendTo(e)})},_contactContainers:function(t){for(var e,i,s,n,o,a,r,l,h,c=null,u=null,d=this.containers.length-1;0<=d;d--)V.contains(this.currentItem[0],this.containers[d].element[0])||(this._intersectsWith(this.containers[d].containerCache)?c&&V.contains(this.containers[d].element[0],c.element[0])||(c=this.containers[d],u=d):this.containers[d].containerCache.over&&(this.containers[d]._trigger("out",t,this._uiHash(this)),this.containers[d].containerCache.over=0));if(c)if(1===this.containers.length)this.containers[u].containerCache.over||(this.containers[u]._trigger("over",t,this._uiHash(this)),this.containers[u].containerCache.over=1);else{for(i=1e4,s=null,n=(l=c.floating||this._isFloating(this.currentItem))?"left":"top",o=l?"width":"height",h=l?"pageX":"pageY",e=this.items.length-1;0<=e;e--)V.contains(this.containers[u].element[0],this.items[e].item[0])&&this.items[e].item[0]!==this.currentItem[0]&&(a=this.items[e].item.offset()[n],r=!1,t[h]-a>this.items[e][o]/2&&(r=!0),Math.abs(t[h]-a)<i&&(i=Math.abs(t[h]-a),s=this.items[e],this.direction=r?"up":"down"));(s||this.options.dropOnEmpty)&&(this.currentContainer!==this.containers[u]?(s?this._rearrange(t,s,null,!0):this._rearrange(t,null,this.containers[u].element,!0),this._trigger("change",t,this._uiHash()),this.containers[u]._trigger("change",t,this._uiHash(this)),this.currentContainer=this.containers[u],this.options.placeholder.update(this.currentContainer,this.placeholder),this.scrollParent=this.placeholder.scrollParent(),this.scrollParent[0]!==this.document[0]&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this.containers[u]._trigger("over",t,this._uiHash(this)),this.containers[u].containerCache.over=1):this.currentContainer.containerCache.over||(this.containers[u]._trigger("over",t,this._uiHash()),this.currentContainer.containerCache.over=1))}},_createHelper:function(t){var e=this.options,t="function"==typeof e.helper?V(e.helper.apply(this.element[0],[t,this.currentItem])):"clone"===e.helper?this.currentItem.clone():this.currentItem;return t.parents("body").length||this.appendTo[0].appendChild(t[0]),t[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),t[0].style.width&&!e.forceHelperSize||t.width(this.currentItem.width()),t[0].style.height&&!e.forceHelperSize||t.height(this.currentItem.height()),t},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),"left"in(t=Array.isArray(t)?{left:+t[0],top:+t[1]||0}:t)&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==this.document[0]&&V.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),{top:(t=this.offsetParent[0]===this.document[0].body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&V.ui.ie?{top:0,left:0}:t).top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"!==this.cssPosition)return{top:0,left:0};var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,e,i=this.options;"parent"===i.containment&&(i.containment=this.helper[0].parentNode),"document"!==i.containment&&"window"!==i.containment||(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,"document"===i.containment?this.document.width():this.window.width()-this.helperProportions.width-this.margins.left,("document"===i.containment?this.document.height()||document.body.parentNode.scrollHeight:this.window.height()||this.document[0].body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(i.containment)||(t=V(i.containment)[0],e=V(i.containment).offset(),i="hidden"!==V(t).css("overflow"),this.containment=[e.left+(parseInt(V(t).css("borderLeftWidth"),10)||0)+(parseInt(V(t).css("paddingLeft"),10)||0)-this.margins.left,e.top+(parseInt(V(t).css("borderTopWidth"),10)||0)+(parseInt(V(t).css("paddingTop"),10)||0)-this.margins.top,e.left+(i?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(V(t).css("borderLeftWidth"),10)||0)-(parseInt(V(t).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,e.top+(i?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(V(t).css("borderTopWidth"),10)||0)-(parseInt(V(t).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,e){e=e||this.position;var i="absolute"===t?1:-1,s="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&V.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,t=/(html|body)/i.test(s[0].tagName);return{top:e.top+this.offset.relative.top*i+this.offset.parent.top*i-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():t?0:s.scrollTop())*i,left:e.left+this.offset.relative.left*i+this.offset.parent.left*i-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():t?0:s.scrollLeft())*i}},_generatePosition:function(t){var e=this.options,i=t.pageX,s=t.pageY,n="absolute"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&V.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(n[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==this.document[0]&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(i=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(s=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(i=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(s=this.containment[3]+this.offset.click.top)),e.grid&&(t=this.originalPageY+Math.round((s-this.originalPageY)/e.grid[1])*e.grid[1],s=!this.containment||t-this.offset.click.top>=this.containment[1]&&t-this.offset.click.top<=this.containment[3]?t:t-this.offset.click.top>=this.containment[1]?t-e.grid[1]:t+e.grid[1],t=this.originalPageX+Math.round((i-this.originalPageX)/e.grid[0])*e.grid[0],i=!this.containment||t-this.offset.click.left>=this.containment[0]&&t-this.offset.click.left<=this.containment[2]?t:t-this.offset.click.left>=this.containment[0]?t-e.grid[0]:t+e.grid[0])),{top:s-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():o?0:n.scrollTop()),left:i-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():o?0:n.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){this.reverting=!1;var i,s=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)"auto"!==this._storedCSS[i]&&"static"!==this._storedCSS[i]||(this._storedCSS[i]="");this.currentItem.css(this._storedCSS),this._removeClass(this.currentItem,"ui-sortable-helper")}else this.currentItem.show();function n(e,i,s){return function(t){s._trigger(e,t,i._uiHash(i))}}for(this.fromOutside&&!e&&s.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||s.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(s.push(function(t){this._trigger("remove",t,this._uiHash())}),s.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),s.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;0<=i;i--)e||s.push(n("deactivate",this,this.containers[i])),this.containers[i].containerCache.over&&(s.push(n("out",this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.cancelHelperRemoval||(this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null),!e){for(i=0;i<s.length;i++)s[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!this.cancelHelperRemoval},_trigger:function(){!1===V.Widget.prototype._trigger.apply(this,arguments)&&this.cancel()},_uiHash:function(t){var e=t||this;return{helper:e.helper,placeholder:e.placeholder||V([]),position:e.position,originalPosition:e.originalPosition,offset:e.positionAbs,item:e.currentItem,sender:t?t.element:null}}}),V.widget("ui.accordion",{version:"1.13.2",options:{active:0,animate:{},classes:{"ui-accordion-header":"ui-corner-top","ui-accordion-header-collapsed":"ui-corner-all","ui-accordion-content":"ui-corner-bottom"},collapsible:!1,event:"click",header:function(t){return t.find("> li > :first-child").add(t.find("> :not(li)").even())},heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},hideProps:{borderTopWidth:"hide",borderBottomWidth:"hide",paddingTop:"hide",paddingBottom:"hide",height:"hide"},showProps:{borderTopWidth:"show",borderBottomWidth:"show",paddingTop:"show",paddingBottom:"show",height:"show"},_create:function(){var t=this.options;this.prevShow=this.prevHide=V(),this._addClass("ui-accordion","ui-widget ui-helper-reset"),this.element.attr("role","tablist"),t.collapsible||!1!==t.active&&null!=t.active||(t.active=0),this._processPanels(),t.active<0&&(t.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():V()}},_createIcons:function(){var t,e=this.options.icons;e&&(t=V("<span>"),this._addClass(t,"ui-accordion-header-icon","ui-icon "+e.header),t.prependTo(this.headers),t=this.active.children(".ui-accordion-header-icon"),this._removeClass(t,e.header)._addClass(t,null,e.activeHeader)._addClass(this.headers,"ui-accordion-icons"))},_destroyIcons:function(){this._removeClass(this.headers,"ui-accordion-icons"),this.headers.children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeAttr("role"),this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId(),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role aria-hidden aria-labelledby").removeUniqueId(),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){"active"!==t?("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||!1!==this.options.active||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons())):this._activate(e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t),this._toggleClass(this.headers.add(this.headers.next()),null,"ui-state-disabled",!!t)},_keydown:function(t){if(!t.altKey&&!t.ctrlKey){var e=V.ui.keyCode,i=this.headers.length,s=this.headers.index(t.target),n=!1;switch(t.keyCode){case e.RIGHT:case e.DOWN:n=this.headers[(s+1)%i];break;case e.LEFT:case e.UP:n=this.headers[(s-1+i)%i];break;case e.SPACE:case e.ENTER:this._eventHandler(t);break;case e.HOME:n=this.headers[0];break;case e.END:n=this.headers[i-1]}n&&(V(t.target).attr("tabIndex",-1),V(n).attr("tabIndex",0),V(n).trigger("focus"),t.preventDefault())}},_panelKeyDown:function(t){t.keyCode===V.ui.keyCode.UP&&t.ctrlKey&&V(t.currentTarget).prev().trigger("focus")},refresh:function(){var t=this.options;this._processPanels(),!1===t.active&&!0===t.collapsible||!this.headers.length?(t.active=!1,this.active=V()):!1===t.active?this._activate(0):this.active.length&&!V.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(t.active=!1,this.active=V()):this._activate(Math.max(0,t.active-1)):t.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){var t=this.headers,e=this.panels;"function"==typeof this.options.header?this.headers=this.options.header(this.element):this.headers=this.element.find(this.options.header),this._addClass(this.headers,"ui-accordion-header ui-accordion-header-collapsed","ui-state-default"),this.panels=this.headers.next().filter(":not(.ui-accordion-content-active)").hide(),this._addClass(this.panels,"ui-accordion-content","ui-helper-reset ui-widget-content"),e&&(this._off(t.not(this.headers)),this._off(e.not(this.panels)))},_refresh:function(){var i,t=this.options,e=t.heightStyle,s=this.element.parent();this.active=this._findActive(t.active),this._addClass(this.active,"ui-accordion-header-active","ui-state-active")._removeClass(this.active,"ui-accordion-header-collapsed"),this._addClass(this.active.next(),"ui-accordion-content-active"),this.active.next().show(),this.headers.attr("role","tab").each(function(){var t=V(this),e=t.uniqueId().attr("id"),i=t.next(),s=i.uniqueId().attr("id");t.attr("aria-controls",s),i.attr("aria-labelledby",e)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}).next().attr({"aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}).next().attr({"aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(t.event),"fill"===e?(i=s.height(),this.element.siblings(":visible").each(function(){var t=V(this),e=t.css("position");"absolute"!==e&&"fixed"!==e&&(i-=t.outerHeight(!0))}),this.headers.each(function(){i-=V(this).outerHeight(!0)}),this.headers.next().each(function(){V(this).height(Math.max(0,i-V(this).innerHeight()+V(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.headers.next().each(function(){var t=V(this).is(":visible");t||V(this).show(),i=Math.max(i,V(this).css("height","").height()),t||V(this).hide()}).height(i))},_activate:function(t){t=this._findActive(t)[0];t!==this.active[0]&&(t=t||this.active[0],this._eventHandler({target:t,currentTarget:t,preventDefault:V.noop}))},_findActive:function(t){return"number"==typeof t?this.headers.eq(t):V()},_setupEvents:function(t){var i={keydown:"_keydown"};t&&V.each(t.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(t){var e=this.options,i=this.active,s=V(t.currentTarget),n=s[0]===i[0],o=n&&e.collapsible,a=o?V():s.next(),r=i.next(),a={oldHeader:i,oldPanel:r,newHeader:o?V():s,newPanel:a};t.preventDefault(),n&&!e.collapsible||!1===this._trigger("beforeActivate",t,a)||(e.active=!o&&this.headers.index(s),this.active=n?V():s,this._toggle(a),this._removeClass(i,"ui-accordion-header-active","ui-state-active"),e.icons&&(i=i.children(".ui-accordion-header-icon"),this._removeClass(i,null,e.icons.activeHeader)._addClass(i,null,e.icons.header)),n||(this._removeClass(s,"ui-accordion-header-collapsed")._addClass(s,"ui-accordion-header-active","ui-state-active"),e.icons&&(n=s.children(".ui-accordion-header-icon"),this._removeClass(n,null,e.icons.header)._addClass(n,null,e.icons.activeHeader)),this._addClass(s.next(),"ui-accordion-content-active")))},_toggle:function(t){var e=t.newPanel,i=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=e,this.prevHide=i,this.options.animate?this._animate(e,i,t):(i.hide(),e.show(),this._toggleComplete(t)),i.attr({"aria-hidden":"true"}),i.prev().attr({"aria-selected":"false","aria-expanded":"false"}),e.length&&i.length?i.prev().attr({tabIndex:-1,"aria-expanded":"false"}):e.length&&this.headers.filter(function(){return 0===parseInt(V(this).attr("tabIndex"),10)}).attr("tabIndex",-1),e.attr("aria-hidden","false").prev().attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_animate:function(t,i,e){var s,n,o,a=this,r=0,l=t.css("box-sizing"),h=t.length&&(!i.length||t.index()<i.index()),c=this.options.animate||{},u=h&&c.down||c,h=function(){a._toggleComplete(e)};return n=(n="string"==typeof u?u:n)||u.easing||c.easing,o=(o="number"==typeof u?u:o)||u.duration||c.duration,i.length?t.length?(s=t.show().outerHeight(),i.animate(this.hideProps,{duration:o,easing:n,step:function(t,e){e.now=Math.round(t)}}),void t.hide().animate(this.showProps,{duration:o,easing:n,complete:h,step:function(t,e){e.now=Math.round(t),"height"!==e.prop?"content-box"===l&&(r+=e.now):"content"!==a.options.heightStyle&&(e.now=Math.round(s-i.outerHeight()-r),r=0)}})):i.animate(this.hideProps,o,n,h):t.animate(this.showProps,o,n,h)},_toggleComplete:function(t){var e=t.oldPanel,i=e.prev();this._removeClass(e,"ui-accordion-content-active"),this._removeClass(i,"ui-accordion-header-active")._addClass(i,"ui-accordion-header-collapsed"),e.length&&(e.parent()[0].className=e.parent()[0].className),this._trigger("activate",null,t)}}),V.widget("ui.menu",{version:"1.13.2",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-caret-1-e"},items:"> *",menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.lastMousePosition={x:null,y:null},this.element.uniqueId().attr({role:this.options.role,tabIndex:0}),this._addClass("ui-menu","ui-widget ui-widget-content"),this._on({"mousedown .ui-menu-item":function(t){t.preventDefault(),this._activateItem(t)},"click .ui-menu-item":function(t){var e=V(t.target),i=V(V.ui.safeActiveElement(this.document[0]));!this.mouseHandled&&e.not(".ui-state-disabled").length&&(this.select(t),t.isPropagationStopped()||(this.mouseHandled=!0),e.has(".ui-menu").length?this.expand(t):!this.element.is(":focus")&&i.closest(".ui-menu").length&&(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":"_activateItem","mousemove .ui-menu-item":"_activateItem",mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this._menuItems().first();e||this.focus(t,i)},blur:function(t){this._delay(function(){V.contains(this.element[0],V.ui.safeActiveElement(this.document[0]))||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){this._closeOnDocumentClick(t)&&this.collapseAll(t,!0),this.mouseHandled=!1}})},_activateItem:function(t){var e,i;this.previousFilter||t.clientX===this.lastMousePosition.x&&t.clientY===this.lastMousePosition.y||(this.lastMousePosition={x:t.clientX,y:t.clientY},e=V(t.target).closest(".ui-menu-item"),i=V(t.currentTarget),e[0]===i[0]&&(i.is(".ui-state-active")||(this._removeClass(i.siblings().children(".ui-state-active"),null,"ui-state-active"),this.focus(t,i))))},_destroy:function(){var t=this.element.find(".ui-menu-item").removeAttr("role aria-disabled").children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled tabIndex").removeUniqueId().show(),t.children().each(function(){var t=V(this);t.data("ui-menu-submenu-caret")&&t.remove()})},_keydown:function(t){var e,i,s,n=!0;switch(t.keyCode){case V.ui.keyCode.PAGE_UP:this.previousPage(t);break;case V.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case V.ui.keyCode.HOME:this._move("first","first",t);break;case V.ui.keyCode.END:this._move("last","last",t);break;case V.ui.keyCode.UP:this.previous(t);break;case V.ui.keyCode.DOWN:this.next(t);break;case V.ui.keyCode.LEFT:this.collapse(t);break;case V.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case V.ui.keyCode.ENTER:case V.ui.keyCode.SPACE:this._activate(t);break;case V.ui.keyCode.ESCAPE:this.collapse(t);break;default:e=this.previousFilter||"",s=n=!1,i=96<=t.keyCode&&t.keyCode<=105?(t.keyCode-96).toString():String.fromCharCode(t.keyCode),clearTimeout(this.filterTimer),i===e?s=!0:i=e+i,e=this._filterMenuItems(i),(e=s&&-1!==e.index(this.active.next())?this.active.nextAll(".ui-menu-item"):e).length||(i=String.fromCharCode(t.keyCode),e=this._filterMenuItems(i)),e.length?(this.focus(t,e),this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter}n&&t.preventDefault()},_activate:function(t){this.active&&!this.active.is(".ui-state-disabled")&&(this.active.children("[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var t,e,s=this,n=this.options.icons.submenu,i=this.element.find(this.options.menus);this._toggleClass("ui-menu-icons",null,!!this.element.find(".ui-icon").length),e=i.filter(":not(.ui-menu)").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=V(this),e=t.prev(),i=V("<span>").data("ui-menu-submenu-caret",!0);s._addClass(i,"ui-menu-icon","ui-icon "+n),e.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",e.attr("id"))}),this._addClass(e,"ui-menu","ui-widget ui-widget-content ui-front"),(t=i.add(this.element).find(this.options.items)).not(".ui-menu-item").each(function(){var t=V(this);s._isDivider(t)&&s._addClass(t,"ui-menu-divider","ui-widget-content")}),i=(e=t.not(".ui-menu-item, .ui-menu-divider")).children().not(".ui-menu").uniqueId().attr({tabIndex:-1,role:this._itemRole()}),this._addClass(e,"ui-menu-item")._addClass(i,"ui-menu-item-wrapper"),t.filter(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!V.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){var i;"icons"===t&&(i=this.element.find(".ui-menu-icon"),this._removeClass(i,null,this.options.icons.submenu)._addClass(i,null,e.submenu)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",String(t)),this._toggleClass(null,"ui-state-disabled",!!t)},focus:function(t,e){var i;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),i=this.active.children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),this.options.role&&this.element.attr("aria-activedescendant",i.attr("id")),i=this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper"),this._addClass(i,null,"ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),(i=e.children(".ui-menu")).length&&t&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(t){var e,i,s;this._hasScroll()&&(i=parseFloat(V.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(V.css(this.activeMenu[0],"paddingTop"))||0,e=t.offset().top-this.activeMenu.offset().top-i-s,i=this.activeMenu.scrollTop(),s=this.activeMenu.height(),t=t.outerHeight(),e<0?this.activeMenu.scrollTop(i+e):s<e+t&&this.activeMenu.scrollTop(i+e-s+t))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this._removeClass(this.active.children(".ui-menu-item-wrapper"),null,"ui-state-active"),this._trigger("blur",t,{item:this.active}),this.active=null)},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(t){var e=V.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(e)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var t=i?this.element:V(e&&e.target).closest(this.element.find(".ui-menu"));t.length||(t=this.element),this._close(t),this.blur(e),this._removeClass(t.find(".ui-state-active"),null,"ui-state-active"),this.activeMenu=t},i?0:this.delay)},_close:function(t){(t=t||(this.active?this.active.parent():this.element)).find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false")},_closeOnDocumentClick:function(t){return!V(t.target).closest(".ui-menu").length},_isDivider:function(t){return!/[^\-\u2014\u2013\s]/.test(t.text())},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this._menuItems(this.active.children(".ui-menu")).first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_menuItems:function(t){return(t||this.element).find(this.options.items).filter(".ui-menu-item")},_move:function(t,e,i){var s;(s=this.active?"first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").last():this.active[t+"All"](".ui-menu-item").first():s)&&s.length&&this.active||(s=this._menuItems(this.activeMenu)[e]()),this.focus(i,s)},nextPage:function(t){var e,i,s;this.active?this.isLastItem()||(this._hasScroll()?(i=this.active.offset().top,s=this.element.innerHeight(),0===V.fn.jquery.indexOf("3.2.")&&(s+=this.element[0].offsetHeight-this.element.outerHeight()),this.active.nextAll(".ui-menu-item").each(function(){return(e=V(this)).offset().top-i-s<0}),this.focus(t,e)):this.focus(t,this._menuItems(this.activeMenu)[this.active?"last":"first"]())):this.next(t)},previousPage:function(t){var e,i,s;this.active?this.isFirstItem()||(this._hasScroll()?(i=this.active.offset().top,s=this.element.innerHeight(),0===V.fn.jquery.indexOf("3.2.")&&(s+=this.element[0].offsetHeight-this.element.outerHeight()),this.active.prevAll(".ui-menu-item").each(function(){return 0<(e=V(this)).offset().top-i+s}),this.focus(t,e)):this.focus(t,this._menuItems(this.activeMenu).first())):this.next(t)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||V(t.target).closest(".ui-menu-item");var e={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,e)},_filterMenuItems:function(t){var t=t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&"),e=new RegExp("^"+t,"i");return this.activeMenu.find(this.options.items).filter(".ui-menu-item").filter(function(){return e.test(String.prototype.trim.call(V(this).children(".ui-menu-item-wrapper").text()))})}});V.widget("ui.autocomplete",{version:"1.13.2",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},requestIndex:0,pending:0,liveRegionTimer:null,_create:function(){var i,s,n,t=this.element[0].nodeName.toLowerCase(),e="textarea"===t,t="input"===t;this.isMultiLine=e||!t&&this._isContentEditable(this.element),this.valueMethod=this.element[e||t?"val":"text"],this.isNewMenu=!0,this._addClass("ui-autocomplete-input"),this.element.attr("autocomplete","off"),this._on(this.element,{keydown:function(t){if(this.element.prop("readOnly"))s=n=i=!0;else{s=n=i=!1;var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:i=!0,this._move("previousPage",t);break;case e.PAGE_DOWN:i=!0,this._move("nextPage",t);break;case e.UP:i=!0,this._keyEvent("previous",t);break;case e.DOWN:i=!0,this._keyEvent("next",t);break;case e.ENTER:this.menu.active&&(i=!0,t.preventDefault(),this.menu.select(t));break;case e.TAB:this.menu.active&&this.menu.select(t);break;case e.ESCAPE:this.menu.element.is(":visible")&&(this.isMultiLine||this._value(this.term),this.close(t),t.preventDefault());break;default:s=!0,this._searchTimeout(t)}}},keypress:function(t){if(i)return i=!1,void(this.isMultiLine&&!this.menu.element.is(":visible")||t.preventDefault());if(!s){var e=V.ui.keyCode;switch(t.keyCode){case e.PAGE_UP:this._move("previousPage",t);break;case e.PAGE_DOWN:this._move("nextPage",t);break;case e.UP:this._keyEvent("previous",t);break;case e.DOWN:this._keyEvent("next",t)}}},input:function(t){if(n)return n=!1,void t.preventDefault();this._searchTimeout(t)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){clearTimeout(this.searching),this.close(t),this._change(t)}}),this._initSource(),this.menu=V("<ul>").appendTo(this._appendTo()).menu({role:null}).hide().attr({unselectable:"on"}).menu("instance"),this._addClass(this.menu.element,"ui-autocomplete","ui-front"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault()},menufocus:function(t,e){var i,s;if(this.isNewMenu&&(this.isNewMenu=!1,t.originalEvent&&/^mouse/.test(t.originalEvent.type)))return this.menu.blur(),void this.document.one("mousemove",function(){V(t.target).trigger(t.originalEvent)});s=e.item.data("ui-autocomplete-item"),!1!==this._trigger("focus",t,{item:s})&&t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(s.value),(i=e.item.attr("aria-label")||s.value)&&String.prototype.trim.call(i).length&&(clearTimeout(this.liveRegionTimer),this.liveRegionTimer=this._delay(function(){this.liveRegion.html(V("<div>").text(i))},100))},menuselect:function(t,e){var i=e.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==V.ui.safeActiveElement(this.document[0])&&(this.element.trigger("focus"),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",t,{item:i})&&this._value(i.value),this.term=this._value(),this.close(t),this.selectedItem=i}}),this.liveRegion=V("<div>",{role:"status","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_isEventTargetInWidget:function(t){var e=this.menu.element[0];return t.target===this.element[0]||t.target===e||V.contains(e,t.target)},_closeOnClickOutside:function(t){this._isEventTargetInWidget(t)||this.close()},_appendTo:function(){var t=this.options.appendTo;return t=!(t=!(t=t&&(t.jquery||t.nodeType?V(t):this.document.find(t).eq(0)))||!t[0]?this.element.closest(".ui-front, dialog"):t).length?this.document[0].body:t},_initSource:function(){var i,s,n=this;Array.isArray(this.options.source)?(i=this.options.source,this.source=function(t,e){e(V.ui.autocomplete.filter(i,t.term))}):"string"==typeof this.options.source?(s=this.options.source,this.source=function(t,e){n.xhr&&n.xhr.abort(),n.xhr=V.ajax({url:s,data:t,dataType:"json",success:function(t){e(t)},error:function(){e([])}})}):this.source=this.options.source},_searchTimeout:function(s){clearTimeout(this.searching),this.searching=this._delay(function(){var t=this.term===this._value(),e=this.menu.element.is(":visible"),i=s.altKey||s.ctrlKey||s.metaKey||s.shiftKey;t&&(e||i)||(this.selectedItem=null,this.search(null,s))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length<this.options.minLength?this.close(e):!1!==this._trigger("search",e)?this._search(t):void 0},_search:function(t){this.pending++,this._addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:t},this._response())},_response:function(){var e=++this.requestIndex;return function(t){e===this.requestIndex&&this.__response(t),this.pending--,this.pending||this._removeClass("ui-autocomplete-loading")}.bind(this)},__response:function(t){t=t&&this._normalize(t),this._trigger("response",null,{content:t}),!this.options.disabled&&t&&t.length&&!this.cancelSearch?(this._suggest(t),this._trigger("open")):this._close()},close:function(t){this.cancelSearch=!0,this._close(t)},_close:function(t){this._off(this.document,"mousedown"),this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",t))},_change:function(t){this.previous!==this._value()&&this._trigger("change",t,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:V.map(t,function(t){return"string"==typeof t?{label:t,value:t}:V.extend({},t,{label:t.label||t.value,value:t.value||t.label})})},_suggest:function(t){var e=this.menu.element.empty();this._renderMenu(e,t),this.isNewMenu=!0,this.menu.refresh(),e.show(),this._resizeMenu(),e.position(V.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next(),this._on(this.document,{mousedown:"_closeOnClickOutside"})},_resizeMenu:function(){var t=this.menu.element;t.outerWidth(Math.max(t.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(i,t){var s=this;V.each(t,function(t,e){s._renderItemData(i,e)})},_renderItemData:function(t,e){return this._renderItem(t,e).data("ui-autocomplete-item",e)},_renderItem:function(t,e){return V("<li>").append(V("<div>").text(e.label)).appendTo(t)},_move:function(t,e){if(this.menu.element.is(":visible"))return this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this.isMultiLine||this._value(this.term),void this.menu.blur()):void this.menu[t](e);this.search(null,e)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){this.isMultiLine&&!this.menu.element.is(":visible")||(this._move(t,e),e.preventDefault())},_isContentEditable:function(t){if(!t.length)return!1;var e=t.prop("contentEditable");return"inherit"===e?this._isContentEditable(t.parent()):"true"===e}}),V.extend(V.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,e){var i=new RegExp(V.ui.autocomplete.escapeRegex(e),"i");return V.grep(t,function(t){return i.test(t.label||t.value||t)})}}),V.widget("ui.autocomplete",V.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(1<t?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var e;this._superApply(arguments),this.options.disabled||this.cancelSearch||(e=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,clearTimeout(this.liveRegionTimer),this.liveRegionTimer=this._delay(function(){this.liveRegion.html(V("<div>").text(e))},100))}});V.ui.autocomplete;var m=/ui-corner-([a-z]){2,6}/g;V.widget("ui.controlgroup",{version:"1.13.2",defaultElement:"<div>",options:{direction:"horizontal",disabled:null,onlyVisible:!0,items:{button:"input[type=button], input[type=submit], input[type=reset], button, a",controlgroupLabel:".ui-controlgroup-label",checkboxradio:"input[type='checkbox'], input[type='radio']",selectmenu:"select",spinner:".ui-spinner-input"}},_create:function(){this._enhance()},_enhance:function(){this.element.attr("role","toolbar"),this.refresh()},_destroy:function(){this._callChildMethod("destroy"),this.childWidgets.removeData("ui-controlgroup-data"),this.element.removeAttr("role"),this.options.items.controlgroupLabel&&this.element.find(this.options.items.controlgroupLabel).find(".ui-controlgroup-label-contents").contents().unwrap()},_initWidgets:function(){var o=this,a=[];V.each(this.options.items,function(s,t){var e,n={};if(t)return"controlgroupLabel"===s?((e=o.element.find(t)).each(function(){var t=V(this);t.children(".ui-controlgroup-label-contents").length||t.contents().wrapAll("<span class='ui-controlgroup-label-contents'></span>")}),o._addClass(e,null,"ui-widget ui-widget-content ui-state-default"),void(a=a.concat(e.get()))):void(V.fn[s]&&(n=o["_"+s+"Options"]?o["_"+s+"Options"]("middle"):{classes:{}},o.element.find(t).each(function(){var t=V(this),e=t[s]("instance"),i=V.widget.extend({},n);"button"===s&&t.parent(".ui-spinner").length||((e=e||t[s]()[s]("instance"))&&(i.classes=o._resolveClassesValues(i.classes,e)),t[s](i),i=t[s]("widget"),V.data(i[0],"ui-controlgroup-data",e||t[s]("instance")),a.push(i[0]))})))}),this.childWidgets=V(V.uniqueSort(a)),this._addClass(this.childWidgets,"ui-controlgroup-item")},_callChildMethod:function(e){this.childWidgets.each(function(){var t=V(this).data("ui-controlgroup-data");t&&t[e]&&t[e]()})},_updateCornerClass:function(t,e){e=this._buildSimpleOptions(e,"label").classes.label;this._removeClass(t,null,"ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all"),this._addClass(t,null,e)},_buildSimpleOptions:function(t,e){var i="vertical"===this.options.direction,s={classes:{}};return s.classes[e]={middle:"",first:"ui-corner-"+(i?"top":"left"),last:"ui-corner-"+(i?"bottom":"right"),only:"ui-corner-all"}[t],s},_spinnerOptions:function(t){t=this._buildSimpleOptions(t,"ui-spinner");return t.classes["ui-spinner-up"]="",t.classes["ui-spinner-down"]="",t},_buttonOptions:function(t){return this._buildSimpleOptions(t,"ui-button")},_checkboxradioOptions:function(t){return this._buildSimpleOptions(t,"ui-checkboxradio-label")},_selectmenuOptions:function(t){var e="vertical"===this.options.direction;return{width:e&&"auto",classes:{middle:{"ui-selectmenu-button-open":"","ui-selectmenu-button-closed":""},first:{"ui-selectmenu-button-open":"ui-corner-"+(e?"top":"tl"),"ui-selectmenu-button-closed":"ui-corner-"+(e?"top":"left")},last:{"ui-selectmenu-button-open":e?"":"ui-corner-tr","ui-selectmenu-button-closed":"ui-corner-"+(e?"bottom":"right")},only:{"ui-selectmenu-button-open":"ui-corner-top","ui-selectmenu-button-closed":"ui-corner-all"}}[t]}},_resolveClassesValues:function(i,s){var n={};return V.each(i,function(t){var e=s.options.classes[t]||"",e=String.prototype.trim.call(e.replace(m,""));n[t]=(e+" "+i[t]).replace(/\s+/g," ")}),n},_setOption:function(t,e){"direction"===t&&this._removeClass("ui-controlgroup-"+this.options.direction),this._super(t,e),"disabled"!==t?this.refresh():this._callChildMethod(e?"disable":"enable")},refresh:function(){var n,o=this;this._addClass("ui-controlgroup ui-controlgroup-"+this.options.direction),"horizontal"===this.options.direction&&this._addClass(null,"ui-helper-clearfix"),this._initWidgets(),n=this.childWidgets,(n=this.options.onlyVisible?n.filter(":visible"):n).length&&(V.each(["first","last"],function(t,e){var i,s=n[e]().data("ui-controlgroup-data");s&&o["_"+s.widgetName+"Options"]?((i=o["_"+s.widgetName+"Options"](1===n.length?"only":e)).classes=o._resolveClassesValues(i.classes,s),s.element[s.widgetName](i)):o._updateCornerClass(n[e](),e)}),this._callChildMethod("refresh"))}});V.widget("ui.checkboxradio",[V.ui.formResetMixin,{version:"1.13.2",options:{disabled:null,label:null,icon:!0,classes:{"ui-checkboxradio-label":"ui-corner-all","ui-checkboxradio-icon":"ui-corner-all"}},_getCreateOptions:function(){var t,e=this._super()||{};return this._readType(),t=this.element.labels(),this.label=V(t[t.length-1]),this.label.length||V.error("No label found for checkboxradio widget"),this.originalLabel="",(t=this.label.contents().not(this.element[0])).length&&(this.originalLabel+=t.clone().wrapAll("<div></div>").parent().html()),this.originalLabel&&(e.label=this.originalLabel),null!=(t=this.element[0].disabled)&&(e.disabled=t),e},_create:function(){var t=this.element[0].checked;this._bindFormResetHandler(),null==this.options.disabled&&(this.options.disabled=this.element[0].disabled),this._setOption("disabled",this.options.disabled),this._addClass("ui-checkboxradio","ui-helper-hidden-accessible"),this._addClass(this.label,"ui-checkboxradio-label","ui-button ui-widget"),"radio"===this.type&&this._addClass(this.label,"ui-checkboxradio-radio-label"),this.options.label&&this.options.label!==this.originalLabel?this._updateLabel():this.originalLabel&&(this.options.label=this.originalLabel),this._enhance(),t&&this._addClass(this.label,"ui-checkboxradio-checked","ui-state-active"),this._on({change:"_toggleClasses",focus:function(){this._addClass(this.label,null,"ui-state-focus ui-visual-focus")},blur:function(){this._removeClass(this.label,null,"ui-state-focus ui-visual-focus")}})},_readType:function(){var t=this.element[0].nodeName.toLowerCase();this.type=this.element[0].type,"input"===t&&/radio|checkbox/.test(this.type)||V.error("Can't create checkboxradio on element.nodeName="+t+" and element.type="+this.type)},_enhance:function(){this._updateIcon(this.element[0].checked)},widget:function(){return this.label},_getRadioGroup:function(){var t=this.element[0].name,e="input[name='"+V.escapeSelector(t)+"']";return t?(this.form.length?V(this.form[0].elements).filter(e):V(e).filter(function(){return 0===V(this)._form().length})).not(this.element):V([])},_toggleClasses:function(){var t=this.element[0].checked;this._toggleClass(this.label,"ui-checkboxradio-checked","ui-state-active",t),this.options.icon&&"checkbox"===this.type&&this._toggleClass(this.icon,null,"ui-icon-check ui-state-checked",t)._toggleClass(this.icon,null,"ui-icon-blank",!t),"radio"===this.type&&this._getRadioGroup().each(function(){var t=V(this).checkboxradio("instance");t&&t._removeClass(t.label,"ui-checkboxradio-checked","ui-state-active")})},_destroy:function(){this._unbindFormResetHandler(),this.icon&&(this.icon.remove(),this.iconSpace.remove())},_setOption:function(t,e){if("label"!==t||e){if(this._super(t,e),"disabled"===t)return this._toggleClass(this.label,null,"ui-state-disabled",e),void(this.element[0].disabled=e);this.refresh()}},_updateIcon:function(t){var e="ui-icon ui-icon-background ";this.options.icon?(this.icon||(this.icon=V("<span>"),this.iconSpace=V("<span> </span>"),this._addClass(this.iconSpace,"ui-checkboxradio-icon-space")),"checkbox"===this.type?(e+=t?"ui-icon-check ui-state-checked":"ui-icon-blank",this._removeClass(this.icon,null,t?"ui-icon-blank":"ui-icon-check")):e+="ui-icon-blank",this._addClass(this.icon,"ui-checkboxradio-icon",e),t||this._removeClass(this.icon,null,"ui-icon-check ui-state-checked"),this.icon.prependTo(this.label).after(this.iconSpace)):void 0!==this.icon&&(this.icon.remove(),this.iconSpace.remove(),delete this.icon)},_updateLabel:function(){var t=this.label.contents().not(this.element[0]);this.icon&&(t=t.not(this.icon[0])),(t=this.iconSpace?t.not(this.iconSpace[0]):t).remove(),this.label.append(this.options.label)},refresh:function(){var t=this.element[0].checked,e=this.element[0].disabled;this._updateIcon(t),this._toggleClass(this.label,"ui-checkboxradio-checked","ui-state-active",t),null!==this.options.label&&this._updateLabel(),e!==this.options.disabled&&this._setOptions({disabled:e})}}]);var _;V.ui.checkboxradio;V.widget("ui.button",{version:"1.13.2",defaultElement:"<button>",options:{classes:{"ui-button":"ui-corner-all"},disabled:null,icon:null,iconPosition:"beginning",label:null,showLabel:!0},_getCreateOptions:function(){var t,e=this._super()||{};return this.isInput=this.element.is("input"),null!=(t=this.element[0].disabled)&&(e.disabled=t),this.originalLabel=this.isInput?this.element.val():this.element.html(),this.originalLabel&&(e.label=this.originalLabel),e},_create:function(){!this.option.showLabel&!this.options.icon&&(this.options.showLabel=!0),null==this.options.disabled&&(this.options.disabled=this.element[0].disabled||!1),this.hasTitle=!!this.element.attr("title"),this.options.label&&this.options.label!==this.originalLabel&&(this.isInput?this.element.val(this.options.label):this.element.html(this.options.label)),this._addClass("ui-button","ui-widget"),this._setOption("disabled",this.options.disabled),this._enhance(),this.element.is("a")&&this._on({keyup:function(t){t.keyCode===V.ui.keyCode.SPACE&&(t.preventDefault(),this.element[0].click?this.element[0].click():this.element.trigger("click"))}})},_enhance:function(){this.element.is("button")||this.element.attr("role","button"),this.options.icon&&(this._updateIcon("icon",this.options.icon),this._updateTooltip())},_updateTooltip:function(){this.title=this.element.attr("title"),this.options.showLabel||this.title||this.element.attr("title",this.options.label)},_updateIcon:function(t,e){var i="iconPosition"!==t,s=i?this.options.iconPosition:e,t="top"===s||"bottom"===s;this.icon?i&&this._removeClass(this.icon,null,this.options.icon):(this.icon=V("<span>"),this._addClass(this.icon,"ui-button-icon","ui-icon"),this.options.showLabel||this._addClass("ui-button-icon-only")),i&&this._addClass(this.icon,null,e),this._attachIcon(s),t?(this._addClass(this.icon,null,"ui-widget-icon-block"),this.iconSpace&&this.iconSpace.remove()):(this.iconSpace||(this.iconSpace=V("<span> </span>"),this._addClass(this.iconSpace,"ui-button-icon-space")),this._removeClass(this.icon,null,"ui-wiget-icon-block"),this._attachIconSpace(s))},_destroy:function(){this.element.removeAttr("role"),this.icon&&this.icon.remove(),this.iconSpace&&this.iconSpace.remove(),this.hasTitle||this.element.removeAttr("title")},_attachIconSpace:function(t){this.icon[/^(?:end|bottom)/.test(t)?"before":"after"](this.iconSpace)},_attachIcon:function(t){this.element[/^(?:end|bottom)/.test(t)?"append":"prepend"](this.icon)},_setOptions:function(t){var e=(void 0===t.showLabel?this.options:t).showLabel,i=(void 0===t.icon?this.options:t).icon;e||i||(t.showLabel=!0),this._super(t)},_setOption:function(t,e){"icon"===t&&(e?this._updateIcon(t,e):this.icon&&(this.icon.remove(),this.iconSpace&&this.iconSpace.remove())),"iconPosition"===t&&this._updateIcon(t,e),"showLabel"===t&&(this._toggleClass("ui-button-icon-only",null,!e),this._updateTooltip()),"label"===t&&(this.isInput?this.element.val(e):(this.element.html(e),this.icon&&(this._attachIcon(this.options.iconPosition),this._attachIconSpace(this.options.iconPosition)))),this._super(t,e),"disabled"===t&&(this._toggleClass(null,"ui-state-disabled",e),(this.element[0].disabled=e)&&this.element.trigger("blur"))},refresh:function(){var t=this.element.is("input, button")?this.element[0].disabled:this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOptions({disabled:t}),this._updateTooltip()}}),!1!==V.uiBackCompat&&(V.widget("ui.button",V.ui.button,{options:{text:!0,icons:{primary:null,secondary:null}},_create:function(){this.options.showLabel&&!this.options.text&&(this.options.showLabel=this.options.text),!this.options.showLabel&&this.options.text&&(this.options.text=this.options.showLabel),this.options.icon||!this.options.icons.primary&&!this.options.icons.secondary?this.options.icon&&(this.options.icons.primary=this.options.icon):this.options.icons.primary?this.options.icon=this.options.icons.primary:(this.options.icon=this.options.icons.secondary,this.options.iconPosition="end"),this._super()},_setOption:function(t,e){"text"!==t?("showLabel"===t&&(this.options.text=e),"icon"===t&&(this.options.icons.primary=e),"icons"===t&&(e.primary?(this._super("icon",e.primary),this._super("iconPosition","beginning")):e.secondary&&(this._super("icon",e.secondary),this._super("iconPosition","end"))),this._superApply(arguments)):this._super("showLabel",e)}}),V.fn.button=(_=V.fn.button,function(i){var t="string"==typeof i,s=Array.prototype.slice.call(arguments,1),n=this;return t?this.length||"instance"!==i?this.each(function(){var t=V(this).attr("type"),e=V.data(this,"ui-"+("checkbox"!==t&&"radio"!==t?"button":"checkboxradio"));return"instance"===i?(n=e,!1):e?"function"!=typeof e[i]||"_"===i.charAt(0)?V.error("no such method '"+i+"' for button widget instance"):(t=e[i].apply(e,s))!==e&&void 0!==t?(n=t&&t.jquery?n.pushStack(t.get()):t,!1):void 0:V.error("cannot call methods on button prior to initialization; attempted to call method '"+i+"'")}):n=void 0:(s.length&&(i=V.widget.extend.apply(null,[i].concat(s))),this.each(function(){var t=V(this).attr("type"),e="checkbox"!==t&&"radio"!==t?"button":"checkboxradio",t=V.data(this,"ui-"+e);t?(t.option(i||{}),t._init&&t._init()):"button"!=e?V(this).checkboxradio(V.extend({icon:!1},i)):_.call(V(this),i)})),n}),V.fn.buttonset=function(){return V.ui.controlgroup||V.error("Controlgroup widget missing"),"option"===arguments[0]&&"items"===arguments[1]&&arguments[2]?this.controlgroup.apply(this,[arguments[0],"items.button",arguments[2]]):"option"===arguments[0]&&"items"===arguments[1]?this.controlgroup.apply(this,[arguments[0],"items.button"]):("object"==typeof arguments[0]&&arguments[0].items&&(arguments[0].items={button:arguments[0].items}),this.controlgroup.apply(this,arguments))});var v;V.ui.button;function b(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:"",selectMonthLabel:"Select month",selectYearLabel:"Select year"},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,onUpdateDatepicker:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},V.extend(this._defaults,this.regional[""]),this.regional.en=V.extend(!0,{},this.regional[""]),this.regional["en-US"]=V.extend(!0,{},this.regional.en),this.dpDiv=y(V("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function y(t){var e="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return t.on("mouseout",e,function(){V(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&V(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&V(this).removeClass("ui-datepicker-next-hover")}).on("mouseover",e,w)}function w(){V.datepicker._isDisabledDatepicker((v.inline?v.dpDiv.parent():v.input)[0])||(V(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),V(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&V(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&V(this).addClass("ui-datepicker-next-hover"))}function P(t,e){for(var i in V.extend(t,e),e)null==e[i]&&(t[i]=e[i]);return t}V.extend(V.ui,{datepicker:{version:"1.13.2"}}),V.extend(b.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(t){return P(this._defaults,t||{}),this},_attachDatepicker:function(t,e){var i,s=t.nodeName.toLowerCase(),n="div"===s||"span"===s;t.id||(this.uuid+=1,t.id="dp"+this.uuid),(i=this._newInst(V(t),n)).settings=V.extend({},e||{}),"input"===s?this._connectDatepicker(t,i):n&&this._inlineDatepicker(t,i)},_newInst:function(t,e){return{id:t[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1"),input:t,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:e,dpDiv:e?y(V("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(t,e){var i=V(t);e.append=V([]),e.trigger=V([]),i.hasClass(this.markerClassName)||(this._attachments(i,e),i.addClass(this.markerClassName).on("keydown",this._doKeyDown).on("keypress",this._doKeyPress).on("keyup",this._doKeyUp),this._autoSize(e),V.data(t,"datepicker",e),e.settings.disabled&&this._disableDatepicker(t))},_attachments:function(t,e){var i,s=this._get(e,"appendText"),n=this._get(e,"isRTL");e.append&&e.append.remove(),s&&(e.append=V("<span>").addClass(this._appendClass).text(s),t[n?"before":"after"](e.append)),t.off("focus",this._showDatepicker),e.trigger&&e.trigger.remove(),"focus"!==(i=this._get(e,"showOn"))&&"both"!==i||t.on("focus",this._showDatepicker),"button"!==i&&"both"!==i||(s=this._get(e,"buttonText"),i=this._get(e,"buttonImage"),this._get(e,"buttonImageOnly")?e.trigger=V("<img>").addClass(this._triggerClass).attr({src:i,alt:s,title:s}):(e.trigger=V("<button type='button'>").addClass(this._triggerClass),i?e.trigger.html(V("<img>").attr({src:i,alt:s,title:s})):e.trigger.text(s)),t[n?"before":"after"](e.trigger),e.trigger.on("click",function(){return V.datepicker._datepickerShowing&&V.datepicker._lastInput===t[0]?V.datepicker._hideDatepicker():(V.datepicker._datepickerShowing&&V.datepicker._lastInput!==t[0]&&V.datepicker._hideDatepicker(),V.datepicker._showDatepicker(t[0])),!1}))},_autoSize:function(t){var e,i,s,n,o,a;this._get(t,"autoSize")&&!t.inline&&(o=new Date(2009,11,20),(a=this._get(t,"dateFormat")).match(/[DM]/)&&(e=function(t){for(n=s=i=0;n<t.length;n++)t[n].length>i&&(i=t[n].length,s=n);return s},o.setMonth(e(this._get(t,a.match(/MM/)?"monthNames":"monthNamesShort"))),o.setDate(e(this._get(t,a.match(/DD/)?"dayNames":"dayNamesShort"))+20-o.getDay())),t.input.attr("size",this._formatDate(t,o).length))},_inlineDatepicker:function(t,e){var i=V(t);i.hasClass(this.markerClassName)||(i.addClass(this.markerClassName).append(e.dpDiv),V.data(t,"datepicker",e),this._setDate(e,this._getDefaultDate(e),!0),this._updateDatepicker(e),this._updateAlternate(e),e.settings.disabled&&this._disableDatepicker(t),e.dpDiv.css("display","block"))},_dialogDatepicker:function(t,e,i,s,n){var o,a=this._dialogInst;return a||(this.uuid+=1,o="dp"+this.uuid,this._dialogInput=V("<input type='text' id='"+o+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.on("keydown",this._doKeyDown),V("body").append(this._dialogInput),(a=this._dialogInst=this._newInst(this._dialogInput,!1)).settings={},V.data(this._dialogInput[0],"datepicker",a)),P(a.settings,s||{}),e=e&&e.constructor===Date?this._formatDate(a,e):e,this._dialogInput.val(e),this._pos=n?n.length?n:[n.pageX,n.pageY]:null,this._pos||(o=document.documentElement.clientWidth,s=document.documentElement.clientHeight,e=document.documentElement.scrollLeft||document.body.scrollLeft,n=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[o/2-100+e,s/2-150+n]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),a.settings.onSelect=i,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),V.blockUI&&V.blockUI(this.dpDiv),V.data(this._dialogInput[0],"datepicker",a),this},_destroyDatepicker:function(t){var e,i=V(t),s=V.data(t,"datepicker");i.hasClass(this.markerClassName)&&(e=t.nodeName.toLowerCase(),V.removeData(t,"datepicker"),"input"===e?(s.append.remove(),s.trigger.remove(),i.removeClass(this.markerClassName).off("focus",this._showDatepicker).off("keydown",this._doKeyDown).off("keypress",this._doKeyPress).off("keyup",this._doKeyUp)):"div"!==e&&"span"!==e||i.removeClass(this.markerClassName).empty(),v===s&&(v=null,this._curInst=null))},_enableDatepicker:function(e){var t,i=V(e),s=V.data(e,"datepicker");i.hasClass(this.markerClassName)&&("input"===(t=e.nodeName.toLowerCase())?(e.disabled=!1,s.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):"div"!==t&&"span"!==t||((i=i.children("."+this._inlineClass)).children().removeClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=V.map(this._disabledInputs,function(t){return t===e?null:t}))},_disableDatepicker:function(e){var t,i=V(e),s=V.data(e,"datepicker");i.hasClass(this.markerClassName)&&("input"===(t=e.nodeName.toLowerCase())?(e.disabled=!0,s.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):"div"!==t&&"span"!==t||((i=i.children("."+this._inlineClass)).children().addClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=V.map(this._disabledInputs,function(t){return t===e?null:t}),this._disabledInputs[this._disabledInputs.length]=e)},_isDisabledDatepicker:function(t){if(!t)return!1;for(var e=0;e<this._disabledInputs.length;e++)if(this._disabledInputs[e]===t)return!0;return!1},_getInst:function(t){try{return V.data(t,"datepicker")}catch(t){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(t,e,i){var s,n,o=this._getInst(t);if(2===arguments.length&&"string"==typeof e)return"defaults"===e?V.extend({},V.datepicker._defaults):o?"all"===e?V.extend({},o.settings):this._get(o,e):null;s=e||{},"string"==typeof e&&((s={})[e]=i),o&&(this._curInst===o&&this._hideDatepicker(),n=this._getDateDatepicker(t,!0),e=this._getMinMaxDate(o,"min"),i=this._getMinMaxDate(o,"max"),P(o.settings,s),null!==e&&void 0!==s.dateFormat&&void 0===s.minDate&&(o.settings.minDate=this._formatDate(o,e)),null!==i&&void 0!==s.dateFormat&&void 0===s.maxDate&&(o.settings.maxDate=this._formatDate(o,i)),"disabled"in s&&(s.disabled?this._disableDatepicker(t):this._enableDatepicker(t)),this._attachments(V(t),o),this._autoSize(o),this._setDate(o,n),this._updateAlternate(o),this._updateDatepicker(o))},_changeDatepicker:function(t,e,i){this._optionDatepicker(t,e,i)},_refreshDatepicker:function(t){t=this._getInst(t);t&&this._updateDatepicker(t)},_setDateDatepicker:function(t,e){t=this._getInst(t);t&&(this._setDate(t,e),this._updateDatepicker(t),this._updateAlternate(t))},_getDateDatepicker:function(t,e){t=this._getInst(t);return t&&!t.inline&&this._setDateFromField(t,e),t?this._getDate(t):null},_doKeyDown:function(t){var e,i,s=V.datepicker._getInst(t.target),n=!0,o=s.dpDiv.is(".ui-datepicker-rtl");if(s._keyEvent=!0,V.datepicker._datepickerShowing)switch(t.keyCode){case 9:V.datepicker._hideDatepicker(),n=!1;break;case 13:return(i=V("td."+V.datepicker._dayOverClass+":not(."+V.datepicker._currentClass+")",s.dpDiv))[0]&&V.datepicker._selectDay(t.target,s.selectedMonth,s.selectedYear,i[0]),(e=V.datepicker._get(s,"onSelect"))?(i=V.datepicker._formatDate(s),e.apply(s.input?s.input[0]:null,[i,s])):V.datepicker._hideDatepicker(),!1;case 27:V.datepicker._hideDatepicker();break;case 33:V.datepicker._adjustDate(t.target,t.ctrlKey?-V.datepicker._get(s,"stepBigMonths"):-V.datepicker._get(s,"stepMonths"),"M");break;case 34:V.datepicker._adjustDate(t.target,t.ctrlKey?+V.datepicker._get(s,"stepBigMonths"):+V.datepicker._get(s,"stepMonths"),"M");break;case 35:(t.ctrlKey||t.metaKey)&&V.datepicker._clearDate(t.target),n=t.ctrlKey||t.metaKey;break;case 36:(t.ctrlKey||t.metaKey)&&V.datepicker._gotoToday(t.target),n=t.ctrlKey||t.metaKey;break;case 37:(t.ctrlKey||t.metaKey)&&V.datepicker._adjustDate(t.target,o?1:-1,"D"),n=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&V.datepicker._adjustDate(t.target,t.ctrlKey?-V.datepicker._get(s,"stepBigMonths"):-V.datepicker._get(s,"stepMonths"),"M");break;case 38:(t.ctrlKey||t.metaKey)&&V.datepicker._adjustDate(t.target,-7,"D"),n=t.ctrlKey||t.metaKey;break;case 39:(t.ctrlKey||t.metaKey)&&V.datepicker._adjustDate(t.target,o?-1:1,"D"),n=t.ctrlKey||t.metaKey,t.originalEvent.altKey&&V.datepicker._adjustDate(t.target,t.ctrlKey?+V.datepicker._get(s,"stepBigMonths"):+V.datepicker._get(s,"stepMonths"),"M");break;case 40:(t.ctrlKey||t.metaKey)&&V.datepicker._adjustDate(t.target,7,"D"),n=t.ctrlKey||t.metaKey;break;default:n=!1}else 36===t.keyCode&&t.ctrlKey?V.datepicker._showDatepicker(this):n=!1;n&&(t.preventDefault(),t.stopPropagation())},_doKeyPress:function(t){var e,i=V.datepicker._getInst(t.target);if(V.datepicker._get(i,"constrainInput"))return e=V.datepicker._possibleChars(V.datepicker._get(i,"dateFormat")),i=String.fromCharCode(null==t.charCode?t.keyCode:t.charCode),t.ctrlKey||t.metaKey||i<" "||!e||-1<e.indexOf(i)},_doKeyUp:function(t){t=V.datepicker._getInst(t.target);if(t.input.val()!==t.lastVal)try{V.datepicker.parseDate(V.datepicker._get(t,"dateFormat"),t.input?t.input.val():null,V.datepicker._getFormatConfig(t))&&(V.datepicker._setDateFromField(t),V.datepicker._updateAlternate(t),V.datepicker._updateDatepicker(t))}catch(t){}return!0},_showDatepicker:function(t){var e,i,s,n;"input"!==(t=t.target||t).nodeName.toLowerCase()&&(t=V("input",t.parentNode)[0]),V.datepicker._isDisabledDatepicker(t)||V.datepicker._lastInput===t||(n=V.datepicker._getInst(t),V.datepicker._curInst&&V.datepicker._curInst!==n&&(V.datepicker._curInst.dpDiv.stop(!0,!0),n&&V.datepicker._datepickerShowing&&V.datepicker._hideDatepicker(V.datepicker._curInst.input[0])),!1!==(i=(s=V.datepicker._get(n,"beforeShow"))?s.apply(t,[t,n]):{})&&(P(n.settings,i),n.lastVal=null,V.datepicker._lastInput=t,V.datepicker._setDateFromField(n),V.datepicker._inDialog&&(t.value=""),V.datepicker._pos||(V.datepicker._pos=V.datepicker._findPos(t),V.datepicker._pos[1]+=t.offsetHeight),e=!1,V(t).parents().each(function(){return!(e|="fixed"===V(this).css("position"))}),s={left:V.datepicker._pos[0],top:V.datepicker._pos[1]},V.datepicker._pos=null,n.dpDiv.empty(),n.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),V.datepicker._updateDatepicker(n),s=V.datepicker._checkOffset(n,s,e),n.dpDiv.css({position:V.datepicker._inDialog&&V.blockUI?"static":e?"fixed":"absolute",display:"none",left:s.left+"px",top:s.top+"px"}),n.inline||(i=V.datepicker._get(n,"showAnim"),s=V.datepicker._get(n,"duration"),n.dpDiv.css("z-index",function(t){for(var e,i;t.length&&t[0]!==document;){if(("absolute"===(e=t.css("position"))||"relative"===e||"fixed"===e)&&(i=parseInt(t.css("zIndex"),10),!isNaN(i)&&0!==i))return i;t=t.parent()}return 0}(V(t))+1),V.datepicker._datepickerShowing=!0,V.effects&&V.effects.effect[i]?n.dpDiv.show(i,V.datepicker._get(n,"showOptions"),s):n.dpDiv[i||"show"](i?s:null),V.datepicker._shouldFocusInput(n)&&n.input.trigger("focus"),V.datepicker._curInst=n)))},_updateDatepicker:function(t){this.maxRows=4,(v=t).dpDiv.empty().append(this._generateHTML(t)),this._attachHandlers(t);var e,i=this._getNumberOfMonths(t),s=i[1],n=t.dpDiv.find("."+this._dayOverClass+" a"),o=V.datepicker._get(t,"onUpdateDatepicker");0<n.length&&w.apply(n.get(0)),t.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),1<s&&t.dpDiv.addClass("ui-datepicker-multi-"+s).css("width",17*s+"em"),t.dpDiv[(1!==i[0]||1!==i[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),t.dpDiv[(this._get(t,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),t===V.datepicker._curInst&&V.datepicker._datepickerShowing&&V.datepicker._shouldFocusInput(t)&&t.input.trigger("focus"),t.yearshtml&&(e=t.yearshtml,setTimeout(function(){e===t.yearshtml&&t.yearshtml&&t.dpDiv.find("select.ui-datepicker-year").first().replaceWith(t.yearshtml),e=t.yearshtml=null},0)),o&&o.apply(t.input?t.input[0]:null,[t])},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(t,e,i){var s=t.dpDiv.outerWidth(),n=t.dpDiv.outerHeight(),o=t.input?t.input.outerWidth():0,a=t.input?t.input.outerHeight():0,r=document.documentElement.clientWidth+(i?0:V(document).scrollLeft()),l=document.documentElement.clientHeight+(i?0:V(document).scrollTop());return e.left-=this._get(t,"isRTL")?s-o:0,e.left-=i&&e.left===t.input.offset().left?V(document).scrollLeft():0,e.top-=i&&e.top===t.input.offset().top+a?V(document).scrollTop():0,e.left-=Math.min(e.left,e.left+s>r&&s<r?Math.abs(e.left+s-r):0),e.top-=Math.min(e.top,e.top+n>l&&n<l?Math.abs(n+a):0),e},_findPos:function(t){for(var e=this._getInst(t),i=this._get(e,"isRTL");t&&("hidden"===t.type||1!==t.nodeType||V.expr.pseudos.hidden(t));)t=t[i?"previousSibling":"nextSibling"];return[(e=V(t).offset()).left,e.top]},_hideDatepicker:function(t){var e,i,s=this._curInst;!s||t&&s!==V.data(t,"datepicker")||this._datepickerShowing&&(e=this._get(s,"showAnim"),i=this._get(s,"duration"),t=function(){V.datepicker._tidyDialog(s)},V.effects&&(V.effects.effect[e]||V.effects[e])?s.dpDiv.hide(e,V.datepicker._get(s,"showOptions"),i,t):s.dpDiv["slideDown"===e?"slideUp":"fadeIn"===e?"fadeOut":"hide"](e?i:null,t),e||t(),this._datepickerShowing=!1,(t=this._get(s,"onClose"))&&t.apply(s.input?s.input[0]:null,[s.input?s.input.val():"",s]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),V.blockUI&&(V.unblockUI(),V("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).off(".ui-datepicker-calendar")},_checkExternalClick:function(t){var e;V.datepicker._curInst&&(e=V(t.target),t=V.datepicker._getInst(e[0]),(e[0].id===V.datepicker._mainDivId||0!==e.parents("#"+V.datepicker._mainDivId).length||e.hasClass(V.datepicker.markerClassName)||e.closest("."+V.datepicker._triggerClass).length||!V.datepicker._datepickerShowing||V.datepicker._inDialog&&V.blockUI)&&(!e.hasClass(V.datepicker.markerClassName)||V.datepicker._curInst===t)||V.datepicker._hideDatepicker())},_adjustDate:function(t,e,i){var s=V(t),t=this._getInst(s[0]);this._isDisabledDatepicker(s[0])||(this._adjustInstDate(t,e,i),this._updateDatepicker(t))},_gotoToday:function(t){var e=V(t),i=this._getInst(e[0]);this._get(i,"gotoCurrent")&&i.currentDay?(i.selectedDay=i.currentDay,i.drawMonth=i.selectedMonth=i.currentMonth,i.drawYear=i.selectedYear=i.currentYear):(t=new Date,i.selectedDay=t.getDate(),i.drawMonth=i.selectedMonth=t.getMonth(),i.drawYear=i.selectedYear=t.getFullYear()),this._notifyChange(i),this._adjustDate(e)},_selectMonthYear:function(t,e,i){var s=V(t),t=this._getInst(s[0]);t["selected"+("M"===i?"Month":"Year")]=t["draw"+("M"===i?"Month":"Year")]=parseInt(e.options[e.selectedIndex].value,10),this._notifyChange(t),this._adjustDate(s)},_selectDay:function(t,e,i,s){var n=V(t);V(s).hasClass(this._unselectableClass)||this._isDisabledDatepicker(n[0])||((n=this._getInst(n[0])).selectedDay=n.currentDay=parseInt(V("a",s).attr("data-date")),n.selectedMonth=n.currentMonth=e,n.selectedYear=n.currentYear=i,this._selectDate(t,this._formatDate(n,n.currentDay,n.currentMonth,n.currentYear)))},_clearDate:function(t){t=V(t);this._selectDate(t,"")},_selectDate:function(t,e){var i=V(t),t=this._getInst(i[0]);e=null!=e?e:this._formatDate(t),t.input&&t.input.val(e),this._updateAlternate(t),(i=this._get(t,"onSelect"))?i.apply(t.input?t.input[0]:null,[e,t]):t.input&&t.input.trigger("change"),t.inline?this._updateDatepicker(t):(this._hideDatepicker(),this._lastInput=t.input[0],"object"!=typeof t.input[0]&&t.input.trigger("focus"),this._lastInput=null)},_updateAlternate:function(t){var e,i,s=this._get(t,"altField");s&&(e=this._get(t,"altFormat")||this._get(t,"dateFormat"),i=this._getDate(t),t=this.formatDate(e,i,this._getFormatConfig(t)),V(document).find(s).val(t))},noWeekends:function(t){t=t.getDay();return[0<t&&t<6,""]},iso8601Week:function(t){var e=new Date(t.getTime());return e.setDate(e.getDate()+4-(e.getDay()||7)),t=e.getTime(),e.setMonth(0),e.setDate(1),Math.floor(Math.round((t-e)/864e5)/7)+1},parseDate:function(e,n,t){if(null==e||null==n)throw"Invalid arguments";if(""===(n="object"==typeof n?n.toString():n+""))return null;for(var i,s,o,a=0,r=(t?t.shortYearCutoff:null)||this._defaults.shortYearCutoff,r="string"!=typeof r?r:(new Date).getFullYear()%100+parseInt(r,10),l=(t?t.dayNamesShort:null)||this._defaults.dayNamesShort,h=(t?t.dayNames:null)||this._defaults.dayNames,c=(t?t.monthNamesShort:null)||this._defaults.monthNamesShort,u=(t?t.monthNames:null)||this._defaults.monthNames,d=-1,p=-1,f=-1,g=-1,m=!1,_=function(t){t=w+1<e.length&&e.charAt(w+1)===t;return t&&w++,t},v=function(t){var e=_(t),e="@"===t?14:"!"===t?20:"y"===t&&e?4:"o"===t?3:2,e=new RegExp("^\\d{"+("y"===t?e:1)+","+e+"}"),e=n.substring(a).match(e);if(!e)throw"Missing number at position "+a;return a+=e[0].length,parseInt(e[0],10)},b=function(t,e,i){var s=-1,e=V.map(_(t)?i:e,function(t,e){return[[e,t]]}).sort(function(t,e){return-(t[1].length-e[1].length)});if(V.each(e,function(t,e){var i=e[1];if(n.substr(a,i.length).toLowerCase()===i.toLowerCase())return s=e[0],a+=i.length,!1}),-1!==s)return s+1;throw"Unknown name at position "+a},y=function(){if(n.charAt(a)!==e.charAt(w))throw"Unexpected literal at position "+a;a++},w=0;w<e.length;w++)if(m)"'"!==e.charAt(w)||_("'")?y():m=!1;else switch(e.charAt(w)){case"d":f=v("d");break;case"D":b("D",l,h);break;case"o":g=v("o");break;case"m":p=v("m");break;case"M":p=b("M",c,u);break;case"y":d=v("y");break;case"@":d=(o=new Date(v("@"))).getFullYear(),p=o.getMonth()+1,f=o.getDate();break;case"!":d=(o=new Date((v("!")-this._ticksTo1970)/1e4)).getFullYear(),p=o.getMonth()+1,f=o.getDate();break;case"'":_("'")?y():m=!0;break;default:y()}if(a<n.length&&(s=n.substr(a),!/^\s+/.test(s)))throw"Extra/unparsed characters found in date: "+s;if(-1===d?d=(new Date).getFullYear():d<100&&(d+=(new Date).getFullYear()-(new Date).getFullYear()%100+(d<=r?0:-100)),-1<g)for(p=1,f=g;;){if(f<=(i=this._getDaysInMonth(d,p-1)))break;p++,f-=i}if((o=this._daylightSavingAdjust(new Date(d,p-1,f))).getFullYear()!==d||o.getMonth()+1!==p||o.getDate()!==f)throw"Invalid date";return o},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*60*60*1e7,formatDate:function(e,t,i){if(!t)return"";function s(t,e,i){var s=""+e;if(c(t))for(;s.length<i;)s="0"+s;return s}function n(t,e,i,s){return(c(t)?s:i)[e]}var o,a=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,r=(i?i.dayNames:null)||this._defaults.dayNames,l=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,h=(i?i.monthNames:null)||this._defaults.monthNames,c=function(t){t=o+1<e.length&&e.charAt(o+1)===t;return t&&o++,t},u="",d=!1;if(t)for(o=0;o<e.length;o++)if(d)"'"!==e.charAt(o)||c("'")?u+=e.charAt(o):d=!1;else switch(e.charAt(o)){case"d":u+=s("d",t.getDate(),2);break;case"D":u+=n("D",t.getDay(),a,r);break;case"o":u+=s("o",Math.round((new Date(t.getFullYear(),t.getMonth(),t.getDate()).getTime()-new Date(t.getFullYear(),0,0).getTime())/864e5),3);break;case"m":u+=s("m",t.getMonth()+1,2);break;case"M":u+=n("M",t.getMonth(),l,h);break;case"y":u+=c("y")?t.getFullYear():(t.getFullYear()%100<10?"0":"")+t.getFullYear()%100;break;case"@":u+=t.getTime();break;case"!":u+=1e4*t.getTime()+this._ticksTo1970;break;case"'":c("'")?u+="'":d=!0;break;default:u+=e.charAt(o)}return u},_possibleChars:function(e){for(var t="",i=!1,s=function(t){t=n+1<e.length&&e.charAt(n+1)===t;return t&&n++,t},n=0;n<e.length;n++)if(i)"'"!==e.charAt(n)||s("'")?t+=e.charAt(n):i=!1;else switch(e.charAt(n)){case"d":case"m":case"y":case"@":t+="0123456789";break;case"D":case"M":return null;case"'":s("'")?t+="'":i=!0;break;default:t+=e.charAt(n)}return t},_get:function(t,e){return(void 0!==t.settings[e]?t.settings:this._defaults)[e]},_setDateFromField:function(t,e){if(t.input.val()!==t.lastVal){var i=this._get(t,"dateFormat"),s=t.lastVal=t.input?t.input.val():null,n=this._getDefaultDate(t),o=n,a=this._getFormatConfig(t);try{o=this.parseDate(i,s,a)||n}catch(t){s=e?"":s}t.selectedDay=o.getDate(),t.drawMonth=t.selectedMonth=o.getMonth(),t.drawYear=t.selectedYear=o.getFullYear(),t.currentDay=s?o.getDate():0,t.currentMonth=s?o.getMonth():0,t.currentYear=s?o.getFullYear():0,this._adjustInstDate(t)}},_getDefaultDate:function(t){return this._restrictMinMax(t,this._determineDate(t,this._get(t,"defaultDate"),new Date))},_determineDate:function(r,t,e){var i,s,t=null==t||""===t?e:"string"==typeof t?function(t){try{return V.datepicker.parseDate(V.datepicker._get(r,"dateFormat"),t,V.datepicker._getFormatConfig(r))}catch(t){}for(var e=(t.toLowerCase().match(/^c/)?V.datepicker._getDate(r):null)||new Date,i=e.getFullYear(),s=e.getMonth(),n=e.getDate(),o=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,a=o.exec(t);a;){switch(a[2]||"d"){case"d":case"D":n+=parseInt(a[1],10);break;case"w":case"W":n+=7*parseInt(a[1],10);break;case"m":case"M":s+=parseInt(a[1],10),n=Math.min(n,V.datepicker._getDaysInMonth(i,s));break;case"y":case"Y":i+=parseInt(a[1],10),n=Math.min(n,V.datepicker._getDaysInMonth(i,s))}a=o.exec(t)}return new Date(i,s,n)}(t):"number"==typeof t?isNaN(t)?e:(i=t,(s=new Date).setDate(s.getDate()+i),s):new Date(t.getTime());return(t=t&&"Invalid Date"===t.toString()?e:t)&&(t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0)),this._daylightSavingAdjust(t)},_daylightSavingAdjust:function(t){return t?(t.setHours(12<t.getHours()?t.getHours()+2:0),t):null},_setDate:function(t,e,i){var s=!e,n=t.selectedMonth,o=t.selectedYear,e=this._restrictMinMax(t,this._determineDate(t,e,new Date));t.selectedDay=t.currentDay=e.getDate(),t.drawMonth=t.selectedMonth=t.currentMonth=e.getMonth(),t.drawYear=t.selectedYear=t.currentYear=e.getFullYear(),n===t.selectedMonth&&o===t.selectedYear||i||this._notifyChange(t),this._adjustInstDate(t),t.input&&t.input.val(s?"":this._formatDate(t))},_getDate:function(t){return!t.currentYear||t.input&&""===t.input.val()?null:this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay))},_attachHandlers:function(t){var e=this._get(t,"stepMonths"),i="#"+t.id.replace(/\\\\/g,"\\");t.dpDiv.find("[data-handler]").map(function(){var t={prev:function(){V.datepicker._adjustDate(i,-e,"M")},next:function(){V.datepicker._adjustDate(i,+e,"M")},hide:function(){V.datepicker._hideDatepicker()},today:function(){V.datepicker._gotoToday(i)},selectDay:function(){return V.datepicker._selectDay(i,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return V.datepicker._selectMonthYear(i,this,"M"),!1},selectYear:function(){return V.datepicker._selectMonthYear(i,this,"Y"),!1}};V(this).on(this.getAttribute("data-event"),t[this.getAttribute("data-handler")])})},_generateHTML:function(t){var e,i,s,n,o,a,r,l,h,c,u,d,p,f,g,m,_,v,b,y,w,x,k,C,D,I,T,P,M,S,H,z,A=new Date,O=this._daylightSavingAdjust(new Date(A.getFullYear(),A.getMonth(),A.getDate())),N=this._get(t,"isRTL"),E=this._get(t,"showButtonPanel"),W=this._get(t,"hideIfNoPrevNext"),F=this._get(t,"navigationAsDateFormat"),L=this._getNumberOfMonths(t),R=this._get(t,"showCurrentAtPos"),A=this._get(t,"stepMonths"),Y=1!==L[0]||1!==L[1],B=this._daylightSavingAdjust(t.currentDay?new Date(t.currentYear,t.currentMonth,t.currentDay):new Date(9999,9,9)),j=this._getMinMaxDate(t,"min"),q=this._getMinMaxDate(t,"max"),K=t.drawMonth-R,U=t.drawYear;if(K<0&&(K+=12,U--),q)for(e=this._daylightSavingAdjust(new Date(q.getFullYear(),q.getMonth()-L[0]*L[1]+1,q.getDate())),e=j&&e<j?j:e;this._daylightSavingAdjust(new Date(U,K,1))>e;)--K<0&&(K=11,U--);for(t.drawMonth=K,t.drawYear=U,R=this._get(t,"prevText"),R=F?this.formatDate(R,this._daylightSavingAdjust(new Date(U,K-A,1)),this._getFormatConfig(t)):R,i=this._canAdjustMonth(t,-1,U,K)?V("<a>").attr({class:"ui-datepicker-prev ui-corner-all","data-handler":"prev","data-event":"click",title:R}).append(V("<span>").addClass("ui-icon ui-icon-circle-triangle-"+(N?"e":"w")).text(R))[0].outerHTML:W?"":V("<a>").attr({class:"ui-datepicker-prev ui-corner-all ui-state-disabled",title:R}).append(V("<span>").addClass("ui-icon ui-icon-circle-triangle-"+(N?"e":"w")).text(R))[0].outerHTML,R=this._get(t,"nextText"),R=F?this.formatDate(R,this._daylightSavingAdjust(new Date(U,K+A,1)),this._getFormatConfig(t)):R,s=this._canAdjustMonth(t,1,U,K)?V("<a>").attr({class:"ui-datepicker-next ui-corner-all","data-handler":"next","data-event":"click",title:R}).append(V("<span>").addClass("ui-icon ui-icon-circle-triangle-"+(N?"w":"e")).text(R))[0].outerHTML:W?"":V("<a>").attr({class:"ui-datepicker-next ui-corner-all ui-state-disabled",title:R}).append(V("<span>").attr("class","ui-icon ui-icon-circle-triangle-"+(N?"w":"e")).text(R))[0].outerHTML,A=this._get(t,"currentText"),W=this._get(t,"gotoCurrent")&&t.currentDay?B:O,A=F?this.formatDate(A,W,this._getFormatConfig(t)):A,R="",t.inline||(R=V("<button>").attr({type:"button",class:"ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all","data-handler":"hide","data-event":"click"}).text(this._get(t,"closeText"))[0].outerHTML),F="",E&&(F=V("<div class='ui-datepicker-buttonpane ui-widget-content'>").append(N?R:"").append(this._isInRange(t,W)?V("<button>").attr({type:"button",class:"ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all","data-handler":"today","data-event":"click"}).text(A):"").append(N?"":R)[0].outerHTML),n=parseInt(this._get(t,"firstDay"),10),n=isNaN(n)?0:n,o=this._get(t,"showWeek"),a=this._get(t,"dayNames"),r=this._get(t,"dayNamesMin"),l=this._get(t,"monthNames"),h=this._get(t,"monthNamesShort"),c=this._get(t,"beforeShowDay"),u=this._get(t,"showOtherMonths"),d=this._get(t,"selectOtherMonths"),p=this._getDefaultDate(t),f="",m=0;m<L[0];m++){for(_="",this.maxRows=4,v=0;v<L[1];v++){if(b=this._daylightSavingAdjust(new Date(U,K,t.selectedDay)),y=" ui-corner-all",w="",Y){if(w+="<div class='ui-datepicker-group",1<L[1])switch(v){case 0:w+=" ui-datepicker-group-first",y=" ui-corner-"+(N?"right":"left");break;case L[1]-1:w+=" ui-datepicker-group-last",y=" ui-corner-"+(N?"left":"right");break;default:w+=" ui-datepicker-group-middle",y=""}w+="'>"}for(w+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+y+"'>"+(/all|left/.test(y)&&0===m?N?s:i:"")+(/all|right/.test(y)&&0===m?N?i:s:"")+this._generateMonthYearHeader(t,K,U,j,q,0<m||0<v,l,h)+"</div><table class='ui-datepicker-calendar'><thead><tr>",x=o?"<th class='ui-datepicker-week-col'>"+this._get(t,"weekHeader")+"</th>":"",g=0;g<7;g++)x+="<th scope='col'"+(5<=(g+n+6)%7?" class='ui-datepicker-week-end'":"")+"><span title='"+a[k=(g+n)%7]+"'>"+r[k]+"</span></th>";for(w+=x+"</tr></thead><tbody>",D=this._getDaysInMonth(U,K),U===t.selectedYear&&K===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,D)),C=(this._getFirstDayOfMonth(U,K)-n+7)%7,D=Math.ceil((C+D)/7),I=Y&&this.maxRows>D?this.maxRows:D,this.maxRows=I,T=this._daylightSavingAdjust(new Date(U,K,1-C)),P=0;P<I;P++){for(w+="<tr>",M=o?"<td class='ui-datepicker-week-col'>"+this._get(t,"calculateWeek")(T)+"</td>":"",g=0;g<7;g++)S=c?c.apply(t.input?t.input[0]:null,[T]):[!0,""],z=(H=T.getMonth()!==K)&&!d||!S[0]||j&&T<j||q&&q<T,M+="<td class='"+(5<=(g+n+6)%7?" ui-datepicker-week-end":"")+(H?" ui-datepicker-other-month":"")+(T.getTime()===b.getTime()&&K===t.selectedMonth&&t._keyEvent||p.getTime()===T.getTime()&&p.getTime()===b.getTime()?" "+this._dayOverClass:"")+(z?" "+this._unselectableClass+" ui-state-disabled":"")+(H&&!u?"":" "+S[1]+(T.getTime()===B.getTime()?" "+this._currentClass:"")+(T.getTime()===O.getTime()?" ui-datepicker-today":""))+"'"+(H&&!u||!S[2]?"":" title='"+S[2].replace(/'/g,"&#39;")+"'")+(z?"":" data-handler='selectDay' data-event='click' data-month='"+T.getMonth()+"' data-year='"+T.getFullYear()+"'")+">"+(H&&!u?"&#xa0;":z?"<span class='ui-state-default'>"+T.getDate()+"</span>":"<a class='ui-state-default"+(T.getTime()===O.getTime()?" ui-state-highlight":"")+(T.getTime()===B.getTime()?" ui-state-active":"")+(H?" ui-priority-secondary":"")+"' href='#' aria-current='"+(T.getTime()===B.getTime()?"true":"false")+"' data-date='"+T.getDate()+"'>"+T.getDate()+"</a>")+"</td>",T.setDate(T.getDate()+1),T=this._daylightSavingAdjust(T);w+=M+"</tr>"}11<++K&&(K=0,U++),_+=w+="</tbody></table>"+(Y?"</div>"+(0<L[0]&&v===L[1]-1?"<div class='ui-datepicker-row-break'></div>":""):"")}f+=_}return f+=F,t._keyEvent=!1,f},_generateMonthYearHeader:function(t,e,i,s,n,o,a,r){var l,h,c,u,d,p,f=this._get(t,"changeMonth"),g=this._get(t,"changeYear"),m=this._get(t,"showMonthAfterYear"),_=this._get(t,"selectMonthLabel"),v=this._get(t,"selectYearLabel"),b="<div class='ui-datepicker-title'>",y="";if(o||!f)y+="<span class='ui-datepicker-month'>"+a[e]+"</span>";else{for(l=s&&s.getFullYear()===i,h=n&&n.getFullYear()===i,y+="<select class='ui-datepicker-month' aria-label='"+_+"' data-handler='selectMonth' data-event='change'>",c=0;c<12;c++)(!l||c>=s.getMonth())&&(!h||c<=n.getMonth())&&(y+="<option value='"+c+"'"+(c===e?" selected='selected'":"")+">"+r[c]+"</option>");y+="</select>"}if(m||(b+=y+(!o&&f&&g?"":"&#xa0;")),!t.yearshtml)if(t.yearshtml="",o||!g)b+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(a=this._get(t,"yearRange").split(":"),u=(new Date).getFullYear(),d=(_=function(t){t=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.match(/[+\-].*/)?u+parseInt(t,10):parseInt(t,10);return isNaN(t)?u:t})(a[0]),p=Math.max(d,_(a[1]||"")),d=s?Math.max(d,s.getFullYear()):d,p=n?Math.min(p,n.getFullYear()):p,t.yearshtml+="<select class='ui-datepicker-year' aria-label='"+v+"' data-handler='selectYear' data-event='change'>";d<=p;d++)t.yearshtml+="<option value='"+d+"'"+(d===i?" selected='selected'":"")+">"+d+"</option>";t.yearshtml+="</select>",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),m&&(b+=(!o&&f&&g?"":"&#xa0;")+y),b+="</div>"},_adjustInstDate:function(t,e,i){var s=t.selectedYear+("Y"===i?e:0),n=t.selectedMonth+("M"===i?e:0),e=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),e=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,e)));t.selectedDay=e.getDate(),t.drawMonth=t.selectedMonth=e.getMonth(),t.drawYear=t.selectedYear=e.getFullYear(),"M"!==i&&"Y"!==i||this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),t=this._getMinMaxDate(t,"max"),e=i&&e<i?i:e;return t&&t<e?t:e},_notifyChange:function(t){var e=this._get(t,"onChangeMonthYear");e&&e.apply(t.input?t.input[0]:null,[t.selectedYear,t.selectedMonth+1,t])},_getNumberOfMonths:function(t){t=this._get(t,"numberOfMonths");return null==t?[1,1]:"number"==typeof t?[1,t]:t},_getMinMaxDate:function(t,e){return this._determineDate(t,this._get(t,e+"Date"),null)},_getDaysInMonth:function(t,e){return 32-this._daylightSavingAdjust(new Date(t,e,32)).getDate()},_getFirstDayOfMonth:function(t,e){return new Date(t,e,1).getDay()},_canAdjustMonth:function(t,e,i,s){var n=this._getNumberOfMonths(t),n=this._daylightSavingAdjust(new Date(i,s+(e<0?e:n[0]*n[1]),1));return e<0&&n.setDate(this._getDaysInMonth(n.getFullYear(),n.getMonth())),this._isInRange(t,n)},_isInRange:function(t,e){var i=this._getMinMaxDate(t,"min"),s=this._getMinMaxDate(t,"max"),n=null,o=null,a=this._get(t,"yearRange");return a&&(t=a.split(":"),a=(new Date).getFullYear(),n=parseInt(t[0],10),o=parseInt(t[1],10),t[0].match(/[+\-].*/)&&(n+=a),t[1].match(/[+\-].*/)&&(o+=a)),(!i||e.getTime()>=i.getTime())&&(!s||e.getTime()<=s.getTime())&&(!n||e.getFullYear()>=n)&&(!o||e.getFullYear()<=o)},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return{shortYearCutoff:e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);e=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),e,this._getFormatConfig(t))}}),V.fn.datepicker=function(t){if(!this.length)return this;V.datepicker.initialized||(V(document).on("mousedown",V.datepicker._checkExternalClick),V.datepicker.initialized=!0),0===V("#"+V.datepicker._mainDivId).length&&V("body").append(V.datepicker.dpDiv);var e=Array.prototype.slice.call(arguments,1);return"string"==typeof t&&("isDisabled"===t||"getDate"===t||"widget"===t)||"option"===t&&2===arguments.length&&"string"==typeof arguments[1]?V.datepicker["_"+t+"Datepicker"].apply(V.datepicker,[this[0]].concat(e)):this.each(function(){"string"==typeof t?V.datepicker["_"+t+"Datepicker"].apply(V.datepicker,[this].concat(e)):V.datepicker._attachDatepicker(this,t)})},V.datepicker=new b,V.datepicker.initialized=!1,V.datepicker.uuid=(new Date).getTime(),V.datepicker.version="1.13.2";V.datepicker;V.widget("ui.dialog",{version:"1.13.2",options:{appendTo:"body",autoOpen:!0,buttons:[],classes:{"ui-dialog":"ui-corner-all","ui-dialog-titlebar":"ui-corner-all"},closeOnEscape:!0,closeText:"Close",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var e=V(this).css(t).offset().top;e<0&&V(this).css("top",t.top-e)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},sizeRelatedOptions:{buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},resizableRelatedOptions:{maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),null==this.options.title&&null!=this.originalTitle&&(this.options.title=this.originalTitle),this.options.disabled&&(this.options.disabled=!1),this._createWrapper(),this.element.show().removeAttr("title").appendTo(this.uiDialog),this._addClass("ui-dialog-content","ui-widget-content"),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&V.fn.draggable&&this._makeDraggable(),this.options.resizable&&V.fn.resizable&&this._makeResizable(),this._isOpen=!1,this._trackFocus()},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?V(t):this.document.find(t||"body").eq(0)},_destroy:function(){var t,e=this.originalPosition;this._untrackInstance(),this._destroyOverlay(),this.element.removeUniqueId().css(this.originalCss).detach(),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),(t=e.parent.children().eq(e.index)).length&&t[0]!==this.element[0]?t.before(this.element):e.parent.append(this.element)},widget:function(){return this.uiDialog},disable:V.noop,enable:V.noop,close:function(t){var e=this;this._isOpen&&!1!==this._trigger("beforeClose",t)&&(this._isOpen=!1,this._focusedElement=null,this._destroyOverlay(),this._untrackInstance(),this.opener.filter(":focusable").trigger("focus").length||V.ui.safeBlur(V.ui.safeActiveElement(this.document[0])),this._hide(this.uiDialog,this.options.hide,function(){e._trigger("close",t)}))},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,e){var i=!1,s=this.uiDialog.siblings(".ui-front:visible").map(function(){return+V(this).css("z-index")}).get(),s=Math.max.apply(null,s);return s>=+this.uiDialog.css("z-index")&&(this.uiDialog.css("z-index",s+1),i=!0),i&&!e&&this._trigger("focus",t),i},open:function(){var t=this;this._isOpen?this._moveToTop()&&this._focusTabbable():(this._isOpen=!0,this.opener=V(V.ui.safeActiveElement(this.document[0])),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this.overlay&&this.overlay.css("z-index",this.uiDialog.css("z-index")-1),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._makeFocusTarget(),this._trigger("open"))},_focusTabbable:function(){var t=this._focusedElement;(t=!(t=!(t=!(t=!(t=t||this.element.find("[autofocus]")).length?this.element.find(":tabbable"):t).length?this.uiDialogButtonPane.find(":tabbable"):t).length?this.uiDialogTitlebarClose.filter(":tabbable"):t).length?this.uiDialog:t).eq(0).trigger("focus")},_restoreTabbableFocus:function(){var t=V.ui.safeActiveElement(this.document[0]);this.uiDialog[0]===t||V.contains(this.uiDialog[0],t)||this._focusTabbable()},_keepFocus:function(t){t.preventDefault(),this._restoreTabbableFocus(),this._delay(this._restoreTabbableFocus)},_createWrapper:function(){this.uiDialog=V("<div>").hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._addClass(this.uiDialog,"ui-dialog","ui-widget ui-widget-content ui-front"),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===V.ui.keyCode.ESCAPE)return t.preventDefault(),void this.close(t);var e,i,s;t.keyCode!==V.ui.keyCode.TAB||t.isDefaultPrevented()||(e=this.uiDialog.find(":tabbable"),i=e.first(),s=e.last(),t.target!==s[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==i[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(this._delay(function(){s.trigger("focus")}),t.preventDefault()):(this._delay(function(){i.trigger("focus")}),t.preventDefault()))},mousedown:function(t){this._moveToTop(t)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=V("<div>"),this._addClass(this.uiDialogTitlebar,"ui-dialog-titlebar","ui-widget-header ui-helper-clearfix"),this._on(this.uiDialogTitlebar,{mousedown:function(t){V(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.trigger("focus")}}),this.uiDialogTitlebarClose=V("<button type='button'></button>").button({label:V("<a>").text(this.options.closeText).html(),icon:"ui-icon-closethick",showLabel:!1}).appendTo(this.uiDialogTitlebar),this._addClass(this.uiDialogTitlebarClose,"ui-dialog-titlebar-close"),this._on(this.uiDialogTitlebarClose,{click:function(t){t.preventDefault(),this.close(t)}}),t=V("<span>").uniqueId().prependTo(this.uiDialogTitlebar),this._addClass(t,"ui-dialog-title"),this._title(t),this.uiDialogTitlebar.prependTo(this.uiDialog),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(t){this.options.title?t.text(this.options.title):t.html("&#160;")},_createButtonPane:function(){this.uiDialogButtonPane=V("<div>"),this._addClass(this.uiDialogButtonPane,"ui-dialog-buttonpane","ui-widget-content ui-helper-clearfix"),this.uiButtonSet=V("<div>").appendTo(this.uiDialogButtonPane),this._addClass(this.uiButtonSet,"ui-dialog-buttonset"),this._createButtons()},_createButtons:function(){var s=this,t=this.options.buttons;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),V.isEmptyObject(t)||Array.isArray(t)&&!t.length?this._removeClass(this.uiDialog,"ui-dialog-buttons"):(V.each(t,function(t,e){var i;e=V.extend({type:"button"},e="function"==typeof e?{click:e,text:t}:e),i=e.click,t={icon:e.icon,iconPosition:e.iconPosition,showLabel:e.showLabel,icons:e.icons,text:e.text},delete e.click,delete e.icon,delete e.iconPosition,delete e.showLabel,delete e.icons,"boolean"==typeof e.text&&delete e.text,V("<button></button>",e).button(t).appendTo(s.uiButtonSet).on("click",function(){i.apply(s.element[0],arguments)})}),this._addClass(this.uiDialog,"ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog))},_makeDraggable:function(){var n=this,o=this.options;function a(t){return{position:t.position,offset:t.offset}}this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(t,e){n._addClass(V(this),"ui-dialog-dragging"),n._blockFrames(),n._trigger("dragStart",t,a(e))},drag:function(t,e){n._trigger("drag",t,a(e))},stop:function(t,e){var i=e.offset.left-n.document.scrollLeft(),s=e.offset.top-n.document.scrollTop();o.position={my:"left top",at:"left"+(0<=i?"+":"")+i+" top"+(0<=s?"+":"")+s,of:n.window},n._removeClass(V(this),"ui-dialog-dragging"),n._unblockFrames(),n._trigger("dragStop",t,a(e))}})},_makeResizable:function(){var n=this,o=this.options,t=o.resizable,e=this.uiDialog.css("position"),t="string"==typeof t?t:"n,e,s,w,se,sw,ne,nw";function a(t){return{originalPosition:t.originalPosition,originalSize:t.originalSize,position:t.position,size:t.size}}this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:o.maxWidth,maxHeight:o.maxHeight,minWidth:o.minWidth,minHeight:this._minHeight(),handles:t,start:function(t,e){n._addClass(V(this),"ui-dialog-resizing"),n._blockFrames(),n._trigger("resizeStart",t,a(e))},resize:function(t,e){n._trigger("resize",t,a(e))},stop:function(t,e){var i=n.uiDialog.offset(),s=i.left-n.document.scrollLeft(),i=i.top-n.document.scrollTop();o.height=n.uiDialog.height(),o.width=n.uiDialog.width(),o.position={my:"left top",at:"left"+(0<=s?"+":"")+s+" top"+(0<=i?"+":"")+i,of:n.window},n._removeClass(V(this),"ui-dialog-resizing"),n._unblockFrames(),n._trigger("resizeStop",t,a(e))}}).css("position",e)},_trackFocus:function(){this._on(this.widget(),{focusin:function(t){this._makeFocusTarget(),this._focusedElement=V(t.target)}})},_makeFocusTarget:function(){this._untrackInstance(),this._trackingInstances().unshift(this)},_untrackInstance:function(){var t=this._trackingInstances(),e=V.inArray(this,t);-1!==e&&t.splice(e,1)},_trackingInstances:function(){var t=this.document.data("ui-dialog-instances");return t||this.document.data("ui-dialog-instances",t=[]),t},_minHeight:function(){var t=this.options;return"auto"===t.height?t.minHeight:Math.min(t.minHeight,t.height)},_position:function(){var t=this.uiDialog.is(":visible");t||this.uiDialog.show(),this.uiDialog.position(this.options.position),t||this.uiDialog.hide()},_setOptions:function(t){var i=this,s=!1,n={};V.each(t,function(t,e){i._setOption(t,e),t in i.sizeRelatedOptions&&(s=!0),t in i.resizableRelatedOptions&&(n[t]=e)}),s&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",n)},_setOption:function(t,e){var i,s=this.uiDialog;"disabled"!==t&&(this._super(t,e),"appendTo"===t&&this.uiDialog.appendTo(this._appendTo()),"buttons"===t&&this._createButtons(),"closeText"===t&&this.uiDialogTitlebarClose.button({label:V("<a>").text(""+this.options.closeText).html()}),"draggable"===t&&((i=s.is(":data(ui-draggable)"))&&!e&&s.draggable("destroy"),!i&&e&&this._makeDraggable()),"position"===t&&this._position(),"resizable"===t&&((i=s.is(":data(ui-resizable)"))&&!e&&s.resizable("destroy"),i&&"string"==typeof e&&s.resizable("option","handles",e),i||!1===e||this._makeResizable()),"title"===t&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var t,e,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),t=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),e=Math.max(0,s.minHeight-t),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-t):"none","auto"===s.height?this.element.css({minHeight:e,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-t)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=V(this);return V("<div>").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return!!V(t.target).closest(".ui-dialog").length||!!V(t.target).closest(".ui-datepicker").length},_createOverlay:function(){var i,s;this.options.modal&&(i=V.fn.jquery.substring(0,4),s=!0,this._delay(function(){s=!1}),this.document.data("ui-dialog-overlays")||this.document.on("focusin.ui-dialog",function(t){var e;s||((e=this._trackingInstances()[0])._allowInteraction(t)||(t.preventDefault(),e._focusTabbable(),"3.4."!==i&&"3.5."!==i||e._delay(e._restoreTabbableFocus)))}.bind(this)),this.overlay=V("<div>").appendTo(this._appendTo()),this._addClass(this.overlay,null,"ui-widget-overlay ui-front"),this._on(this.overlay,{mousedown:"_keepFocus"}),this.document.data("ui-dialog-overlays",(this.document.data("ui-dialog-overlays")||0)+1))},_destroyOverlay:function(){var t;this.options.modal&&this.overlay&&((t=this.document.data("ui-dialog-overlays")-1)?this.document.data("ui-dialog-overlays",t):(this.document.off("focusin.ui-dialog"),this.document.removeData("ui-dialog-overlays")),this.overlay.remove(),this.overlay=null)}}),!1!==V.uiBackCompat&&V.widget("ui.dialog",V.ui.dialog,{options:{dialogClass:""},_createWrapper:function(){this._super(),this.uiDialog.addClass(this.options.dialogClass)},_setOption:function(t,e){"dialogClass"===t&&this.uiDialog.removeClass(this.options.dialogClass).addClass(e),this._superApply(arguments)}});V.ui.dialog,V.widget("ui.progressbar",{version:"1.13.2",options:{classes:{"ui-progressbar":"ui-corner-all","ui-progressbar-value":"ui-corner-left","ui-progressbar-complete":"ui-corner-right"},max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.attr({role:"progressbar","aria-valuemin":this.min}),this._addClass("ui-progressbar","ui-widget ui-widget-content"),this.valueDiv=V("<div>").appendTo(this.element),this._addClass(this.valueDiv,"ui-progressbar-value","ui-widget-header"),this._refreshValue()},_destroy:function(){this.element.removeAttr("role aria-valuemin aria-valuemax aria-valuenow"),this.valueDiv.remove()},value:function(t){if(void 0===t)return this.options.value;this.options.value=this._constrainedValue(t),this._refreshValue()},_constrainedValue:function(t){return void 0===t&&(t=this.options.value),this.indeterminate=!1===t,"number"!=typeof t&&(t=0),!this.indeterminate&&Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this.element.attr("aria-disabled",t),this._toggleClass(null,"ui-state-disabled",!!t)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var t=this.options.value,e=this._percentage();this.valueDiv.toggle(this.indeterminate||t>this.min).width(e.toFixed(0)+"%"),this._toggleClass(this.valueDiv,"ui-progressbar-complete",null,t===this.options.max)._toggleClass("ui-progressbar-indeterminate",null,this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=V("<div>").appendTo(this.valueDiv),this._addClass(this.overlayDiv,"ui-progressbar-overlay"))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":t}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==t&&(this.oldValue=t,this._trigger("change")),t===this.options.max&&this._trigger("complete")}}),V.widget("ui.selectmenu",[V.ui.formResetMixin,{version:"1.13.2",defaultElement:"<select>",options:{appendTo:null,classes:{"ui-selectmenu-button-open":"ui-corner-top","ui-selectmenu-button-closed":"ui-corner-all"},disabled:null,icons:{button:"ui-icon-triangle-1-s"},position:{my:"left top",at:"left bottom",collision:"none"},width:!1,change:null,close:null,focus:null,open:null,select:null},_create:function(){var t=this.element.uniqueId().attr("id");this.ids={element:t,button:t+"-button",menu:t+"-menu"},this._drawButton(),this._drawMenu(),this._bindFormResetHandler(),this._rendered=!1,this.menuItems=V()},_drawButton:function(){var t,e=this,i=this._parseOption(this.element.find("option:selected"),this.element[0].selectedIndex);this.labels=this.element.labels().attr("for",this.ids.button),this._on(this.labels,{click:function(t){this.button.trigger("focus"),t.preventDefault()}}),this.element.hide(),this.button=V("<span>",{tabindex:this.options.disabled?-1:0,id:this.ids.button,role:"combobox","aria-expanded":"false","aria-autocomplete":"list","aria-owns":this.ids.menu,"aria-haspopup":"true",title:this.element.attr("title")}).insertAfter(this.element),this._addClass(this.button,"ui-selectmenu-button ui-selectmenu-button-closed","ui-button ui-widget"),t=V("<span>").appendTo(this.button),this._addClass(t,"ui-selectmenu-icon","ui-icon "+this.options.icons.button),this.buttonItem=this._renderButtonItem(i).appendTo(this.button),!1!==this.options.width&&this._resizeButton(),this._on(this.button,this._buttonEvents),this.button.one("focusin",function(){e._rendered||e._refreshMenu()})},_drawMenu:function(){var i=this;this.menu=V("<ul>",{"aria-hidden":"true","aria-labelledby":this.ids.button,id:this.ids.menu}),this.menuWrap=V("<div>").append(this.menu),this._addClass(this.menuWrap,"ui-selectmenu-menu","ui-front"),this.menuWrap.appendTo(this._appendTo()),this.menuInstance=this.menu.menu({classes:{"ui-menu":"ui-corner-bottom"},role:"listbox",select:function(t,e){t.preventDefault(),i._setSelection(),i._select(e.item.data("ui-selectmenu-item"),t)},focus:function(t,e){e=e.item.data("ui-selectmenu-item");null!=i.focusIndex&&e.index!==i.focusIndex&&(i._trigger("focus",t,{item:e}),i.isOpen||i._select(e,t)),i.focusIndex=e.index,i.button.attr("aria-activedescendant",i.menuItems.eq(e.index).attr("id"))}}).menu("instance"),this.menuInstance._off(this.menu,"mouseleave"),this.menuInstance._closeOnDocumentClick=function(){return!1},this.menuInstance._isDivider=function(){return!1}},refresh:function(){this._refreshMenu(),this.buttonItem.replaceWith(this.buttonItem=this._renderButtonItem(this._getSelectedItem().data("ui-selectmenu-item")||{})),null===this.options.width&&this._resizeButton()},_refreshMenu:function(){var t=this.element.find("option");this.menu.empty(),this._parseOptions(t),this._renderMenu(this.menu,this.items),this.menuInstance.refresh(),this.menuItems=this.menu.find("li").not(".ui-selectmenu-optgroup").find(".ui-menu-item-wrapper"),this._rendered=!0,t.length&&(t=this._getSelectedItem(),this.menuInstance.focus(null,t),this._setAria(t.data("ui-selectmenu-item")),this._setOption("disabled",this.element.prop("disabled")))},open:function(t){this.options.disabled||(this._rendered?(this._removeClass(this.menu.find(".ui-state-active"),null,"ui-state-active"),this.menuInstance.focus(null,this._getSelectedItem())):this._refreshMenu(),this.menuItems.length&&(this.isOpen=!0,this._toggleAttr(),this._resizeMenu(),this._position(),this._on(this.document,this._documentClick),this._trigger("open",t)))},_position:function(){this.menuWrap.position(V.extend({of:this.button},this.options.position))},close:function(t){this.isOpen&&(this.isOpen=!1,this._toggleAttr(),this.range=null,this._off(this.document),this._trigger("close",t))},widget:function(){return this.button},menuWidget:function(){return this.menu},_renderButtonItem:function(t){var e=V("<span>");return this._setText(e,t.label),this._addClass(e,"ui-selectmenu-text"),e},_renderMenu:function(s,t){var n=this,o="";V.each(t,function(t,e){var i;e.optgroup!==o&&(i=V("<li>",{text:e.optgroup}),n._addClass(i,"ui-selectmenu-optgroup","ui-menu-divider"+(e.element.parent("optgroup").prop("disabled")?" ui-state-disabled":"")),i.appendTo(s),o=e.optgroup),n._renderItemData(s,e)})},_renderItemData:function(t,e){return this._renderItem(t,e).data("ui-selectmenu-item",e)},_renderItem:function(t,e){var i=V("<li>"),s=V("<div>",{title:e.element.attr("title")});return e.disabled&&this._addClass(i,null,"ui-state-disabled"),this._setText(s,e.label),i.append(s).appendTo(t)},_setText:function(t,e){e?t.text(e):t.html("&#160;")},_move:function(t,e){var i,s=".ui-menu-item";this.isOpen?i=this.menuItems.eq(this.focusIndex).parent("li"):(i=this.menuItems.eq(this.element[0].selectedIndex).parent("li"),s+=":not(.ui-state-disabled)"),(s="first"===t||"last"===t?i["first"===t?"prevAll":"nextAll"](s).eq(-1):i[t+"All"](s).eq(0)).length&&this.menuInstance.focus(e,s)},_getSelectedItem:function(){return this.menuItems.eq(this.element[0].selectedIndex).parent("li")},_toggle:function(t){this[this.isOpen?"close":"open"](t)},_setSelection:function(){var t;this.range&&(window.getSelection?((t=window.getSelection()).removeAllRanges(),t.addRange(this.range)):this.range.select(),this.button.trigger("focus"))},_documentClick:{mousedown:function(t){this.isOpen&&(V(t.target).closest(".ui-selectmenu-menu, #"+V.escapeSelector(this.ids.button)).length||this.close(t))}},_buttonEvents:{mousedown:function(){var t;window.getSelection?(t=window.getSelection()).rangeCount&&(this.range=t.getRangeAt(0)):this.range=document.selection.createRange()},click:function(t){this._setSelection(),this._toggle(t)},keydown:function(t){var e=!0;switch(t.keyCode){case V.ui.keyCode.TAB:case V.ui.keyCode.ESCAPE:this.close(t),e=!1;break;case V.ui.keyCode.ENTER:this.isOpen&&this._selectFocusedItem(t);break;case V.ui.keyCode.UP:t.altKey?this._toggle(t):this._move("prev",t);break;case V.ui.keyCode.DOWN:t.altKey?this._toggle(t):this._move("next",t);break;case V.ui.keyCode.SPACE:this.isOpen?this._selectFocusedItem(t):this._toggle(t);break;case V.ui.keyCode.LEFT:this._move("prev",t);break;case V.ui.keyCode.RIGHT:this._move("next",t);break;case V.ui.keyCode.HOME:case V.ui.keyCode.PAGE_UP:this._move("first",t);break;case V.ui.keyCode.END:case V.ui.keyCode.PAGE_DOWN:this._move("last",t);break;default:this.menu.trigger(t),e=!1}e&&t.preventDefault()}},_selectFocusedItem:function(t){var e=this.menuItems.eq(this.focusIndex).parent("li");e.hasClass("ui-state-disabled")||this._select(e.data("ui-selectmenu-item"),t)},_select:function(t,e){var i=this.element[0].selectedIndex;this.element[0].selectedIndex=t.index,this.buttonItem.replaceWith(this.buttonItem=this._renderButtonItem(t)),this._setAria(t),this._trigger("select",e,{item:t}),t.index!==i&&this._trigger("change",e,{item:t}),this.close(e)},_setAria:function(t){t=this.menuItems.eq(t.index).attr("id");this.button.attr({"aria-labelledby":t,"aria-activedescendant":t}),this.menu.attr("aria-activedescendant",t)},_setOption:function(t,e){var i;"icons"===t&&(i=this.button.find("span.ui-icon"),this._removeClass(i,null,this.options.icons.button)._addClass(i,null,e.button)),this._super(t,e),"appendTo"===t&&this.menuWrap.appendTo(this._appendTo()),"width"===t&&this._resizeButton()},_setOptionDisabled:function(t){this._super(t),this.menuInstance.option("disabled",t),this.button.attr("aria-disabled",t),this._toggleClass(this.button,null,"ui-state-disabled",t),this.element.prop("disabled",t),t?(this.button.attr("tabindex",-1),this.close()):this.button.attr("tabindex",0)},_appendTo:function(){var t=this.options.appendTo;return t=!(t=!(t=t&&(t.jquery||t.nodeType?V(t):this.document.find(t).eq(0)))||!t[0]?this.element.closest(".ui-front, dialog"):t).length?this.document[0].body:t},_toggleAttr:function(){this.button.attr("aria-expanded",this.isOpen),this._removeClass(this.button,"ui-selectmenu-button-"+(this.isOpen?"closed":"open"))._addClass(this.button,"ui-selectmenu-button-"+(this.isOpen?"open":"closed"))._toggleClass(this.menuWrap,"ui-selectmenu-open",null,this.isOpen),this.menu.attr("aria-hidden",!this.isOpen)},_resizeButton:function(){var t=this.options.width;!1!==t?(null===t&&(t=this.element.show().outerWidth(),this.element.hide()),this.button.outerWidth(t)):this.button.css("width","")},_resizeMenu:function(){this.menu.outerWidth(Math.max(this.button.outerWidth(),this.menu.width("").outerWidth()+1))},_getCreateOptions:function(){var t=this._super();return t.disabled=this.element.prop("disabled"),t},_parseOptions:function(t){var i=this,s=[];t.each(function(t,e){e.hidden||s.push(i._parseOption(V(e),t))}),this.items=s},_parseOption:function(t,e){var i=t.parent("optgroup");return{element:t,index:e,value:t.val(),label:t.text(),optgroup:i.attr("label")||"",disabled:i.prop("disabled")||t.prop("disabled")}},_destroy:function(){this._unbindFormResetHandler(),this.menuWrap.remove(),this.button.remove(),this.element.show(),this.element.removeUniqueId(),this.labels.attr("for",this.ids.element)}}]),V.widget("ui.slider",V.ui.mouse,{version:"1.13.2",widgetEventPrefix:"slide",options:{animate:!1,classes:{"ui-slider":"ui-corner-all","ui-slider-handle":"ui-corner-all","ui-slider-range":"ui-corner-all ui-widget-header"},distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},numPages:5,_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this._calculateNewMax(),this._addClass("ui-slider ui-slider-"+this.orientation,"ui-widget ui-widget-content"),this._refresh(),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var t,e=this.options,i=this.element.find(".ui-slider-handle"),s=[],n=e.values&&e.values.length||1;for(i.length>n&&(i.slice(n).remove(),i=i.slice(0,n)),t=i.length;t<n;t++)s.push("<span tabindex='0'></span>");this.handles=i.add(V(s.join("")).appendTo(this.element)),this._addClass(this.handles,"ui-slider-handle","ui-state-default"),this.handle=this.handles.eq(0),this.handles.each(function(t){V(this).data("ui-slider-handle-index",t).attr("tabIndex",0)})},_createRange:function(){var t=this.options;t.range?(!0===t.range&&(t.values?t.values.length&&2!==t.values.length?t.values=[t.values[0],t.values[0]]:Array.isArray(t.values)&&(t.values=t.values.slice(0)):t.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?(this._removeClass(this.range,"ui-slider-range-min ui-slider-range-max"),this.range.css({left:"",bottom:""})):(this.range=V("<div>").appendTo(this.element),this._addClass(this.range,"ui-slider-range")),"min"!==t.range&&"max"!==t.range||this._addClass(this.range,"ui-slider-range-"+t.range)):(this.range&&this.range.remove(),this.range=null)},_setupEvents:function(){this._off(this.handles),this._on(this.handles,this._handleEvents),this._hoverable(this.handles),this._focusable(this.handles)},_destroy:function(){this.handles.remove(),this.range&&this.range.remove(),this._mouseDestroy()},_mouseCapture:function(t){var i,s,n,o,e,a,r=this,l=this.options;return!l.disabled&&(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),a={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(a),s=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var e=Math.abs(i-r.values(t));(e<s||s===e&&(t===r._lastChangedValue||r.values(t)===l.min))&&(s=e,n=V(this),o=t)}),!1!==this._start(t,o)&&(this._mouseSliding=!0,this._handleIndex=o,this._addClass(n,null,"ui-state-active"),n.trigger("focus"),e=n.offset(),a=!V(t.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=a?{left:0,top:0}:{left:t.pageX-e.left-n.width()/2,top:t.pageY-e.top-n.height()/2-(parseInt(n.css("borderTopWidth"),10)||0)-(parseInt(n.css("borderBottomWidth"),10)||0)+(parseInt(n.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,i),this._animateOff=!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},e=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,e),!1},_mouseStop:function(t){return this._removeClass(this.handles,null,"ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,t="horizontal"===this.orientation?(e=this.elementSize.width,t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),t=t/e;return(t=1<t?1:t)<0&&(t=0),"vertical"===this.orientation&&(t=1-t),e=this._valueMax()-this._valueMin(),e=this._valueMin()+t*e,this._trimAlignValue(e)},_uiHash:function(t,e,i){var s={handle:this.handles[t],handleIndex:t,value:void 0!==e?e:this.value()};return this._hasMultipleValues()&&(s.value=void 0!==e?e:this.values(t),s.values=i||this.values()),s},_hasMultipleValues:function(){return this.options.values&&this.options.values.length},_start:function(t,e){return this._trigger("start",t,this._uiHash(e))},_slide:function(t,e,i){var s,n=this.value(),o=this.values();this._hasMultipleValues()&&(s=this.values(e?0:1),n=this.values(e),2===this.options.values.length&&!0===this.options.range&&(i=0===e?Math.min(s,i):Math.max(s,i)),o[e]=i),i!==n&&!1!==this._trigger("slide",t,this._uiHash(e,i,o))&&(this._hasMultipleValues()?this.values(e,i):this.value(i))},_stop:function(t,e){this._trigger("stop",t,this._uiHash(e))},_change:function(t,e){this._keySliding||this._mouseSliding||(this._lastChangedValue=e,this._trigger("change",t,this._uiHash(e)))},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),void this._change(null,0)):this._value()},values:function(t,e){var i,s,n;if(1<arguments.length)return this.options.values[t]=this._trimAlignValue(e),this._refreshValue(),void this._change(null,t);if(!arguments.length)return this._values();if(!Array.isArray(t))return this._hasMultipleValues()?this._values(t):this.value();for(i=this.options.values,s=t,n=0;n<i.length;n+=1)i[n]=this._trimAlignValue(s[n]),this._change(null,n);this._refreshValue()},_setOption:function(t,e){var i,s=0;switch("range"===t&&!0===this.options.range&&("min"===e?(this.options.value=this._values(0),this.options.values=null):"max"===e&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),Array.isArray(this.options.values)&&(s=this.options.values.length),this._super(t,e),t){case"orientation":this._detectOrientation(),this._removeClass("ui-slider-horizontal ui-slider-vertical")._addClass("ui-slider-"+this.orientation),this._refreshValue(),this.options.range&&this._refreshRange(e),this.handles.css("horizontal"===e?"bottom":"left","");break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),i=s-1;0<=i;i--)this._change(null,i);this._animateOff=!1;break;case"step":case"min":case"max":this._animateOff=!0,this._calculateNewMax(),this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_setOptionDisabled:function(t){this._super(t),this._toggleClass(null,"ui-state-disabled",!!t)},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i;if(arguments.length)return t=this.options.values[t],t=this._trimAlignValue(t);if(this._hasMultipleValues()){for(e=this.options.values.slice(),i=0;i<e.length;i+=1)e[i]=this._trimAlignValue(e[i]);return e}return[]},_trimAlignValue:function(t){if(t<=this._valueMin())return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=0<this.options.step?this.options.step:1,i=(t-this._valueMin())%e,t=t-i;return 2*Math.abs(i)>=e&&(t+=0<i?e:-e),parseFloat(t.toFixed(5))},_calculateNewMax:function(){var t=this.options.max,e=this._valueMin(),i=this.options.step;(t=Math.round((t-e)/i)*i+e)>this.options.max&&(t-=i),this.max=parseFloat(t.toFixed(this._precision()))},_precision:function(){var t=this._precisionOf(this.options.step);return t=null!==this.options.min?Math.max(t,this._precisionOf(this.options.min)):t},_precisionOf:function(t){var e=t.toString(),t=e.indexOf(".");return-1===t?0:e.length-t-1},_valueMin:function(){return this.options.min},_valueMax:function(){return this.max},_refreshRange:function(t){"vertical"===t&&this.range.css({width:"",left:""}),"horizontal"===t&&this.range.css({height:"",bottom:""})},_refreshValue:function(){var e,i,t,s,n,o=this.options.range,a=this.options,r=this,l=!this._animateOff&&a.animate,h={};this._hasMultipleValues()?this.handles.each(function(t){i=(r.values(t)-r._valueMin())/(r._valueMax()-r._valueMin())*100,h["horizontal"===r.orientation?"left":"bottom"]=i+"%",V(this).stop(1,1)[l?"animate":"css"](h,a.animate),!0===r.options.range&&("horizontal"===r.orientation?(0===t&&r.range.stop(1,1)[l?"animate":"css"]({left:i+"%"},a.animate),1===t&&r.range[l?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:a.animate})):(0===t&&r.range.stop(1,1)[l?"animate":"css"]({bottom:i+"%"},a.animate),1===t&&r.range[l?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:a.animate}))),e=i}):(t=this.value(),s=this._valueMin(),n=this._valueMax(),i=n!==s?(t-s)/(n-s)*100:0,h["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[l?"animate":"css"](h,a.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:i+"%"},a.animate),"max"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:100-i+"%"},a.animate),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:i+"%"},a.animate),"max"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:100-i+"%"},a.animate))},_handleEvents:{keydown:function(t){var e,i,s,n=V(t.target).data("ui-slider-handle-index");switch(t.keyCode){case V.ui.keyCode.HOME:case V.ui.keyCode.END:case V.ui.keyCode.PAGE_UP:case V.ui.keyCode.PAGE_DOWN:case V.ui.keyCode.UP:case V.ui.keyCode.RIGHT:case V.ui.keyCode.DOWN:case V.ui.keyCode.LEFT:if(t.preventDefault(),!this._keySliding&&(this._keySliding=!0,this._addClass(V(t.target),null,"ui-state-active"),!1===this._start(t,n)))return}switch(s=this.options.step,e=i=this._hasMultipleValues()?this.values(n):this.value(),t.keyCode){case V.ui.keyCode.HOME:i=this._valueMin();break;case V.ui.keyCode.END:i=this._valueMax();break;case V.ui.keyCode.PAGE_UP:i=this._trimAlignValue(e+(this._valueMax()-this._valueMin())/this.numPages);break;case V.ui.keyCode.PAGE_DOWN:i=this._trimAlignValue(e-(this._valueMax()-this._valueMin())/this.numPages);break;case V.ui.keyCode.UP:case V.ui.keyCode.RIGHT:if(e===this._valueMax())return;i=this._trimAlignValue(e+s);break;case V.ui.keyCode.DOWN:case V.ui.keyCode.LEFT:if(e===this._valueMin())return;i=this._trimAlignValue(e-s)}this._slide(t,n,i)},keyup:function(t){var e=V(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,e),this._change(t,e),this._removeClass(V(t.target),null,"ui-state-active"))}}});function M(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}V.widget("ui.spinner",{version:"1.13.2",defaultElement:"<input>",widgetEventPrefix:"spin",options:{classes:{"ui-spinner":"ui-corner-all","ui-spinner-down":"ui-corner-br","ui-spinner-up":"ui-corner-tr"},culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),""!==this.value()&&this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var s=this._super(),n=this.element;return V.each(["min","max","step"],function(t,e){var i=n.attr(e);null!=i&&i.length&&(s[e]=i)}),s},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){this.cancelBlur?delete this.cancelBlur:(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t))},mousewheel:function(t,e){var i=V.ui.safeActiveElement(this.document[0]);if(this.element[0]===i&&e){if(!this.spinning&&!this._start(t))return!1;this._spin((0<e?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(t){var e;function i(){this.element[0]===V.ui.safeActiveElement(this.document[0])||(this.element.trigger("focus"),this.previous=e,this._delay(function(){this.previous=e}))}e=this.element[0]===V.ui.safeActiveElement(this.document[0])?this.previous:this.element.val(),t.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),!1!==this._start(t)&&this._repeat(null,V(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(V(t.currentTarget).hasClass("ui-state-active"))return!1!==this._start(t)&&void this._repeat(null,V(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_enhance:function(){this.uiSpinner=this.element.attr("autocomplete","off").wrap("<span>").parent().append("<a></a><a></a>")},_draw:function(){this._enhance(),this._addClass(this.uiSpinner,"ui-spinner","ui-widget ui-widget-content"),this._addClass("ui-spinner-input"),this.element.attr("role","spinbutton"),this.buttons=this.uiSpinner.children("a").attr("tabIndex",-1).attr("aria-hidden",!0).button({classes:{"ui-button":""}}),this._removeClass(this.buttons,"ui-corner-all"),this._addClass(this.buttons.first(),"ui-spinner-button ui-spinner-up"),this._addClass(this.buttons.last(),"ui-spinner-button ui-spinner-down"),this.buttons.first().button({icon:this.options.icons.up,showLabel:!1}),this.buttons.last().button({icon:this.options.icons.down,showLabel:!1}),this.buttons.height()>Math.ceil(.5*this.uiSpinner.height())&&0<this.uiSpinner.height()&&this.uiSpinner.height(this.uiSpinner.height())},_keydown:function(t){var e=this.options,i=V.ui.keyCode;switch(t.keyCode){case i.UP:return this._repeat(null,1,t),!0;case i.DOWN:return this._repeat(null,-1,t),!0;case i.PAGE_UP:return this._repeat(null,e.page,t),!0;case i.PAGE_DOWN:return this._repeat(null,-e.page,t),!0}return!1},_start:function(t){return!(!this.spinning&&!1===this._trigger("start",t))&&(this.counter||(this.counter=1),this.spinning=!0)},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&!1===this._trigger("spin",e,{value:i})||(this._value(i),this.counter++)},_increment:function(t){var e=this.options.incremental;return e?"function"==typeof e?e(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return t=null!==this.options.min?Math.max(t,this._precisionOf(this.options.min)):t},_precisionOf:function(t){var e=t.toString(),t=e.indexOf(".");return-1===t?0:e.length-t-1},_adjustValue:function(t){var e=this.options,i=null!==e.min?e.min:0,s=t-i;return t=i+Math.round(s/e.step)*e.step,t=parseFloat(t.toFixed(this._precision())),null!==e.max&&t>e.max?e.max:null!==e.min&&t<e.min?e.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){var i;if("culture"===t||"numberFormat"===t)return i=this._parse(this.element.val()),this.options[t]=e,void this.element.val(this._format(i));"max"!==t&&"min"!==t&&"step"!==t||"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(i=this.buttons.first().find(".ui-icon"),this._removeClass(i,null,this.options.icons.up),this._addClass(i,null,e.up),i=this.buttons.last().find(".ui-icon"),this._removeClass(i,null,this.options.icons.down),this._addClass(i,null,e.down)),this._super(t,e)},_setOptionDisabled:function(t){this._super(t),this._toggleClass(this.uiSpinner,null,"ui-state-disabled",!!t),this.element.prop("disabled",!!t),this.buttons.button(t?"disable":"enable")},_setOptions:M(function(t){this._super(t)}),_parse:function(t){return""===(t="string"==typeof t&&""!==t?window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t:t)||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},isValid:function(){var t=this.value();return null!==t&&t===this._adjustValue(t)},_value:function(t,e){var i;""!==t&&null!==(i=this._parse(t))&&(e||(i=this._adjustValue(i)),t=this._format(i)),this.element.val(t),this._refresh()},_destroy:function(){this.element.prop("disabled",!1).removeAttr("autocomplete role aria-valuemin aria-valuemax aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:M(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:M(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:M(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:M(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){if(!arguments.length)return this._parse(this.element.val());M(this._value).call(this,t)},widget:function(){return this.uiSpinner}}),!1!==V.uiBackCompat&&V.widget("ui.spinner",V.ui.spinner,{_enhance:function(){this.uiSpinner=this.element.attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml())},_uiSpinnerHtml:function(){return"<span>"},_buttonHtml:function(){return"<a></a><a></a>"}});var S;V.ui.spinner;V.widget("ui.tabs",{version:"1.13.2",delay:300,options:{active:null,classes:{"ui-tabs":"ui-corner-all","ui-tabs-nav":"ui-corner-all","ui-tabs-panel":"ui-corner-bottom","ui-tabs-tab":"ui-corner-top"},collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_isLocal:(S=/#.*$/,function(t){var e=t.href.replace(S,""),i=location.href.replace(S,"");try{e=decodeURIComponent(e)}catch(t){}try{i=decodeURIComponent(i)}catch(t){}return 1<t.hash.length&&e===i}),_create:function(){var e=this,t=this.options;this.running=!1,this._addClass("ui-tabs","ui-widget ui-widget-content"),this._toggleClass("ui-tabs-collapsible",null,t.collapsible),this._processTabs(),t.active=this._initialActive(),Array.isArray(t.disabled)&&(t.disabled=V.uniqueSort(t.disabled.concat(V.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),!1!==this.options.active&&this.anchors.length?this.active=this._findActive(t.active):this.active=V(),this._refresh(),this.active.length&&this.load(t.active)},_initialActive:function(){var i=this.options.active,t=this.options.collapsible,s=location.hash.substring(1);return null===i&&(s&&this.tabs.each(function(t,e){if(V(e).attr("aria-controls")===s)return i=t,!1}),null!==(i=null===i?this.tabs.index(this.tabs.filter(".ui-tabs-active")):i)&&-1!==i||(i=!!this.tabs.length&&0)),!1!==i&&-1===(i=this.tabs.index(this.tabs.eq(i)))&&(i=!t&&0),i=!t&&!1===i&&this.anchors.length?0:i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):V()}},_tabKeydown:function(t){var e=V(V.ui.safeActiveElement(this.document[0])).closest("li"),i=this.tabs.index(e),s=!0;if(!this._handlePageNav(t)){switch(t.keyCode){case V.ui.keyCode.RIGHT:case V.ui.keyCode.DOWN:i++;break;case V.ui.keyCode.UP:case V.ui.keyCode.LEFT:s=!1,i--;break;case V.ui.keyCode.END:i=this.anchors.length-1;break;case V.ui.keyCode.HOME:i=0;break;case V.ui.keyCode.SPACE:return t.preventDefault(),clearTimeout(this.activating),void this._activate(i);case V.ui.keyCode.ENTER:return t.preventDefault(),clearTimeout(this.activating),void this._activate(i!==this.options.active&&i);default:return}t.preventDefault(),clearTimeout(this.activating),i=this._focusNextTab(i,s),t.ctrlKey||t.metaKey||(e.attr("aria-selected","false"),this.tabs.eq(i).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",i)},this.delay))}},_panelKeydown:function(t){this._handlePageNav(t)||t.ctrlKey&&t.keyCode===V.ui.keyCode.UP&&(t.preventDefault(),this.active.trigger("focus"))},_handlePageNav:function(t){return t.altKey&&t.keyCode===V.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):t.altKey&&t.keyCode===V.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):void 0},_findNextTab:function(t,e){var i=this.tabs.length-1;for(;-1!==V.inArray(t=(t=i<t?0:t)<0?i:t,this.options.disabled);)t=e?t+1:t-1;return t},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).trigger("focus"),t},_setOption:function(t,e){"active"!==t?(this._super(t,e),"collapsible"===t&&(this._toggleClass("ui-tabs-collapsible",null,e),e||!1!==this.options.active||this._activate(0)),"event"===t&&this._setupEvents(e),"heightStyle"===t&&this._setupHeightStyle(e)):this._activate(e)},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,e=this.tablist.children(":has(a[href])");t.disabled=V.map(e.filter(".ui-state-disabled"),function(t){return e.index(t)}),this._processTabs(),!1!==t.active&&this.anchors.length?this.active.length&&!V.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=V()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active):(t.active=!1,this.active=V()),this._refresh()},_refresh:function(){this._setOptionDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false","aria-expanded":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-hidden":"true"}),this.active.length?(this.active.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0}),this._addClass(this.active,"ui-tabs-active","ui-state-active"),this._getPanelForTab(this.active).show().attr({"aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var l=this,t=this.tabs,e=this.anchors,i=this.panels;this.tablist=this._getList().attr("role","tablist"),this._addClass(this.tablist,"ui-tabs-nav","ui-helper-reset ui-helper-clearfix ui-widget-header"),this.tablist.on("mousedown"+this.eventNamespace,"> li",function(t){V(this).is(".ui-state-disabled")&&t.preventDefault()}).on("focus"+this.eventNamespace,".ui-tabs-anchor",function(){V(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this.tabs=this.tablist.find("> li:has(a[href])").attr({role:"tab",tabIndex:-1}),this._addClass(this.tabs,"ui-tabs-tab","ui-state-default"),this.anchors=this.tabs.map(function(){return V("a",this)[0]}).attr({tabIndex:-1}),this._addClass(this.anchors,"ui-tabs-anchor"),this.panels=V(),this.anchors.each(function(t,e){var i,s,n,o=V(e).uniqueId().attr("id"),a=V(e).closest("li"),r=a.attr("aria-controls");l._isLocal(e)?(n=(i=e.hash).substring(1),s=l.element.find(l._sanitizeSelector(i))):(n=a.attr("aria-controls")||V({}).uniqueId()[0].id,(s=l.element.find(i="#"+n)).length||(s=l._createPanel(n)).insertAfter(l.panels[t-1]||l.tablist),s.attr("aria-live","polite")),s.length&&(l.panels=l.panels.add(s)),r&&a.data("ui-tabs-aria-controls",r),a.attr({"aria-controls":n,"aria-labelledby":o}),s.attr("aria-labelledby",o)}),this.panels.attr("role","tabpanel"),this._addClass(this.panels,"ui-tabs-panel","ui-widget-content"),t&&(this._off(t.not(this.tabs)),this._off(e.not(this.anchors)),this._off(i.not(this.panels)))},_getList:function(){return this.tablist||this.element.find("ol, ul").eq(0)},_createPanel:function(t){return V("<div>").attr("id",t).data("ui-tabs-destroy",!0)},_setOptionDisabled:function(t){var e,i;for(Array.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1),i=0;e=this.tabs[i];i++)e=V(e),!0===t||-1!==V.inArray(i,t)?(e.attr("aria-disabled","true"),this._addClass(e,null,"ui-state-disabled")):(e.removeAttr("aria-disabled"),this._removeClass(e,null,"ui-state-disabled"));this.options.disabled=t,this._toggleClass(this.widget(),this.widgetFullName+"-disabled",null,!0===t)},_setupEvents:function(t){var i={};t&&V.each(t.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(!0,this.anchors,{click:function(t){t.preventDefault()}}),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var i,e=this.element.parent();"fill"===t?(i=e.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var t=V(this),e=t.css("position");"absolute"!==e&&"fixed"!==e&&(i-=t.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=V(this).outerHeight(!0)}),this.panels.each(function(){V(this).height(Math.max(0,i-V(this).innerHeight()+V(this).height()))}).css("overflow","auto")):"auto"===t&&(i=0,this.panels.each(function(){i=Math.max(i,V(this).height("").height())}).height(i))},_eventHandler:function(t){var e=this.options,i=this.active,s=V(t.currentTarget).closest("li"),n=s[0]===i[0],o=n&&e.collapsible,a=o?V():this._getPanelForTab(s),r=i.length?this._getPanelForTab(i):V(),i={oldTab:i,oldPanel:r,newTab:o?V():s,newPanel:a};t.preventDefault(),s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||n&&!e.collapsible||!1===this._trigger("beforeActivate",t,i)||(e.active=!o&&this.tabs.index(s),this.active=n?V():s,this.xhr&&this.xhr.abort(),r.length||a.length||V.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,i))},_toggle:function(t,e){var i=this,s=e.newPanel,n=e.oldPanel;function o(){i.running=!1,i._trigger("activate",t,e)}function a(){i._addClass(e.newTab.closest("li"),"ui-tabs-active","ui-state-active"),s.length&&i.options.show?i._show(s,i.options.show,o):(s.show(),o())}this.running=!0,n.length&&this.options.hide?this._hide(n,this.options.hide,function(){i._removeClass(e.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),a()}):(this._removeClass(e.oldTab.closest("li"),"ui-tabs-active","ui-state-active"),n.hide(),a()),n.attr("aria-hidden","true"),e.oldTab.attr({"aria-selected":"false","aria-expanded":"false"}),s.length&&n.length?e.oldTab.attr("tabIndex",-1):s.length&&this.tabs.filter(function(){return 0===V(this).attr("tabIndex")}).attr("tabIndex",-1),s.attr("aria-hidden","false"),e.newTab.attr({"aria-selected":"true","aria-expanded":"true",tabIndex:0})},_activate:function(t){var t=this._findActive(t);t[0]!==this.active[0]&&(t=(t=!t.length?this.active:t).find(".ui-tabs-anchor")[0],this._eventHandler({target:t,currentTarget:t,preventDefault:V.noop}))},_findActive:function(t){return!1===t?V():this.tabs.eq(t)},_getIndex:function(t){return t="string"==typeof t?this.anchors.index(this.anchors.filter("[href$='"+V.escapeSelector(t)+"']")):t},_destroy:function(){this.xhr&&this.xhr.abort(),this.tablist.removeAttr("role").off(this.eventNamespace),this.anchors.removeAttr("role tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){V.data(this,"ui-tabs-destroy")?V(this).remove():V(this).removeAttr("role tabIndex aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded")}),this.tabs.each(function(){var t=V(this),e=t.data("ui-tabs-aria-controls");e?t.attr("aria-controls",e).removeData("ui-tabs-aria-controls"):t.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var t=this.options.disabled;!1!==t&&(t=void 0!==i&&(i=this._getIndex(i),Array.isArray(t)?V.map(t,function(t){return t!==i?t:null}):V.map(this.tabs,function(t,e){return e!==i?e:null})),this._setOptionDisabled(t))},disable:function(t){var e=this.options.disabled;if(!0!==e){if(void 0===t)e=!0;else{if(t=this._getIndex(t),-1!==V.inArray(t,e))return;e=Array.isArray(e)?V.merge([t],e).sort():[t]}this._setOptionDisabled(e)}},load:function(t,s){t=this._getIndex(t);function n(t,e){"abort"===e&&o.panels.stop(!1,!0),o._removeClass(i,"ui-tabs-loading"),a.removeAttr("aria-busy"),t===o.xhr&&delete o.xhr}var o=this,i=this.tabs.eq(t),t=i.find(".ui-tabs-anchor"),a=this._getPanelForTab(i),r={tab:i,panel:a};this._isLocal(t[0])||(this.xhr=V.ajax(this._ajaxSettings(t,s,r)),this.xhr&&"canceled"!==this.xhr.statusText&&(this._addClass(i,"ui-tabs-loading"),a.attr("aria-busy","true"),this.xhr.done(function(t,e,i){setTimeout(function(){a.html(t),o._trigger("load",s,r),n(i,e)},1)}).fail(function(t,e){setTimeout(function(){n(t,e)},1)})))},_ajaxSettings:function(t,i,s){var n=this;return{url:t.attr("href").replace(/#.*$/,""),beforeSend:function(t,e){return n._trigger("beforeLoad",i,V.extend({jqXHR:t,ajaxSettings:e},s))}}},_getPanelForTab:function(t){t=V(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+t))}}),!1!==V.uiBackCompat&&V.widget("ui.tabs",V.ui.tabs,{_processTabs:function(){this._superApply(arguments),this._addClass(this.tabs,"ui-tab")}});V.ui.tabs;V.widget("ui.tooltip",{version:"1.13.2",options:{classes:{"ui-tooltip":"ui-corner-all ui-widget-shadow"},content:function(){var t=V(this).attr("title");return V("<a>").text(t).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,track:!1,close:null,open:null},_addDescribedBy:function(t,e){var i=(t.attr("aria-describedby")||"").split(/\s+/);i.push(e),t.data("ui-tooltip-id",e).attr("aria-describedby",String.prototype.trim.call(i.join(" ")))},_removeDescribedBy:function(t){var e=t.data("ui-tooltip-id"),i=(t.attr("aria-describedby")||"").split(/\s+/),e=V.inArray(e,i);-1!==e&&i.splice(e,1),t.removeData("ui-tooltip-id"),(i=String.prototype.trim.call(i.join(" ")))?t.attr("aria-describedby",i):t.removeAttr("aria-describedby")},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.liveRegion=V("<div>").attr({role:"log","aria-live":"assertive","aria-relevant":"additions"}).appendTo(this.document[0].body),this._addClass(this.liveRegion,null,"ui-helper-hidden-accessible"),this.disabledTitles=V([])},_setOption:function(t,e){var i=this;this._super(t,e),"content"===t&&V.each(this.tooltips,function(t,e){i._updateContent(e.element)})},_setOptionDisabled:function(t){this[t?"_disable":"_enable"]()},_disable:function(){var s=this;V.each(this.tooltips,function(t,e){var i=V.Event("blur");i.target=i.currentTarget=e.element[0],s.close(i,!0)}),this.disabledTitles=this.disabledTitles.add(this.element.find(this.options.items).addBack().filter(function(){var t=V(this);if(t.is("[title]"))return t.data("ui-tooltip-title",t.attr("title")).removeAttr("title")}))},_enable:function(){this.disabledTitles.each(function(){var t=V(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))}),this.disabledTitles=V([])},open:function(t){var i=this,e=V(t?t.target:this.element).closest(this.options.items);e.length&&!e.data("ui-tooltip-id")&&(e.attr("title")&&e.data("ui-tooltip-title",e.attr("title")),e.data("ui-tooltip-open",!0),t&&"mouseover"===t.type&&e.parents().each(function(){var t,e=V(this);e.data("ui-tooltip-open")&&((t=V.Event("blur")).target=t.currentTarget=this,i.close(t,!0)),e.attr("title")&&(e.uniqueId(),i.parents[this.id]={element:this,title:e.attr("title")},e.attr("title",""))}),this._registerCloseHandlers(t,e),this._updateContent(e,t))},_updateContent:function(e,i){var t=this.options.content,s=this,n=i?i.type:null;if("string"==typeof t||t.nodeType||t.jquery)return this._open(i,e,t);(t=t.call(e[0],function(t){s._delay(function(){e.data("ui-tooltip-open")&&(i&&(i.type=n),this._open(i,e,t))})}))&&this._open(i,e,t)},_open:function(t,e,i){var s,n,o,a=V.extend({},this.options.position);function r(t){a.of=t,n.is(":hidden")||n.position(a)}i&&((s=this._find(e))?s.tooltip.find(".ui-tooltip-content").html(i):(e.is("[title]")&&(t&&"mouseover"===t.type?e.attr("title",""):e.removeAttr("title")),s=this._tooltip(e),n=s.tooltip,this._addDescribedBy(e,n.attr("id")),n.find(".ui-tooltip-content").html(i),this.liveRegion.children().hide(),(i=V("<div>").html(n.find(".ui-tooltip-content").html())).removeAttr("name").find("[name]").removeAttr("name"),i.removeAttr("id").find("[id]").removeAttr("id"),i.appendTo(this.liveRegion),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:r}),r(t)):n.position(V.extend({of:e},this.options.position)),n.hide(),this._show(n,this.options.show),this.options.track&&this.options.show&&this.options.show.delay&&(o=this.delayedShow=setInterval(function(){n.is(":visible")&&(r(a.of),clearInterval(o))},13)),this._trigger("open",t,{tooltip:n})))},_registerCloseHandlers:function(t,e){var i={keyup:function(t){t.keyCode===V.ui.keyCode.ESCAPE&&((t=V.Event(t)).currentTarget=e[0],this.close(t,!0))}};e[0]!==this.element[0]&&(i.remove=function(){var t=this._find(e);t&&this._removeTooltip(t.tooltip)}),t&&"mouseover"!==t.type||(i.mouseleave="close"),t&&"focusin"!==t.type||(i.focusout="close"),this._on(!0,e,i)},close:function(t){var e,i=this,s=V(t?t.currentTarget:this.element),n=this._find(s);n?(e=n.tooltip,n.closing||(clearInterval(this.delayedShow),s.data("ui-tooltip-title")&&!s.attr("title")&&s.attr("title",s.data("ui-tooltip-title")),this._removeDescribedBy(s),n.hiding=!0,e.stop(!0),this._hide(e,this.options.hide,function(){i._removeTooltip(V(this))}),s.removeData("ui-tooltip-open"),this._off(s,"mouseleave focusout keyup"),s[0]!==this.element[0]&&this._off(s,"remove"),this._off(this.document,"mousemove"),t&&"mouseleave"===t.type&&V.each(this.parents,function(t,e){V(e.element).attr("title",e.title),delete i.parents[t]}),n.closing=!0,this._trigger("close",t,{tooltip:e}),n.hiding||(n.closing=!1))):s.removeData("ui-tooltip-open")},_tooltip:function(t){var e=V("<div>").attr("role","tooltip"),i=V("<div>").appendTo(e),s=e.uniqueId().attr("id");return this._addClass(i,"ui-tooltip-content"),this._addClass(e,"ui-tooltip","ui-widget ui-widget-content"),e.appendTo(this._appendTo(t)),this.tooltips[s]={element:t,tooltip:e}},_find:function(t){t=t.data("ui-tooltip-id");return t?this.tooltips[t]:null},_removeTooltip:function(t){clearInterval(this.delayedShow),t.remove(),delete this.tooltips[t.attr("id")]},_appendTo:function(t){t=t.closest(".ui-front, dialog");return t=!t.length?this.document[0].body:t},_destroy:function(){var s=this;V.each(this.tooltips,function(t,e){var i=V.Event("blur"),e=e.element;i.target=i.currentTarget=e[0],s.close(i,!0),V("#"+t).remove(),e.data("ui-tooltip-title")&&(e.attr("title")||e.attr("title",e.data("ui-tooltip-title")),e.removeData("ui-tooltip-title"))}),this.liveRegion.remove()}}),!1!==V.uiBackCompat&&V.widget("ui.tooltip",V.ui.tooltip,{options:{tooltipClass:null},_tooltip:function(){var t=this._superApply(arguments);return this.options.tooltipClass&&t.tooltip.addClass(this.options.tooltipClass),t}});V.ui.tooltip;var H=V,z={},A=z.toString,O=/^([\-+])=\s*(\d+\.?\d*)/,N=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16),t[4]?(parseInt(t[4],16)/255).toFixed(2):1]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16),t[4]?(parseInt(t[4]+t[4],16)/255).toFixed(2):1]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],E=H.Color=function(t,e,i,s){return new H.Color.fn.parse(t,e,i,s)},W={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},F={byte:{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},L=E.support={},R=H("<p>")[0],Y=H.each;function B(t){return null==t?t+"":"object"==typeof t?z[A.call(t)]||"object":typeof t}function j(t,e,i){var s=F[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:Math.min(s.max,Math.max(0,t)))}function q(s){var n=E(),o=n._rgba=[];return s=s.toLowerCase(),Y(N,function(t,e){var i=e.re.exec(s),i=i&&e.parse(i),e=e.space||"rgba";if(i)return i=n[e](i),n[W[e].cache]=i[W[e].cache],o=n._rgba=i._rgba,!1}),o.length?("0,0,0,0"===o.join()&&H.extend(o,st.transparent),n):st[s]}function K(t,e,i){return 6*(i=(i+1)%1)<1?t+(e-t)*i*6:2*i<1?e:3*i<2?t+(e-t)*(2/3-i)*6:t}R.style.cssText="background-color:rgba(1,1,1,.5)",L.rgba=-1<R.style.backgroundColor.indexOf("rgba"),Y(W,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),H.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(t,e){z["[object "+e+"]"]=e.toLowerCase()}),(E.fn=H.extend(E.prototype,{parse:function(n,t,e,i){if(void 0===n)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=H(n).css(t),t=void 0);var o=this,s=B(n),a=this._rgba=[];return void 0!==t&&(n=[n,t,e,i],s="array"),"string"===s?this.parse(q(n)||st._default):"array"===s?(Y(W.rgba.props,function(t,e){a[e.idx]=j(n[e.idx],e)}),this):"object"===s?(Y(W,n instanceof E?function(t,e){n[e.cache]&&(o[e.cache]=n[e.cache].slice())}:function(t,i){var s=i.cache;Y(i.props,function(t,e){if(!o[s]&&i.to){if("alpha"===t||null==n[t])return;o[s]=i.to(o._rgba)}o[s][e.idx]=j(n[t],e,!0)}),o[s]&&H.inArray(null,o[s].slice(0,3))<0&&(null==o[s][3]&&(o[s][3]=1),i.from&&(o._rgba=i.from(o[s])))}),this):void 0},is:function(t){var n=E(t),o=!0,a=this;return Y(W,function(t,e){var i,s=n[e.cache];return s&&(i=a[e.cache]||e.to&&e.to(a._rgba)||[],Y(e.props,function(t,e){if(null!=s[e.idx])return o=s[e.idx]===i[e.idx]})),o}),o},_space:function(){var i=[],s=this;return Y(W,function(t,e){s[e.cache]&&i.push(t)}),i.pop()},transition:function(t,a){var e=(h=E(t))._space(),i=W[e],t=0===this.alpha()?E("transparent"):this,r=t[i.cache]||i.to(t._rgba),l=r.slice(),h=h[i.cache];return Y(i.props,function(t,e){var i=e.idx,s=r[i],n=h[i],o=F[e.type]||{};null!==n&&(null===s?l[i]=n:(o.mod&&(n-s>o.mod/2?s+=o.mod:s-n>o.mod/2&&(s-=o.mod)),l[i]=j((n-s)*a+s,e)))}),this[e](l)},blend:function(t){if(1===this._rgba[3])return this;var e=this._rgba.slice(),i=e.pop(),s=E(t)._rgba;return E(H.map(e,function(t,e){return(1-i)*s[e]+i*t}))},toRgbaString:function(){var t="rgba(",e=H.map(this._rgba,function(t,e){return null!=t?t:2<e?1:0});return 1===e[3]&&(e.pop(),t="rgb("),t+e.join()+")"},toHslaString:function(){var t="hsla(",e=H.map(this.hsla(),function(t,e){return null==t&&(t=2<e?1:0),t=e&&e<3?Math.round(100*t)+"%":t});return 1===e[3]&&(e.pop(),t="hsl("),t+e.join()+")"},toHexString:function(t){var e=this._rgba.slice(),i=e.pop();return t&&e.push(~~(255*i)),"#"+H.map(e,function(t){return 1===(t=(t||0).toString(16)).length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}})).parse.prototype=E.fn,W.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/255,i=t[1]/255,s=t[2]/255,n=t[3],o=Math.max(e,i,s),a=Math.min(e,i,s),r=o-a,l=o+a,t=.5*l,i=a===o?0:e===o?60*(i-s)/r+360:i===o?60*(s-e)/r+120:60*(e-i)/r+240,l=0==r?0:t<=.5?r/l:r/(2-l);return[Math.round(i)%360,l,t,null==n?1:n]},W.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],t=t[3],i=s<=.5?s*(1+i):s+i-s*i,s=2*s-i;return[Math.round(255*K(s,i,e+1/3)),Math.round(255*K(s,i,e)),Math.round(255*K(s,i,e-1/3)),t]},Y(W,function(l,t){var e=t.props,o=t.cache,a=t.to,r=t.from;E.fn[l]=function(t){if(a&&!this[o]&&(this[o]=a(this._rgba)),void 0===t)return this[o].slice();var i=B(t),s="array"===i||"object"===i?t:arguments,n=this[o].slice();return Y(e,function(t,e){t=s["object"===i?t:e.idx];null==t&&(t=n[e.idx]),n[e.idx]=j(t,e)}),r?((t=E(r(n)))[o]=n,t):E(n)},Y(e,function(a,r){E.fn[a]||(E.fn[a]=function(t){var e,i=B(t),s="alpha"===a?this._hsla?"hsla":"rgba":l,n=this[s](),o=n[r.idx];return"undefined"===i?o:("function"===i&&(i=B(t=t.call(this,o))),null==t&&r.empty?this:("string"===i&&(e=O.exec(t))&&(t=o+parseFloat(e[2])*("+"===e[1]?1:-1)),n[r.idx]=t,this[s](n)))})})}),(E.hook=function(t){t=t.split(" ");Y(t,function(t,o){H.cssHooks[o]={set:function(t,e){var i,s,n="";if("transparent"!==e&&("string"!==B(e)||(i=q(e)))){if(e=E(i||e),!L.rgba&&1!==e._rgba[3]){for(s="backgroundColor"===o?t.parentNode:t;(""===n||"transparent"===n)&&s&&s.style;)try{n=H.css(s,"backgroundColor"),s=s.parentNode}catch(t){}e=e.blend(n&&"transparent"!==n?n:"_default")}e=e.toRgbaString()}try{t.style[o]=e}catch(t){}}},H.fx.step[o]=function(t){t.colorInit||(t.start=E(t.elem,o),t.end=E(t.end),t.colorInit=!0),H.cssHooks[o].set(t.elem,t.start.transition(t.end,t.pos))}})})("backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor"),H.cssHooks.borderColor={expand:function(i){var s={};return Y(["Top","Right","Bottom","Left"],function(t,e){s["border"+e+"Color"]=i}),s}};var U,X,$,G,Q,J,Z,tt,et,it,st=H.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"},nt="ui-effects-",ot="ui-effects-style",at="ui-effects-animated";function rt(t){var e,i,s=t.ownerDocument.defaultView?t.ownerDocument.defaultView.getComputedStyle(t,null):t.currentStyle,n={};if(s&&s.length&&s[0]&&s[s[0]])for(i=s.length;i--;)"string"==typeof s[e=s[i]]&&(n[e.replace(/-([\da-z])/gi,function(t,e){return e.toUpperCase()})]=s[e]);else for(e in s)"string"==typeof s[e]&&(n[e]=s[e]);return n}function lt(t,e,i,s){return t={effect:t=V.isPlainObject(t)?(e=t).effect:t},"function"==typeof(e=null==e?{}:e)&&(s=e,i=null,e={}),"number"!=typeof e&&!V.fx.speeds[e]||(s=i,i=e,e={}),"function"==typeof i&&(s=i,i=null),e&&V.extend(t,e),i=i||e.duration,t.duration=V.fx.off?0:"number"==typeof i?i:i in V.fx.speeds?V.fx.speeds[i]:V.fx.speeds._default,t.complete=s||e.complete,t}function ht(t){return!t||"number"==typeof t||V.fx.speeds[t]||("string"==typeof t&&!V.effects.effect[t]||("function"==typeof t||"object"==typeof t&&!t.effect))}function ct(t,e){var i=e.outerWidth(),e=e.outerHeight(),t=/^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/.exec(t)||["",0,i,e,0];return{top:parseFloat(t[1])||0,right:"auto"===t[2]?i:parseFloat(t[2]),bottom:"auto"===t[3]?e:parseFloat(t[3]),left:parseFloat(t[4])||0}}V.effects={effect:{}},G=["add","remove","toggle"],Q={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1},V.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,e){V.fx.step[e]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(H.style(t.elem,e,t.end),t.setAttr=!0)}}),V.fn.addBack||(V.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),V.effects.animateClass=function(n,t,e,i){var o=V.speed(t,e,i);return this.queue(function(){var i=V(this),t=i.attr("class")||"",e=(e=o.children?i.find("*").addBack():i).map(function(){return{el:V(this),start:rt(this)}}),s=function(){V.each(G,function(t,e){n[e]&&i[e+"Class"](n[e])})};s(),e=e.map(function(){return this.end=rt(this.el[0]),this.diff=function(t,e){var i,s,n={};for(i in e)s=e[i],t[i]!==s&&(Q[i]||!V.fx.step[i]&&isNaN(parseFloat(s))||(n[i]=s));return n}(this.start,this.end),this}),i.attr("class",t),e=e.map(function(){var t=this,e=V.Deferred(),i=V.extend({},o,{queue:!1,complete:function(){e.resolve(t)}});return this.el.animate(this.diff,i),e.promise()}),V.when.apply(V,e.get()).done(function(){s(),V.each(arguments,function(){var e=this.el;V.each(this.diff,function(t){e.css(t,"")})}),o.complete.call(i[0])})})},V.fn.extend({addClass:($=V.fn.addClass,function(t,e,i,s){return e?V.effects.animateClass.call(this,{add:t},e,i,s):$.apply(this,arguments)}),removeClass:(X=V.fn.removeClass,function(t,e,i,s){return 1<arguments.length?V.effects.animateClass.call(this,{remove:t},e,i,s):X.apply(this,arguments)}),toggleClass:(U=V.fn.toggleClass,function(t,e,i,s,n){return"boolean"==typeof e||void 0===e?i?V.effects.animateClass.call(this,e?{add:t}:{remove:t},i,s,n):U.apply(this,arguments):V.effects.animateClass.call(this,{toggle:t},e,i,s)}),switchClass:function(t,e,i,s,n){return V.effects.animateClass.call(this,{add:e,remove:t},i,s,n)}}),V.expr&&V.expr.pseudos&&V.expr.pseudos.animated&&(V.expr.pseudos.animated=(J=V.expr.pseudos.animated,function(t){return!!V(t).data(at)||J(t)})),!1!==V.uiBackCompat&&V.extend(V.effects,{save:function(t,e){for(var i=0,s=e.length;i<s;i++)null!==e[i]&&t.data(nt+e[i],t[0].style[e[i]])},restore:function(t,e){for(var i,s=0,n=e.length;s<n;s++)null!==e[s]&&(i=t.data(nt+e[s]),t.css(e[s],i))},setMode:function(t,e){return e="toggle"===e?t.is(":hidden")?"show":"hide":e},createWrapper:function(i){if(i.parent().is(".ui-effects-wrapper"))return i.parent();var s={width:i.outerWidth(!0),height:i.outerHeight(!0),float:i.css("float")},t=V("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),e={width:i.width(),height:i.height()},n=document.activeElement;try{n.id}catch(t){n=document.body}return i.wrap(t),i[0]!==n&&!V.contains(i[0],n)||V(n).trigger("focus"),t=i.parent(),"static"===i.css("position")?(t.css({position:"relative"}),i.css({position:"relative"})):(V.extend(s,{position:i.css("position"),zIndex:i.css("z-index")}),V.each(["top","left","bottom","right"],function(t,e){s[e]=i.css(e),isNaN(parseInt(s[e],10))&&(s[e]="auto")}),i.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),i.css(e),t.css(s).show()},removeWrapper:function(t){var e=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),t[0]!==e&&!V.contains(t[0],e)||V(e).trigger("focus")),t}}),V.extend(V.effects,{version:"1.13.2",define:function(t,e,i){return i||(i=e,e="effect"),V.effects.effect[t]=i,V.effects.effect[t].mode=e,i},scaledDimensions:function(t,e,i){if(0===e)return{height:0,width:0,outerHeight:0,outerWidth:0};var s="horizontal"!==i?(e||100)/100:1,e="vertical"!==i?(e||100)/100:1;return{height:t.height()*e,width:t.width()*s,outerHeight:t.outerHeight()*e,outerWidth:t.outerWidth()*s}},clipToBox:function(t){return{width:t.clip.right-t.clip.left,height:t.clip.bottom-t.clip.top,left:t.clip.left,top:t.clip.top}},unshift:function(t,e,i){var s=t.queue();1<e&&s.splice.apply(s,[1,0].concat(s.splice(e,i))),t.dequeue()},saveStyle:function(t){t.data(ot,t[0].style.cssText)},restoreStyle:function(t){t[0].style.cssText=t.data(ot)||"",t.removeData(ot)},mode:function(t,e){t=t.is(":hidden");return"toggle"===e&&(e=t?"show":"hide"),e=(t?"hide"===e:"show"===e)?"none":e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createPlaceholder:function(t){var e,i=t.css("position"),s=t.position();return t.css({marginTop:t.css("marginTop"),marginBottom:t.css("marginBottom"),marginLeft:t.css("marginLeft"),marginRight:t.css("marginRight")}).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()),/^(static|relative)/.test(i)&&(i="absolute",e=V("<"+t[0].nodeName+">").insertAfter(t).css({display:/^(inline|ruby)/.test(t.css("display"))?"inline-block":"block",visibility:"hidden",marginTop:t.css("marginTop"),marginBottom:t.css("marginBottom"),marginLeft:t.css("marginLeft"),marginRight:t.css("marginRight"),float:t.css("float")}).outerWidth(t.outerWidth()).outerHeight(t.outerHeight()).addClass("ui-effects-placeholder"),t.data(nt+"placeholder",e)),t.css({position:i,left:s.left,top:s.top}),e},removePlaceholder:function(t){var e=nt+"placeholder",i=t.data(e);i&&(i.remove(),t.removeData(e))},cleanUp:function(t){V.effects.restoreStyle(t),V.effects.removePlaceholder(t)},setTransition:function(s,t,n,o){return o=o||{},V.each(t,function(t,e){var i=s.cssUnit(e);0<i[0]&&(o[e]=i[0]*n+i[1])}),o}}),V.fn.extend({effect:function(){function t(t){var e=V(this),i=V.effects.mode(e,r)||o;e.data(at,!0),l.push(i),o&&("show"===i||i===o&&"hide"===i)&&e.show(),o&&"none"===i||V.effects.saveStyle(e),"function"==typeof t&&t()}var s=lt.apply(this,arguments),n=V.effects.effect[s.effect],o=n.mode,e=s.queue,i=e||"fx",a=s.complete,r=s.mode,l=[];return V.fx.off||!n?r?this[r](s.duration,a):this.each(function(){a&&a.call(this)}):!1===e?this.each(t).each(h):this.queue(i,t).queue(i,h);function h(t){var e=V(this);function i(){"function"==typeof a&&a.call(e[0]),"function"==typeof t&&t()}s.mode=l.shift(),!1===V.uiBackCompat||o?"none"===s.mode?(e[r](),i()):n.call(e[0],s,function(){e.removeData(at),V.effects.cleanUp(e),"hide"===s.mode&&e.hide(),i()}):(e.is(":hidden")?"hide"===r:"show"===r)?(e[r](),i()):n.call(e[0],s,i)}},show:(et=V.fn.show,function(t){if(ht(t))return et.apply(this,arguments);t=lt.apply(this,arguments);return t.mode="show",this.effect.call(this,t)}),hide:(tt=V.fn.hide,function(t){if(ht(t))return tt.apply(this,arguments);t=lt.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)}),toggle:(Z=V.fn.toggle,function(t){if(ht(t)||"boolean"==typeof t)return Z.apply(this,arguments);t=lt.apply(this,arguments);return t.mode="toggle",this.effect.call(this,t)}),cssUnit:function(t){var i=this.css(t),s=[];return V.each(["em","px","%","pt"],function(t,e){0<i.indexOf(e)&&(s=[parseFloat(i),e])}),s},cssClip:function(t){return t?this.css("clip","rect("+t.top+"px "+t.right+"px "+t.bottom+"px "+t.left+"px)"):ct(this.css("clip"),this)},transfer:function(t,e){var i=V(this),s=V(t.to),n="fixed"===s.css("position"),o=V("body"),a=n?o.scrollTop():0,r=n?o.scrollLeft():0,o=s.offset(),o={top:o.top-a,left:o.left-r,height:s.innerHeight(),width:s.innerWidth()},s=i.offset(),l=V("<div class='ui-effects-transfer'></div>");l.appendTo("body").addClass(t.className).css({top:s.top-a,left:s.left-r,height:i.innerHeight(),width:i.innerWidth(),position:n?"fixed":"absolute"}).animate(o,t.duration,t.easing,function(){l.remove(),"function"==typeof e&&e()})}}),V.fx.step.clip=function(t){t.clipInit||(t.start=V(t.elem).cssClip(),"string"==typeof t.end&&(t.end=ct(t.end,t.elem)),t.clipInit=!0),V(t.elem).cssClip({top:t.pos*(t.end.top-t.start.top)+t.start.top,right:t.pos*(t.end.right-t.start.right)+t.start.right,bottom:t.pos*(t.end.bottom-t.start.bottom)+t.start.bottom,left:t.pos*(t.end.left-t.start.left)+t.start.left})},it={},V.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,t){it[t]=function(t){return Math.pow(t,e+2)}}),V.extend(it,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;t<((e=Math.pow(2,--i))-1)/11;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),V.each(it,function(t,e){V.easing["easeIn"+t]=e,V.easing["easeOut"+t]=function(t){return 1-e(1-t)},V.easing["easeInOut"+t]=function(t){return t<.5?e(2*t)/2:1-e(-2*t+2)/2}});R=V.effects,V.effects.define("blind","hide",function(t,e){var i={up:["bottom","top"],vertical:["bottom","top"],down:["top","bottom"],left:["right","left"],horizontal:["right","left"],right:["left","right"]},s=V(this),n=t.direction||"up",o=s.cssClip(),a={clip:V.extend({},o)},r=V.effects.createPlaceholder(s);a.clip[i[n][0]]=a.clip[i[n][1]],"show"===t.mode&&(s.cssClip(a.clip),r&&r.css(V.effects.clipToBox(a)),a.clip=o),r&&r.animate(V.effects.clipToBox(a),t.duration,t.easing),s.animate(a,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("bounce",function(t,e){var i,s,n=V(this),o=t.mode,a="hide"===o,r="show"===o,l=t.direction||"up",h=t.distance,c=t.times||5,o=2*c+(r||a?1:0),u=t.duration/o,d=t.easing,p="up"===l||"down"===l?"top":"left",f="up"===l||"left"===l,g=0,t=n.queue().length;for(V.effects.createPlaceholder(n),l=n.css(p),h=h||n["top"==p?"outerHeight":"outerWidth"]()/3,r&&((s={opacity:1})[p]=l,n.css("opacity",0).css(p,f?2*-h:2*h).animate(s,u,d)),a&&(h/=Math.pow(2,c-1)),(s={})[p]=l;g<c;g++)(i={})[p]=(f?"-=":"+=")+h,n.animate(i,u,d).animate(s,u,d),h=a?2*h:h/2;a&&((i={opacity:0})[p]=(f?"-=":"+=")+h,n.animate(i,u,d)),n.queue(e),V.effects.unshift(n,t,1+o)}),V.effects.define("clip","hide",function(t,e){var i={},s=V(this),n=t.direction||"vertical",o="both"===n,a=o||"horizontal"===n,o=o||"vertical"===n,n=s.cssClip();i.clip={top:o?(n.bottom-n.top)/2:n.top,right:a?(n.right-n.left)/2:n.right,bottom:o?(n.bottom-n.top)/2:n.bottom,left:a?(n.right-n.left)/2:n.left},V.effects.createPlaceholder(s),"show"===t.mode&&(s.cssClip(i.clip),i.clip=n),s.animate(i,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("drop","hide",function(t,e){var i=V(this),s="show"===t.mode,n=t.direction||"left",o="up"===n||"down"===n?"top":"left",a="up"===n||"left"===n?"-=":"+=",r="+="==a?"-=":"+=",l={opacity:0};V.effects.createPlaceholder(i),n=t.distance||i["top"==o?"outerHeight":"outerWidth"](!0)/2,l[o]=a+n,s&&(i.css(l),l[o]=r+n,l.opacity=1),i.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("explode","hide",function(t,e){var i,s,n,o,a,r,l=t.pieces?Math.round(Math.sqrt(t.pieces)):3,h=l,c=V(this),u="show"===t.mode,d=c.show().css("visibility","hidden").offset(),p=Math.ceil(c.outerWidth()/h),f=Math.ceil(c.outerHeight()/l),g=[];function m(){g.push(this),g.length===l*h&&(c.css({visibility:"visible"}),V(g).remove(),e())}for(i=0;i<l;i++)for(o=d.top+i*f,r=i-(l-1)/2,s=0;s<h;s++)n=d.left+s*p,a=s-(h-1)/2,c.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-s*p,top:-i*f}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:p,height:f,left:n+(u?a*p:0),top:o+(u?r*f:0),opacity:u?0:1}).animate({left:n+(u?0:a*p),top:o+(u?0:r*f),opacity:u?1:0},t.duration||500,t.easing,m)}),V.effects.define("fade","toggle",function(t,e){var i="show"===t.mode;V(this).css("opacity",i?0:1).animate({opacity:i?1:0},{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("fold","hide",function(e,t){var i=V(this),s=e.mode,n="show"===s,o="hide"===s,a=e.size||15,r=/([0-9]+)%/.exec(a),l=!!e.horizFirst?["right","bottom"]:["bottom","right"],h=e.duration/2,c=V.effects.createPlaceholder(i),u=i.cssClip(),d={clip:V.extend({},u)},p={clip:V.extend({},u)},f=[u[l[0]],u[l[1]]],s=i.queue().length;r&&(a=parseInt(r[1],10)/100*f[o?0:1]),d.clip[l[0]]=a,p.clip[l[0]]=a,p.clip[l[1]]=0,n&&(i.cssClip(p.clip),c&&c.css(V.effects.clipToBox(p)),p.clip=u),i.queue(function(t){c&&c.animate(V.effects.clipToBox(d),h,e.easing).animate(V.effects.clipToBox(p),h,e.easing),t()}).animate(d,h,e.easing).animate(p,h,e.easing).queue(t),V.effects.unshift(i,s,4)}),V.effects.define("highlight","show",function(t,e){var i=V(this),s={backgroundColor:i.css("backgroundColor")};"hide"===t.mode&&(s.opacity=0),V.effects.saveStyle(i),i.css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(s,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),V.effects.define("size",function(s,e){var n,i=V(this),t=["fontSize"],o=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],a=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],r=s.mode,l="effect"!==r,h=s.scale||"both",c=s.origin||["middle","center"],u=i.css("position"),d=i.position(),p=V.effects.scaledDimensions(i),f=s.from||p,g=s.to||V.effects.scaledDimensions(i,0);V.effects.createPlaceholder(i),"show"===r&&(r=f,f=g,g=r),n={from:{y:f.height/p.height,x:f.width/p.width},to:{y:g.height/p.height,x:g.width/p.width}},"box"!==h&&"both"!==h||(n.from.y!==n.to.y&&(f=V.effects.setTransition(i,o,n.from.y,f),g=V.effects.setTransition(i,o,n.to.y,g)),n.from.x!==n.to.x&&(f=V.effects.setTransition(i,a,n.from.x,f),g=V.effects.setTransition(i,a,n.to.x,g))),"content"!==h&&"both"!==h||n.from.y!==n.to.y&&(f=V.effects.setTransition(i,t,n.from.y,f),g=V.effects.setTransition(i,t,n.to.y,g)),c&&(c=V.effects.getBaseline(c,p),f.top=(p.outerHeight-f.outerHeight)*c.y+d.top,f.left=(p.outerWidth-f.outerWidth)*c.x+d.left,g.top=(p.outerHeight-g.outerHeight)*c.y+d.top,g.left=(p.outerWidth-g.outerWidth)*c.x+d.left),delete f.outerHeight,delete f.outerWidth,i.css(f),"content"!==h&&"both"!==h||(o=o.concat(["marginTop","marginBottom"]).concat(t),a=a.concat(["marginLeft","marginRight"]),i.find("*[width]").each(function(){var t=V(this),e=V.effects.scaledDimensions(t),i={height:e.height*n.from.y,width:e.width*n.from.x,outerHeight:e.outerHeight*n.from.y,outerWidth:e.outerWidth*n.from.x},e={height:e.height*n.to.y,width:e.width*n.to.x,outerHeight:e.height*n.to.y,outerWidth:e.width*n.to.x};n.from.y!==n.to.y&&(i=V.effects.setTransition(t,o,n.from.y,i),e=V.effects.setTransition(t,o,n.to.y,e)),n.from.x!==n.to.x&&(i=V.effects.setTransition(t,a,n.from.x,i),e=V.effects.setTransition(t,a,n.to.x,e)),l&&V.effects.saveStyle(t),t.css(i),t.animate(e,s.duration,s.easing,function(){l&&V.effects.restoreStyle(t)})})),i.animate(g,{queue:!1,duration:s.duration,easing:s.easing,complete:function(){var t=i.offset();0===g.opacity&&i.css("opacity",f.opacity),l||(i.css("position","static"===u?"relative":u).offset(t),V.effects.saveStyle(i)),e()}})}),V.effects.define("scale",function(t,e){var i=V(this),s=t.mode,s=parseInt(t.percent,10)||(0===parseInt(t.percent,10)||"effect"!==s?0:100),s=V.extend(!0,{from:V.effects.scaledDimensions(i),to:V.effects.scaledDimensions(i,s,t.direction||"both"),origin:t.origin||["middle","center"]},t);t.fade&&(s.from.opacity=1,s.to.opacity=0),V.effects.effect.size.call(this,s,e)}),V.effects.define("puff","hide",function(t,e){t=V.extend(!0,{},t,{fade:!0,percent:parseInt(t.percent,10)||150});V.effects.effect.scale.call(this,t,e)}),V.effects.define("pulsate","show",function(t,e){var i=V(this),s=t.mode,n="show"===s,o=2*(t.times||5)+(n||"hide"===s?1:0),a=t.duration/o,r=0,l=1,s=i.queue().length;for(!n&&i.is(":visible")||(i.css("opacity",0).show(),r=1);l<o;l++)i.animate({opacity:r},a,t.easing),r=1-r;i.animate({opacity:r},a,t.easing),i.queue(e),V.effects.unshift(i,s,1+o)}),V.effects.define("shake",function(t,e){var i=1,s=V(this),n=t.direction||"left",o=t.distance||20,a=t.times||3,r=2*a+1,l=Math.round(t.duration/r),h="up"===n||"down"===n?"top":"left",c="up"===n||"left"===n,u={},d={},p={},n=s.queue().length;for(V.effects.createPlaceholder(s),u[h]=(c?"-=":"+=")+o,d[h]=(c?"+=":"-=")+2*o,p[h]=(c?"-=":"+=")+2*o,s.animate(u,l,t.easing);i<a;i++)s.animate(d,l,t.easing).animate(p,l,t.easing);s.animate(d,l,t.easing).animate(u,l/2,t.easing).queue(e),V.effects.unshift(s,n,1+r)}),V.effects.define("slide","show",function(t,e){var i,s,n=V(this),o={up:["bottom","top"],down:["top","bottom"],left:["right","left"],right:["left","right"]},a=t.mode,r=t.direction||"left",l="up"===r||"down"===r?"top":"left",h="up"===r||"left"===r,c=t.distance||n["top"==l?"outerHeight":"outerWidth"](!0),u={};V.effects.createPlaceholder(n),i=n.cssClip(),s=n.position()[l],u[l]=(h?-1:1)*c+s,u.clip=n.cssClip(),u.clip[o[r][1]]=u.clip[o[r][0]],"show"===a&&(n.cssClip(u.clip),n.css(l,u[l]),u.clip=i,u[l]=s),n.animate(u,{queue:!1,duration:t.duration,easing:t.easing,complete:e})}),!1!==V.uiBackCompat&&V.effects.define("transfer",function(t,e){V(this).transfer(t,e)})}); \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/assets/js/jquery.cleditor-1.4.5.min.js b/vendor/mikespub/php-epub-meta/assets/js/jquery.cleditor-1.4.5.min.js
new file mode 100644
index 000000000..64fb2dfed
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/js/jquery.cleditor-1.4.5.min.js
@@ -0,0 +1,11 @@
+/*!
+ CLEditor WYSIWYG HTML Editor v1.4.5
+ http://premiumsoftware.net/CLEditor
+ requires jQuery v1.4.2 or later
+ Copyright 2010, Chris Landowski, Premium Software, LLC
+ Dual licensed under the MIT or GPL Version 2 licenses.
+*/
+(function(n){function vi(t){var i=this,e=t.target,y=n.data(e,a),p=s[y],w=p.popupName,k=f[w],v,b;if(!i.disabled&&n(e).attr(r)!==r){if(v={editor:i,button:e,buttonName:y,popup:k,popupName:w,command:p.command,useCSS:i.options.useCSS},p.buttonClick&&p.buttonClick(t,v)===!1)return!1;if(y==="source")l(i)?(delete i.range,i.$area.hide(),i.$frame.show(),e.title=p.title):(i.$frame.hide(),i.$area.show(),e.title="Show Rich Text");else if(!l(i)){if(w){if(b=n(k),w==="url"){if(y==="link"&&ri(i)==="")return ut(i,"A selection is required when inserting a link.",e),!1;b.children(":button").unbind(u).bind(u,function(){var t=b.find(":text"),r=n.trim(t.val());r!==""&&h(i,v.command,r,null,v.button);t.val("http://");o();c(i)})}else w==="pastetext"&&b.children(":button").unbind(u).bind(u,function(){var n=b.find("textarea"),t=n.val().replace(/\n/g,"<br />");t!==""&&h(i,v.command,t,null,v.button);n.val("");o();c(i)});return e!==n.data(k,d)?(ui(i,k,e),!1):void 0}if(y==="print")i.$frame[0].contentWindow.print();else if(!h(i,v.command,v.value,v.useCSS,e))return!1}c(i)}}function kt(t){var i=n(t.target).closest("div");i.css(et,i.data(a)?"#FFF":"#FFC")}function dt(t){n(t.target).closest("div").css(et,"transparent")}function yi(i){var v=this,y=i.data.popup,r=i.target,l;if(y!==f.msg&&!n(y).hasClass(tt)){var w=n.data(y,d),u=n.data(w,a),p=s[u],b=p.command,e,k=v.options.useCSS;if(u==="font"?e=r.style.fontFamily.replace(/"/g,""):u==="size"?(r.tagName.toUpperCase()==="DIV"&&(r=r.children[0]),e=r.innerHTML):u==="style"?e="<"+r.tagName+">":u==="color"?e=ti(r.style.backgroundColor):u==="highlight"&&(e=ti(r.style.backgroundColor),t?b="backcolor":k=!0),l={editor:v,button:w,buttonName:u,popup:y,popupName:p.popupName,command:b,value:e,useCSS:k},!p.popupClick||p.popupClick(i,l)!==!1){if(l.command&&!h(v,l.command,l.value,l.useCSS,w))return!1;o();c(v)}}}function it(n){for(var t=1,i=0,r=0;r<n.length;++r)t=(t+n.charCodeAt(r))%65521,i=(i+t)%65521;return i<<16|t}function pi(n){n.$area.val("");ft(n)}function gt(r,u,e,o,s){var h,c;return f[r]?f[r]:(h=n(i).hide().addClass(si).appendTo("body"),o?h.html(o):r==="color"?(c=u.colors.split(" "),c.length<10&&h.width("auto"),n.each(c,function(t,r){n(i).appendTo(h).css(et,"#"+r)}),e=hi):r==="font"?n.each(u.fonts.split(","),function(t,r){n(i).appendTo(h).css("fontFamily",r).html(r)}):r==="size"?n.each(u.sizes.split(","),function(t,r){n(i).appendTo(h).html('<font size="'+r+'">'+r+"<\/font>")}):r==="style"?n.each(u.styles,function(t,r){n(i).appendTo(h).html(r[1]+r[0]+r[1].replace("<","<\/"))}):r==="url"?(h.html('<label>Enter URL:<br /><input type="text" value="http://" style="width:200px" /><\/label><br /><input type="button" value="Submit" />'),e=tt):r==="pastetext"&&(h.html('<label>Paste your content here:<br /><textarea rows="3" style="width:200px"><\/textarea><\/label><br /><input type="button" value="Submit" />'),e=tt),e||o||(e=pt),h.addClass(e),t&&h.attr(ot,"on").find("div,font,p,h1,h2,h3,h4,h5,h6").attr(ot,"on"),(h.hasClass(pt)||s===!0)&&h.children().hover(kt,dt),f[r]=h[0],h[0])}function ni(n,i){i?(n.$area.attr(r,r),n.disabled=!0):(n.$area.removeAttr(r),delete n.disabled);try{t?n.doc.body.contentEditable=!i:n.doc.designMode=i?"off":"on"}catch(u){}b(n)}function h(n,i,r,u,f){var c,h,o,s,l;if(rt(n),t||((u===undefined||u===null)&&(u=n.options.useCSS),n.doc.execCommand("styleWithCSS",0,u.toString())),c=i.toLowerCase()==="inserthtml",t&&c)w(n).pasteHTML(r);else if(y&&c)h=e(n),o=h.getRangeAt(0),o.deleteContents(),o.insertNode(o.createContextualFragment(r)),h.removeAllRanges(),h.addRange(o);else{s=!0;try{s=n.doc.execCommand(i,0,r||null)}catch(a){l=a.message;s=!1}s||("cutcopypaste".indexOf(i)>-1?ut(n,"For security reasons, your browser does not support the "+i+" command. Try using the keyboard shortcut or context menu instead.",f):ut(n,l?l:"Error executing the "+i+" command.",f))}return b(n),ct(n,!0),s}function c(n){setTimeout(function(){l(n)?n.$area.focus():n.$frame[0].contentWindow.focus();b(n)},0)}function w(n){return t?e(n).createRange():e(n).getRangeAt(0)}function e(n){return t?n.doc.selection:n.$frame[0].contentWindow.getSelection()}function ti(n){var i=/rgba?\((\d+), (\d+), (\d+)/.exec(n),t;if(i){for(n=(i[1]<<16|i[2]<<8|i[3]).toString(16);n.length<6;)n="0"+n;return"#"+n}return(t=n.split(""),n.length===4)?"#"+t[1]+t[1]+t[2]+t[2]+t[3]+t[3]:n}function o(){n.each(f,function(t,i){n(i).hide().unbind(u).removeData(d)})}function ii(){var t=n("link[href*=cleditor]").attr("href");return t.replace(/^(.*\/)[^\/]+$/,"$1")+"images/"}function wi(n){return"url("+ii()+n+")"}function ht(i){var s=i.$main,r=i.options;i.$frame&&i.$frame.remove();var u=i.$frame=n('<iframe frameborder="0" src="javascript:true;" />').hide().appendTo(s),l=u[0].contentWindow,f=i.doc=l.document,h=n(f);f.open();f.write(r.docType+"<html>"+(r.docCSSFile===""?"":'<head><link rel="stylesheet" type="text/css" href="'+r.docCSSFile+'" /><\/head>')+'<body style="'+r.bodyStyle+'"><\/body><\/html>');f.close();(t||y)&&h.click(function(){c(i)});ft(i);t||y?(h.bind("beforedeactivate beforeactivate selectionchange keypress keyup",function(n){if(n.type==="beforedeactivate")i.inactive=!0;else if(n.type==="beforeactivate")!i.inactive&&i.range&&i.range.length>1&&i.range.shift(),delete i.inactive;else if(!i.inactive)for(i.range||(i.range=[]),i.range.unshift(w(i));i.range.length>2;)i.range.pop()}),u.focus(function(){rt(i);n(i).triggerHandler(nt)}),u.blur(function(){n(i).triggerHandler(k)})):n(u[0].contentWindow).focus(function(){n(i).triggerHandler(nt)}).blur(function(){n(i).triggerHandler(k)});h.click(o).keydown(function(n){t&&e(i).type=="Control"&&n.keyCode==8&&(e(i).clear(),n.preventDefault())}).bind("keyup mouseup",function(){b(i);ct(i,!0)});st?i.$area.show():u.show();n(function(){var t=i.$toolbar,f=t.children("div:last"),e=s.width(),n=f.offset().top+f.outerHeight()-t.offset().top+1;t.height(n);n=(/%/.test(""+r.height)?s.height():parseInt(r.height,10))-n;u.width(e).height(n);i.$area.width(e).height(li?n-2:n);ni(i,i.disabled);b(i)})}function b(i){var u,e;st||!ai||i.focused||(i.$frame[0].contentWindow.focus(),window.focus(),i.focused=!0);u=i.doc;t&&(u=w(i));e=l(i);n.each(i.$toolbar.find("."+vt),function(o,s){var v=n(s),h=n.cleditor.buttons[n.data(s,a)],c=h.command,l=!0,p;if(i.disabled)l=!1;else if(h.getEnabled)p={editor:i,button:s,buttonName:h.name,popup:f[h.popupName],popupName:h.popupName,command:h.command,useCSS:i.options.useCSS},l=h.getEnabled(p),l===undefined&&(l=!0);else if((e||st)&&h.name!=="source"||t&&(c==="undo"||c==="redo"))l=!1;else if(c&&c!=="print"&&(t&&c==="hilitecolor"&&(c="backcolor"),!t&&!y||c!=="inserthtml"))try{l=u.queryCommandEnabled(c)}catch(w){l=!1}l?(v.removeClass(yt),v.removeAttr(r)):(v.addClass(yt),v.attr(r,r))})}function rt(n){n.range&&(t?n.range[0].select():y&&e(n).addRange(n.range[0]))}function bi(n){setTimeout(function(){l(n)?n.$area.select():h(n,"selectall")},0)}function ki(i){var u,r,f;return(rt(i),u=w(i),t)?u.htmlText:(r=n("<layer>")[0],r.appendChild(u.cloneContents()),f=r.innerHTML,r=null,f)}function ri(n){return(rt(n),t)?w(n).text:e(n).toString()}function ut(n,t,i){var r=gt("msg",n.options,ci);r.innerHTML=t;ui(n,r,i)}function ui(t,i,r){var f,h,c,e=n(i),l,s;r?(l=n(r),f=l.offset(),h=--f.left,c=f.top+l.height()):(s=t.$toolbar,f=s.offset(),h=Math.floor((s.width()-e.width())/2)+f.left,c=f.top+s.height()-2);o();e.css({left:h,top:c}).show();r&&(n.data(i,d,r),e.bind(u,{popup:i},n.proxy(yi,t)));setTimeout(function(){e.find(":text,textarea").eq(0).focus().select()},100)}function l(n){return n.$area.is(":visible")}function ft(t,i){var u=t.$area.val(),o=t.options,f=o.updateFrame,s=n(t.doc.body),e,r;if(f){if(e=it(u),i&&t.areaChecksum===e)return;t.areaChecksum=e}r=f?f(u):u;r=r.replace(/<(?=\/?script)/ig,"&lt;");o.updateTextArea&&(t.frameChecksum=it(r));r!==s.html()&&(s.html(r),n(t).triggerHandler(g))}function ct(t,i){var u=n(t.doc.body).html(),o=t.options,f=o.updateTextArea,s=t.$area,e,r;if(f){if(e=it(u),i&&t.frameChecksum===e)return;t.frameChecksum=e}r=f?f(u):u;o.updateFrame&&(t.areaChecksum=it(r));r!==s.val()&&(s.val(r),n(t).triggerHandler(g))}var p,bt;n.cleditor={defaultOptions:{width:"auto",height:250,controls:"bold italic underline strikethrough subscript superscript | font size style | color highlight removeformat | bullets numbering | outdent indent | alignleft center alignright justify | undo redo | rule image link unlink | cut copy paste pastetext | print source",colors:"FFF FCC FC9 FF9 FFC 9F9 9FF CFF CCF FCF CCC F66 F96 FF6 FF3 6F9 3FF 6FF 99F F9F BBB F00 F90 FC6 FF0 3F3 6CC 3CF 66C C6C 999 C00 F60 FC3 FC0 3C0 0CC 36F 63F C3C 666 900 C60 C93 990 090 399 33F 60C 939 333 600 930 963 660 060 366 009 339 636 000 300 630 633 330 030 033 006 309 303",fonts:"Arial,Arial Black,Comic Sans MS,Courier New,Narrow,Garamond,Georgia,Impact,Sans Serif,Serif,Tahoma,Trebuchet MS,Verdana",sizes:"1,2,3,4,5,6,7",styles:[["Paragraph","<p>"],["Header 1","<h1>"],["Header 2","<h2>"],["Header 3","<h3>"],["Header 4","<h4>"],["Header 5","<h5>"],["Header 6","<h6>"]],useCSS:!0,docType:'<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',docCSSFile:"",bodyStyle:"margin:4px; font:10pt Arial,Verdana; cursor:text"},buttons:{init:"bold,,|italic,,|underline,,|strikethrough,,|subscript,,|superscript,,|font,,fontname,|size,Font Size,fontsize,|style,,formatblock,|color,Font Color,forecolor,|highlight,Text Highlight Color,hilitecolor,color|removeformat,Remove Formatting,|bullets,,insertunorderedlist|numbering,,insertorderedlist|outdent,,|indent,,|alignleft,Align Text Left,justifyleft|center,,justifycenter|alignright,Align Text Right,justifyright|justify,,justifyfull|undo,,|redo,,|rule,Insert Horizontal Rule,inserthorizontalrule|image,Insert Image,insertimage,url|link,Insert Hyperlink,createlink,url|unlink,Remove Hyperlink,|cut,,|copy,,|paste,,|pastetext,Paste as Text,inserthtml,|print,,|source,Show Source"},imagesPath:function(){return ii()}};n.fn.cleditor=function(t){var i=n([]);return this.each(function(r,u){if(u.tagName.toUpperCase()==="TEXTAREA"){var f=n.data(u,lt);f||(f=new cleditor(u,t));i=i.add(f)}}),i};var et="backgroundColor",k="blurred",d="button",a="buttonName",g="change",lt="cleditor",u="click",r="disabled",i="<div>",nt="focused",ot="unselectable",fi="cleditorMain",ei="cleditorToolbar",at="cleditorGroup",vt="cleditorButton",yt="cleditorDisabled",oi="cleditorDivider",si="cleditorPopup",pt="cleditorList",hi="cleditorColor",tt="cleditorPrompt",ci="cleditorMsg",v=navigator.userAgent.toLowerCase(),t=/msie/.test(v),li=/msie\s6/.test(v),y=/(trident)(?:.*rv:([\w.]+))?/.test(v),ai=/webkit/.test(v),st=/iPhone|iPad|iPod/i.test(v),f={},wt,s=n.cleditor.buttons;n.each(s.init.split("|"),function(n,t){var i=t.split(","),r=i[0];s[r]={stripIndex:n,name:r,title:i[1]===""?r.charAt(0).toUpperCase()+r.substr(1):i[1],command:i[2]===""?r:i[2],popupName:i[3]===""?r:i[3]}});delete s.init;cleditor=function(r,f){var e=this;e.options=f=n.extend({},n.cleditor.defaultOptions,f);var l=e.$area=n(r).css({border:"none",margin:0,padding:0}).hide().data(lt,e).blur(function(){ft(e,!0)}),v=e.$main=n(i).addClass(fi).width(f.width).height(f.height),y=e.$toolbar=n(i).addClass(ei).appendTo(v),h=n(i).addClass(at).appendTo(y),c=0;n.each(f.controls.split(" "),function(r,o){var w,l,p,v;if(o==="")return!0;o==="|"?(w=n(i).addClass(oi).appendTo(h),h.width(c+1),c=0,h=n(i).addClass(at).appendTo(y)):(l=s[o],p=n(i).data(a,l.name).addClass(vt).attr("title",l.title).bind(u,n.proxy(vi,e)).appendTo(h).hover(kt,dt),c+=24,h.width(c+1),v={},l.css?v=l.css:l.image&&(v.backgroundImage=wi(l.image)),l.stripIndex&&(v.backgroundPosition=l.stripIndex*-24),p.css(v),t&&p.attr(ot,"on"),l.popupName&&gt(l.popupName,f,l.popupClass,l.popupContent,l.popupHover))});v.insertBefore(l).append(l);wt||(n(document).click(function(t){var i=n(t.target);i.add(i.parents()).is("."+tt)||o()}),wt=!0);/auto|%/.test(""+f.width+f.height)&&n(window).bind("resize.cleditor",function(){ht(e)});ht(e)};p=cleditor.prototype;bt=[["clear",pi],["disable",ni],["execCommand",h],["focus",c],["hidePopups",o],["sourceMode",l,!0],["refresh",ht],["select",bi],["selectedHTML",ki,!0],["selectedText",ri,!0],["showMessage",ut],["updateFrame",ft],["updateTextArea",ct]];n.each(bt,function(n,t){p[t[0]]=function(){for(var u,n=this,r=[n],i=0;i<arguments.length;i++)r.push(arguments[i]);return(u=t[1].apply(n,r),t[2])?u:n}});p.blurred=function(t){var i=n(this);return t?i.bind(k,t):i.trigger(k)};p.change=function(t){var i=n(this);return t?i.bind(g,t):i.trigger(g)};p.focused=function(t){var i=n(this);return t?i.bind(nt,t):i.trigger(nt)}})(jQuery);
+/*
+//# sourceMappingURL=jquery.cleditor.min.js.map
+*/ \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/assets/js/script.js b/vendor/mikespub/php-epub-meta/assets/js/script.js
new file mode 100644
index 000000000..cf8b3f2a1
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/assets/js/script.js
@@ -0,0 +1,194 @@
+
+var bookapi = {
+ $dialog: null,
+
+ resulttpl:
+ '<div class="result">' +
+ ' <img src="" />'+
+ ' <div>' +
+ ' <div class="buttons">' +
+ ' <button class="btn-repl">replace</button><br />' +
+ ' <button class="btn-fill">fill in</button>' +
+ ' </div>' +
+ ' <h1 class="title"></h1>' +
+ ' <p class="authors"></p>' +
+ ' <p class="description"></p>' +
+ ' <p class="more">' +
+ ' <span class="lang"></span>' +
+ ' <span class="publisher"></span>' +
+ ' <span class="subjects"></span>' +
+ ' </p>' +
+ ' </div>' +
+ '</div>',
+
+ init: function(){
+ $('body').append('<div id="bookapi"></div>');
+ bookapi.$dialog = $('#bookapi');
+ bookapi.$dialog.dialog(
+ {
+ autoOpen: false,
+ title: 'Lookup Book Data',
+ width: 800,
+ height: 500
+ }
+ );
+ bookapi.$dialog.append('<div class="head">Lookup: <input type="text" id="bookapi-q" /></div>')
+ .append('<div id="bookapi-out"></div>');
+ bookapi.$out = $('#bookapi-out');
+
+ $('#bookpanel').append('<a href="#" id="bookapi-s">Lookup Book Data</a>');
+ $('#bookapi-s').attr('title','Search this book at Google Books');
+ $('#bookapi-s').click(bookapi.open);
+
+ $('#bookapi-q').keypress(
+ function(event){
+ if(event.which == 13){
+ event.preventDefault();
+ bookapi.search();
+ }
+ });
+
+ },
+
+ open: function(){
+ bookapi.$dialog.dialog('open');
+
+ var query = $('#bookpanel input[name=title]').val();
+ $('#bookapi-q').val(query);
+
+ bookapi.search();
+ },
+
+ search: function(){
+ bookapi.$out.html('please wait...');
+ $.ajax({
+ type: 'GET',
+ data: {'api':$('#bookapi-q').val()},
+ success: bookapi.searchdone,
+ dataType: 'json'
+ });
+ },
+
+ searchdone: function(data){
+ if(data.totalItems == 0){
+ bookapi.$out.html('Found no results.<br />Try adjusting the query and retry.');
+ return;
+ }
+
+ bookapi.$out.html('');
+ for(i=0; i<data.items.length; i++){
+ $res = $(bookapi.resulttpl);
+ if(data.items[i].volumeInfo.title)
+ $res.find('.title').html(data.items[i].volumeInfo.title);
+ if(data.items[i].volumeInfo.authors)
+ $res.find('.authors').html(data.items[i].volumeInfo.authors.join(', '));
+ if(data.items[i].volumeInfo.description)
+ $res.find('.description').html(data.items[i].volumeInfo.description);
+ if(data.items[i].volumeInfo.language)
+ $res.find('.lang').html('['+data.items[i].volumeInfo.language+']');
+ if(data.items[i].volumeInfo.publisher)
+ $res.find('.publisher').html(data.items[i].volumeInfo.publisher);
+ if(data.items[i].volumeInfo.categories)
+ $res.find('.subjects').html(data.items[i].volumeInfo.categories.join(', '));
+ if(data.items[i].volumeInfo.imageLinks)
+ if(data.items[i].volumeInfo.imageLinks.thumbnail)
+ $res.find('img').attr('src',data.items[i].volumeInfo.imageLinks.thumbnail);
+
+ $res.find('.btn-repl').click(data.items[i].volumeInfo,bookapi.replace);
+ $res.find('.btn-fill').click(data.items[i].volumeInfo,bookapi.fillin);
+
+ bookapi.$out.append($res);
+ }
+ },
+
+ replace: function(event){
+ item = event.data;
+ if(item.title)
+ $('#bookpanel input[name=title]').val(item.title);
+ if(item.description)
+ $('#bookpanel textarea[name=description]').val(item.description);
+ $wysiwyg[0].updateFrame();
+ if(item.language)
+ $('#bookpanel input[name=language]').val(item.language);
+ if(item.publisher)
+ $('#bookpanel input[name=publisher]').val(item.publisher);
+ if(item.categories)
+ $('#bookpanel input[name=subjects]').val(item.categories.join(', '));
+ if(item.imageLinks){
+ $('#bookpanel input[name=coverurl]').val(item.imageLinks.thumbnail);
+ $('#cover').attr('src',item.imageLinks.thumbnail);
+ }
+ bookapi.$dialog.dialog('close');
+ },
+
+ fillin: function(event){
+ item = event.data;
+
+ if(item.title && $('#bookpanel input[name=title]').val() == '')
+ $('#bookpanel input[name=title]').val(item.title);
+ if(item.description && $('#bookpanel textarea[name=description]').val() == '')
+ $('#bookpanel textarea[name=description]').val(item.description);
+ $wysiwyg[0].updateFrame();
+ if(item.language && $('#bookpanel input[name=language]').val() == '')
+ $('#bookpanel input[name=language]').val(item.language);
+ if(item.publisher && $('#bookpanel input[name=publisher]').val() == '')
+ $('#bookpanel input[name=publisher]').val(item.publisher);
+ if(item.categories && $('#bookpanel input[name=subjects]').val() == '')
+ $('#bookpanel input[name=subjects]').val(item.categories.join(', '));
+ if(item.imageLinks && $('#cover').hasClass('noimg')){
+ $('#bookpanel input[name=coverurl]').val(item.imageLinks.thumbnail);
+ $('#cover').attr('src',item.imageLinks.thumbnail);
+ }
+ bookapi.$dialog.dialog('close');
+ }
+
+};
+
+var author = {
+ init: function(){
+ $button = $(document.createElement('a'));
+ $button.text('+').attr('href','#');
+ $button.attr('title','add another author line');
+ $button.click(author.add);
+ $button.addClass('addauthor');
+
+ $td = $('#authors');
+ $td.append($button);
+ },
+
+ add: function(){
+ $td = $('#authors');
+
+ $ps = $td.find('p');
+ $new = $ps.first().clone();
+ $new.find('input').first().attr('name','authorname['+$ps.length+']').val('');
+ $new.find('input').last().attr('name','authoras['+$ps.length+']').val('');
+
+ $ps.last().after($new);
+ }
+};
+
+var $wysiwg = null;
+$(function(){
+ bookapi.init();
+ author.init();
+
+ // scroll to currently selected book
+ $current = $('#booklist li.active');
+ if($current.length){
+ $current[0].scrollIntoView();
+ }
+
+ // initialize the WYSIWYG editor
+ $wysiwyg = $('textarea').cleditor({
+ width: 450,
+ controls: // controls to add to the toolbar
+ "bold italic underline strikethrough | " +
+ "style removeformat | bullets numbering | " +
+ "alignleft center alignright justify | undo redo | " +
+ "link unlink | source",
+ styles: // styles in the style popup
+ [["Paragraph", "<p>"], ["Header 1", "<h1>"], ["Header 2", "<h2>"],
+ ["Header 3", "<h3>"], ["Header 4","<h4>"], ["Header 5","<h5>"]]
+ });
+});
diff --git a/vendor/mikespub/php-epub-meta/composer.json b/vendor/mikespub/php-epub-meta/composer.json
new file mode 100644
index 000000000..2904fec70
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/composer.json
@@ -0,0 +1,46 @@
+{
+ "name": "mikespub/php-epub-meta",
+ "type": "library",
+ "description": "Reading and writing metadata included in the EPub ebook format",
+ "keywords": ["epub", "metadata", "ebook"],
+ "homepage": "https://github.com/mikespub-org/php-epub-meta",
+ "authors": [
+ {
+ "name": "Andreas Gohr",
+ "email": "andi@splitbrain.org",
+ "homepage": "https://www.splitbrain.org/",
+ "role": "Developer"
+ },
+ {
+ "name": "Sébastien Lucas",
+ "email": "sebastien@slucas.fr",
+ "homepage": "http://www.slucas.fr/",
+ "role": "Developer"
+ },
+ {
+ "name": "mikespub",
+ "homepage": "https://github.com/mikespub-org/php-epub-meta",
+ "role": "Developer"
+ }
+ ],
+ "license": "MIT",
+ "require": {
+ "php": ">=8.1",
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-zip": "*",
+ "ext-zlib": "*",
+ "maennchen/zipstream-php": "^3.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.5"
+ },
+ "suggest": {
+ "mikespub/seblucas-cops": "COPS - Calibre OPDS (and HTML) PHP Server",
+ "mikespub/epub-loader": "epub-loader is a utility resource for ebooks"
+ },
+ "autoload": {
+ "classmap": ["src/"]
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/composer.lock b/vendor/mikespub/php-epub-meta/composer.lock
new file mode 100644
index 000000000..924b5ac37
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/composer.lock
@@ -0,0 +1,1732 @@
+{
+ "_readme": [
+ "This file locks the dependencies of your project to a known state",
+ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
+ "This file is @generated automatically"
+ ],
+ "content-hash": "970529a0cf0853d895d4c863e3ca1a33",
+ "packages": [
+ {
+ "name": "maennchen/zipstream-php",
+ "version": "3.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/maennchen/ZipStream-PHP.git",
+ "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/maennchen/ZipStream-PHP/zipball/b8174494eda667f7d13876b4a7bfef0f62a7c0d1",
+ "reference": "b8174494eda667f7d13876b4a7bfef0f62a7c0d1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "ext-zlib": "*",
+ "php-64bit": "^8.1"
+ },
+ "require-dev": {
+ "ext-zip": "*",
+ "friendsofphp/php-cs-fixer": "^3.16",
+ "guzzlehttp/guzzle": "^7.5",
+ "mikey179/vfsstream": "^1.6",
+ "php-coveralls/php-coveralls": "^2.5",
+ "phpunit/phpunit": "^10.0",
+ "vimeo/psalm": "^5.0"
+ },
+ "suggest": {
+ "guzzlehttp/psr7": "^2.4",
+ "psr/http-message": "^2.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "ZipStream\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Paul Duncan",
+ "email": "pabs@pablotron.org"
+ },
+ {
+ "name": "Jonatan Männchen",
+ "email": "jonatan@maennchen.ch"
+ },
+ {
+ "name": "Jesse Donat",
+ "email": "donatj@gmail.com"
+ },
+ {
+ "name": "András Kolesár",
+ "email": "kolesar@kolesar.hu"
+ }
+ ],
+ "description": "ZipStream is a library for dynamically streaming dynamic zip files from PHP without writing to the disk at all on the server.",
+ "keywords": [
+ "stream",
+ "zip"
+ ],
+ "support": {
+ "issues": "https://github.com/maennchen/ZipStream-PHP/issues",
+ "source": "https://github.com/maennchen/ZipStream-PHP/tree/3.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/maennchen",
+ "type": "github"
+ },
+ {
+ "url": "https://opencollective.com/zipstream",
+ "type": "open_collective"
+ }
+ ],
+ "time": "2023-06-21T14:59:35+00:00"
+ }
+ ],
+ "packages-dev": [
+ {
+ "name": "myclabs/deep-copy",
+ "version": "1.12.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/myclabs/DeepCopy.git",
+ "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
+ "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1 || ^8.0"
+ },
+ "conflict": {
+ "doctrine/collections": "<1.6.8",
+ "doctrine/common": "<2.13.3 || >=3 <3.2.2"
+ },
+ "require-dev": {
+ "doctrine/collections": "^1.6.8",
+ "doctrine/common": "^2.13.3 || ^3.2.2",
+ "phpspec/prophecy": "^1.10",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/DeepCopy/deep_copy.php"
+ ],
+ "psr-4": {
+ "DeepCopy\\": "src/DeepCopy/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Create deep copies (clones) of your objects",
+ "keywords": [
+ "clone",
+ "copy",
+ "duplicate",
+ "object",
+ "object graph"
+ ],
+ "support": {
+ "issues": "https://github.com/myclabs/DeepCopy/issues",
+ "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0"
+ },
+ "funding": [
+ {
+ "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-06-12T14:39:25+00:00"
+ },
+ {
+ "name": "nikic/php-parser",
+ "version": "v5.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/nikic/PHP-Parser.git",
+ "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1",
+ "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1",
+ "shasum": ""
+ },
+ "require": {
+ "ext-ctype": "*",
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "php": ">=7.4"
+ },
+ "require-dev": {
+ "ircmaxell/php-yacc": "^0.0.7",
+ "phpunit/phpunit": "^9.0"
+ },
+ "bin": [
+ "bin/php-parse"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "PhpParser\\": "lib/PhpParser"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Nikita Popov"
+ }
+ ],
+ "description": "A PHP parser written in PHP",
+ "keywords": [
+ "parser",
+ "php"
+ ],
+ "support": {
+ "issues": "https://github.com/nikic/PHP-Parser/issues",
+ "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0"
+ },
+ "time": "2024-07-01T20:03:41+00:00"
+ },
+ {
+ "name": "phar-io/manifest",
+ "version": "2.0.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/manifest.git",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176",
+ "reference": "54750ef60c58e43759730615a392c31c80e23176",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-phar": "*",
+ "ext-xmlwriter": "*",
+ "phar-io/version": "^3.0.1",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "2.0.x-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)",
+ "support": {
+ "issues": "https://github.com/phar-io/manifest/issues",
+ "source": "https://github.com/phar-io/manifest/tree/2.0.4"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-03T12:33:53+00:00"
+ },
+ {
+ "name": "phar-io/version",
+ "version": "3.2.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phar-io/version.git",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Heuer",
+ "email": "sebastian@phpeople.de",
+ "role": "Developer"
+ },
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "Library for handling version information and constraints",
+ "support": {
+ "issues": "https://github.com/phar-io/version/issues",
+ "source": "https://github.com/phar-io/version/tree/3.2.1"
+ },
+ "time": "2022-02-21T01:04:05+00:00"
+ },
+ {
+ "name": "phpunit/php-code-coverage",
+ "version": "10.1.15",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
+ "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae",
+ "reference": "5da8b1728acd1e6ffdf2ff32ffbdfd04307f26ae",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-libxml": "*",
+ "ext-xmlwriter": "*",
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "php": ">=8.1",
+ "phpunit/php-file-iterator": "^4.0",
+ "phpunit/php-text-template": "^3.0",
+ "sebastian/code-unit-reverse-lookup": "^3.0",
+ "sebastian/complexity": "^3.0",
+ "sebastian/environment": "^6.0",
+ "sebastian/lines-of-code": "^2.0",
+ "sebastian/version": "^4.0",
+ "theseer/tokenizer": "^1.2.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.1"
+ },
+ "suggest": {
+ "ext-pcov": "PHP extension that provides line coverage",
+ "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "10.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.",
+ "homepage": "https://github.com/sebastianbergmann/php-code-coverage",
+ "keywords": [
+ "coverage",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
+ "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.15"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-06-29T08:25:15+00:00"
+ },
+ {
+ "name": "phpunit/php-file-iterator",
+ "version": "4.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c",
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "FilterIterator implementation that filters files based on a list of suffixes.",
+ "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
+ "keywords": [
+ "filesystem",
+ "iterator"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
+ "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-08-31T06:24:48+00:00"
+ },
+ {
+ "name": "phpunit/php-invoker",
+ "version": "4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-invoker.git",
+ "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
+ "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "ext-pcntl": "*",
+ "phpunit/phpunit": "^10.0"
+ },
+ "suggest": {
+ "ext-pcntl": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Invoke callables with a timeout",
+ "homepage": "https://github.com/sebastianbergmann/php-invoker/",
+ "keywords": [
+ "process"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-invoker/issues",
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:56:09+00:00"
+ },
+ {
+ "name": "phpunit/php-text-template",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-text-template.git",
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748",
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Simple template engine.",
+ "homepage": "https://github.com/sebastianbergmann/php-text-template/",
+ "keywords": [
+ "template"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-text-template/issues",
+ "security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-08-31T14:07:24+00:00"
+ },
+ {
+ "name": "phpunit/php-timer",
+ "version": "6.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/php-timer.git",
+ "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d",
+ "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Utility class for timing",
+ "homepage": "https://github.com/sebastianbergmann/php-timer/",
+ "keywords": [
+ "timer"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/php-timer/issues",
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:57:52+00:00"
+ },
+ {
+ "name": "phpunit/phpunit",
+ "version": "10.5.30",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/phpunit.git",
+ "reference": "b15524febac0153876b4ba9aab3326c2ee94c897"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b15524febac0153876b4ba9aab3326c2ee94c897",
+ "reference": "b15524febac0153876b4ba9aab3326c2ee94c897",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-json": "*",
+ "ext-libxml": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-xmlwriter": "*",
+ "myclabs/deep-copy": "^1.12.0",
+ "phar-io/manifest": "^2.0.4",
+ "phar-io/version": "^3.2.1",
+ "php": ">=8.1",
+ "phpunit/php-code-coverage": "^10.1.15",
+ "phpunit/php-file-iterator": "^4.1.0",
+ "phpunit/php-invoker": "^4.0.0",
+ "phpunit/php-text-template": "^3.0.1",
+ "phpunit/php-timer": "^6.0.0",
+ "sebastian/cli-parser": "^2.0.1",
+ "sebastian/code-unit": "^2.0.0",
+ "sebastian/comparator": "^5.0.2",
+ "sebastian/diff": "^5.1.1",
+ "sebastian/environment": "^6.1.0",
+ "sebastian/exporter": "^5.1.2",
+ "sebastian/global-state": "^6.0.2",
+ "sebastian/object-enumerator": "^5.0.0",
+ "sebastian/recursion-context": "^5.0.0",
+ "sebastian/type": "^4.0.0",
+ "sebastian/version": "^4.0.1"
+ },
+ "suggest": {
+ "ext-soap": "To be able to generate mocks based on WSDL files"
+ },
+ "bin": [
+ "phpunit"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "10.5-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/Framework/Assert/Functions.php"
+ ],
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "The PHP Unit Testing framework.",
+ "homepage": "https://phpunit.de/",
+ "keywords": [
+ "phpunit",
+ "testing",
+ "xunit"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/phpunit/issues",
+ "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.30"
+ },
+ "funding": [
+ {
+ "url": "https://phpunit.de/sponsors.html",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2024-08-13T06:09:37+00:00"
+ },
+ {
+ "name": "sebastian/cli-parser",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/cli-parser.git",
+ "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084",
+ "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for parsing CLI options",
+ "homepage": "https://github.com/sebastianbergmann/cli-parser",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/cli-parser/issues",
+ "security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-02T07:12:49+00:00"
+ },
+ {
+ "name": "sebastian/code-unit",
+ "version": "2.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit.git",
+ "reference": "a81fee9eef0b7a76af11d121767abc44c104e503"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503",
+ "reference": "a81fee9eef0b7a76af11d121767abc44c104e503",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/code-unit",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit/issues",
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:58:43+00:00"
+ },
+ {
+ "name": "sebastian/code-unit-reverse-lookup",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
+ "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
+ "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Looks up which function or method a line of code belongs to",
+ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T06:59:15+00:00"
+ },
+ {
+ "name": "sebastian/comparator",
+ "version": "5.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/comparator.git",
+ "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53",
+ "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "php": ">=8.1",
+ "sebastian/diff": "^5.0",
+ "sebastian/exporter": "^5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@2bepublished.at"
+ }
+ ],
+ "description": "Provides the functionality to compare PHP values for equality",
+ "homepage": "https://github.com/sebastianbergmann/comparator",
+ "keywords": [
+ "comparator",
+ "compare",
+ "equality"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/comparator/issues",
+ "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-08-12T06:03:08+00:00"
+ },
+ {
+ "name": "sebastian/complexity",
+ "version": "3.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/complexity.git",
+ "reference": "68ff824baeae169ec9f2137158ee529584553799"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
+ "reference": "68ff824baeae169ec9f2137158ee529584553799",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.2-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for calculating the complexity of PHP code units",
+ "homepage": "https://github.com/sebastianbergmann/complexity",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/complexity/issues",
+ "security": "https://github.com/sebastianbergmann/complexity/security/policy",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-12-21T08:37:17+00:00"
+ },
+ {
+ "name": "sebastian/diff",
+ "version": "5.1.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/diff.git",
+ "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e",
+ "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0",
+ "symfony/process": "^6.4"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Kore Nordmann",
+ "email": "mail@kore-nordmann.de"
+ }
+ ],
+ "description": "Diff implementation",
+ "homepage": "https://github.com/sebastianbergmann/diff",
+ "keywords": [
+ "diff",
+ "udiff",
+ "unidiff",
+ "unified diff"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/diff/issues",
+ "security": "https://github.com/sebastianbergmann/diff/security/policy",
+ "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-02T07:15:17+00:00"
+ },
+ {
+ "name": "sebastian/environment",
+ "version": "6.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/environment.git",
+ "reference": "8074dbcd93529b357029f5cc5058fd3e43666984"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984",
+ "reference": "8074dbcd93529b357029f5cc5058fd3e43666984",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "suggest": {
+ "ext-posix": "*"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Provides functionality to handle HHVM/PHP environments",
+ "homepage": "https://github.com/sebastianbergmann/environment",
+ "keywords": [
+ "Xdebug",
+ "environment",
+ "hhvm"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/environment/issues",
+ "security": "https://github.com/sebastianbergmann/environment/security/policy",
+ "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-23T08:47:14+00:00"
+ },
+ {
+ "name": "sebastian/exporter",
+ "version": "5.1.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/exporter.git",
+ "reference": "955288482d97c19a372d3f31006ab3f37da47adf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf",
+ "reference": "955288482d97c19a372d3f31006ab3f37da47adf",
+ "shasum": ""
+ },
+ "require": {
+ "ext-mbstring": "*",
+ "php": ">=8.1",
+ "sebastian/recursion-context": "^5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.1-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Volker Dusch",
+ "email": "github@wallbash.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ },
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "Provides the functionality to export PHP variables for visualization",
+ "homepage": "https://www.github.com/sebastianbergmann/exporter",
+ "keywords": [
+ "export",
+ "exporter"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/exporter/issues",
+ "security": "https://github.com/sebastianbergmann/exporter/security/policy",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-02T07:17:12+00:00"
+ },
+ {
+ "name": "sebastian/global-state",
+ "version": "6.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/global-state.git",
+ "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
+ "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "sebastian/object-reflector": "^3.0",
+ "sebastian/recursion-context": "^5.0"
+ },
+ "require-dev": {
+ "ext-dom": "*",
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "6.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Snapshotting of global state",
+ "homepage": "https://www.github.com/sebastianbergmann/global-state",
+ "keywords": [
+ "global state"
+ ],
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/global-state/issues",
+ "security": "https://github.com/sebastianbergmann/global-state/security/policy",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-02T07:19:19+00:00"
+ },
+ {
+ "name": "sebastian/lines-of-code",
+ "version": "2.0.2",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/lines-of-code.git",
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
+ "shasum": ""
+ },
+ "require": {
+ "nikic/php-parser": "^4.18 || ^5.0",
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library for counting the lines of code in PHP source code",
+ "homepage": "https://github.com/sebastianbergmann/lines-of-code",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
+ "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-12-21T08:38:20+00:00"
+ },
+ {
+ "name": "sebastian/object-enumerator",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-enumerator.git",
+ "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906",
+ "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "sebastian/object-reflector": "^3.0",
+ "sebastian/recursion-context": "^5.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Traverses array structures and object graphs to enumerate all referenced objects",
+ "homepage": "https://github.com/sebastianbergmann/object-enumerator/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T07:08:32+00:00"
+ },
+ {
+ "name": "sebastian/object-reflector",
+ "version": "3.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/object-reflector.git",
+ "reference": "24ed13d98130f0e7122df55d06c5c4942a577957"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957",
+ "reference": "24ed13d98130f0e7122df55d06c5c4942a577957",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "3.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ }
+ ],
+ "description": "Allows reflection of object attributes, including inherited and non-public ones",
+ "homepage": "https://github.com/sebastianbergmann/object-reflector/",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/object-reflector/issues",
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T07:06:18+00:00"
+ },
+ {
+ "name": "sebastian/recursion-context",
+ "version": "5.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/recursion-context.git",
+ "reference": "05909fb5bc7df4c52992396d0116aed689f93712"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712",
+ "reference": "05909fb5bc7df4c52992396d0116aed689f93712",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "5.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de"
+ },
+ {
+ "name": "Jeff Welch",
+ "email": "whatthejeff@gmail.com"
+ },
+ {
+ "name": "Adam Harvey",
+ "email": "aharvey@php.net"
+ }
+ ],
+ "description": "Provides functionality to recursively process PHP variables",
+ "homepage": "https://github.com/sebastianbergmann/recursion-context",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/recursion-context/issues",
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T07:05:40+00:00"
+ },
+ {
+ "name": "sebastian/type",
+ "version": "4.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/type.git",
+ "reference": "462699a16464c3944eefc02ebdd77882bd3925bf"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf",
+ "reference": "462699a16464c3944eefc02ebdd77882bd3925bf",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^10.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Collection of value objects that represent the types of the PHP type system",
+ "homepage": "https://github.com/sebastianbergmann/type",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/type/issues",
+ "source": "https://github.com/sebastianbergmann/type/tree/4.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-03T07:10:45+00:00"
+ },
+ {
+ "name": "sebastian/version",
+ "version": "4.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/sebastianbergmann/version.git",
+ "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17",
+ "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "4.0-dev"
+ }
+ },
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Sebastian Bergmann",
+ "email": "sebastian@phpunit.de",
+ "role": "lead"
+ }
+ ],
+ "description": "Library that helps with managing the version number of Git-hosted PHP projects",
+ "homepage": "https://github.com/sebastianbergmann/version",
+ "support": {
+ "issues": "https://github.com/sebastianbergmann/version/issues",
+ "source": "https://github.com/sebastianbergmann/version/tree/4.0.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/sebastianbergmann",
+ "type": "github"
+ }
+ ],
+ "time": "2023-02-07T11:34:05+00:00"
+ },
+ {
+ "name": "theseer/tokenizer",
+ "version": "1.2.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/theseer/tokenizer.git",
+ "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
+ "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
+ "shasum": ""
+ },
+ "require": {
+ "ext-dom": "*",
+ "ext-tokenizer": "*",
+ "ext-xmlwriter": "*",
+ "php": "^7.2 || ^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "classmap": [
+ "src/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "BSD-3-Clause"
+ ],
+ "authors": [
+ {
+ "name": "Arne Blankerts",
+ "email": "arne@blankerts.de",
+ "role": "Developer"
+ }
+ ],
+ "description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
+ "support": {
+ "issues": "https://github.com/theseer/tokenizer/issues",
+ "source": "https://github.com/theseer/tokenizer/tree/1.2.3"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/theseer",
+ "type": "github"
+ }
+ ],
+ "time": "2024-03-03T12:36:25+00:00"
+ }
+ ],
+ "aliases": [],
+ "minimum-stability": "stable",
+ "stability-flags": [],
+ "prefer-stable": false,
+ "prefer-lowest": false,
+ "platform": {
+ "php": ">=8.1",
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "ext-xml": "*",
+ "ext-zip": "*",
+ "ext-zlib": "*"
+ },
+ "platform-dev": [],
+ "plugin-api-version": "2.6.0"
+}
diff --git a/vendor/mikespub/php-epub-meta/package.json b/vendor/mikespub/php-epub-meta/package.json
new file mode 100644
index 000000000..8f9b29b74
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/package.json
@@ -0,0 +1,9 @@
+{
+ "name": "php-epub-meta",
+ "packageManager": "yarn@4.2.1",
+ "dependencies": {
+ "jquery": "^3.7.1",
+ "jquery-ui": "^1.13.3"
+ },
+ "license": "MIT"
+}
diff --git a/vendor/mikespub/php-epub-meta/phpstan-baseline.neon b/vendor/mikespub/php-epub-meta/phpstan-baseline.neon
new file mode 100644
index 000000000..67e2584b2
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/phpstan-baseline.neon
@@ -0,0 +1,6 @@
+parameters:
+ ignoreErrors:
+ -
+ message: "#^Call to an undefined method DOMNode\\:\\:getAttribute\\(\\)\\.$#"
+ count: 1
+ path: src/Data/Item.php
diff --git a/vendor/mikespub/php-epub-meta/phpstan.neon.dist b/vendor/mikespub/php-epub-meta/phpstan.neon.dist
new file mode 100644
index 000000000..6333d1385
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/phpstan.neon.dist
@@ -0,0 +1,14 @@
+# baseline re-generated with level 4 to keep some issues visible on higher levels
+# at the time this file was updated there are 1 errors reported for levels 4 to 6
+includes:
+ #- phpstan-baseline.neon
+
+parameters:
+ level: 6
+ paths:
+ - .
+ bootstrapFiles:
+ - vendor/autoload.php
+ excludePaths:
+ - vendor/*
+ - src/Other.php
diff --git a/vendor/mikespub/php-epub-meta/phpunit.xml b/vendor/mikespub/php-epub-meta/phpunit.xml
new file mode 100644
index 000000000..9a43c940c
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/phpunit.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" bootstrap="./vendor/autoload.php" cacheDirectory=".phpunit.cache">
+ <coverage>
+ <report>
+ <clover outputFile="./clover.xml"/>
+ <text outputFile="php://stdout" showUncoveredFiles="false"/>
+ </report>
+ </coverage>
+ <logging/>
+ <testsuites>
+ <testsuite name="php-epub-meta">
+ <directory>./test/</directory>
+ <exclude>./test/otherTest.php</exclude>
+ </testsuite>
+ </testsuites>
+ <source>
+ <include>
+ <directory suffix=".php">./app/</directory>
+ <directory suffix=".php">./src/</directory>
+ </include>
+ <exclude>
+ <directory suffix=".php">./test</directory>
+ <directory suffix=".php">./vendor</directory>
+ </exclude>
+ </source>
+</phpunit>
diff --git a/vendor/mikespub/php-epub-meta/src/App/Handler.php b/vendor/mikespub/php-epub-meta/src/App/Handler.php
new file mode 100644
index 000000000..f1f7547ec
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/App/Handler.php
@@ -0,0 +1,236 @@
+<?php
+/**
+ * PHP EPub Meta - App request handler
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Sébastien Lucas <sebastien@slucas.fr>
+ * @author Simon Schrape <simon@epubli.com> © 2015
+ * @author mikespub
+ */
+
+namespace SebLucas\EPubMeta\App;
+
+use SebLucas\EPubMeta\EPub;
+use SebLucas\EPubMeta\Tools\ZipEdit;
+use Exception;
+
+class Handler
+{
+ protected string $bookdir;
+ protected string $rootdir;
+ protected ?EPub $epub;
+ protected ?string $error;
+
+ public function __construct(string $bookdir)
+ {
+ $this->bookdir = $bookdir;
+ $this->rootdir = dirname(__DIR__, 2);
+ }
+
+ /**
+ * Handle request
+ * @param mixed $request @todo
+ * @return void
+ */
+ public function handle($request = null)
+ {
+ // proxy google requests
+ if (isset($_GET['api'])) {
+ header('application/json; charset=UTF-8');
+ echo $this->searchBookApi($_GET['api']);
+ return;
+ }
+ if (!empty($_REQUEST['book'])) {
+ try {
+ $book = preg_replace('/[^\w ._-]+/', '', $_REQUEST['book']);
+ $book = basename($book . '.epub'); // no upper dirs, lowers might be supported later
+ $this->epub = new EPub($this->bookdir . $book, ZipEdit::class);
+ } catch (Exception $e) {
+ $this->error = $e->getMessage();
+ }
+ }
+ // return image data
+ if (!empty($_REQUEST['img']) && isset($this->epub)) {
+ $img = $this->epub->getCoverInfo();
+ header('Content-Type: ' . $img['mime']);
+ echo $img['data'];
+ return;
+ }
+ // save epub data
+ if (isset($_REQUEST['save']) && isset($this->epub)) {
+ $this->epub = $this->saveEpubData($this->epub);
+ if (!$this->error) {
+ // rename
+ $new = $this->renameEpubFile($this->epub);
+ $go = basename($new, '.epub');
+ header('Location: ?book=' . rawurlencode($go));
+ return;
+ }
+ }
+ $data = [];
+ $data['bookdir'] = htmlspecialchars($this->bookdir);
+ $data['booklist'] = '';
+ $list = glob($this->bookdir . '/*.epub');
+ foreach ($list as $book) {
+ $base = basename($book, '.epub');
+ $name = Util::book_output($base);
+ $data['booklist'] .= '<li ' . ($base == $_REQUEST['book'] ? 'class="active"' : '') . '>';
+ $data['booklist'] .= '<a href="?book=' . htmlspecialchars($base) . '">' . $name . '</a>';
+ $data['booklist'] .= '</li>';
+ }
+ if (isset($this->error)) {
+ $data['alert'] = "alert('" . htmlspecialchars($this->error) . "');";
+ }
+ if (empty($this->epub)) {
+ $data['license'] = str_replace("\n\n", '</p><p>', htmlspecialchars(file_get_contents($this->rootdir . '/LICENSE')));
+ $template = $this->rootdir . '/templates/index.html';
+ } else {
+ $data = $this->getEpubData($this->epub, $data);
+ $template = $this->rootdir . '/templates/epub.html';
+ }
+ header('Content-Type: text/html; charset=utf-8');
+ echo $this->renderTemplate($template, $data);
+ }
+
+ /**
+ * Proxy google requests
+ * @param string $query
+ * @return string|false
+ */
+ protected function searchBookApi($query)
+ {
+ return file_get_contents('https://www.googleapis.com/books/v1/volumes?q=' . rawurlencode($query) . '&maxResults=25&printType=books&projection=full');
+ }
+
+ /**
+ * Get Epub data
+ * @param EPub $epub
+ * @param array<string, string> $data
+ * @return array<string, string>
+ */
+ protected function getEpubData($epub, $data = [])
+ {
+ $data['book'] = htmlspecialchars($_REQUEST['book']);
+ $data['title'] = htmlspecialchars($epub->getTitle());
+ $data['authors'] = '';
+ $count = 0;
+ foreach ($epub->getAuthors() as $as => $name) {
+ $data['authors'] .= '<p>';
+ $data['authors'] .= '<input type="text" name="authorname[' . $count . ']" value="' . htmlspecialchars($name) . '" />';
+ $data['authors'] .= ' (<input type="text" name="authoras[' . $count . ']" value="' . htmlspecialchars($as) . '" />)';
+ $data['authors'] .= '</p>';
+ $count++;
+ }
+ $data['cover'] = '?book=' . htmlspecialchars($_REQUEST['book']) . '&amp;img=1';
+ $c = $epub->getCoverInfo();
+ $data['imgclass'] = $c['found'] ? 'hasimg' : 'noimg';
+ $data['description'] = htmlspecialchars($epub->getDescription());
+ $data['subjects'] = htmlspecialchars(join(', ', $epub->getSubjects()));
+ $data['publisher'] = htmlspecialchars($epub->getPublisher());
+ $data['copyright'] = htmlspecialchars($epub->getCopyright());
+ $data['language'] = htmlspecialchars($epub->getLanguage());
+ $data['isbn'] = htmlspecialchars($epub->getISBN());
+ return $data;
+ }
+
+ /**
+ * Save Epub data
+ * @param EPub $epub
+ * @return EPub
+ */
+ protected function saveEpubData($epub)
+ {
+ $epub->setTitle($_POST['title']);
+ $epub->setDescription($_POST['description']);
+ $epub->setLanguage($_POST['language']);
+ $epub->setPublisher($_POST['publisher']);
+ $epub->setCopyright($_POST['copyright']);
+ $epub->setIsbn($_POST['isbn']);
+ $epub->setSubjects($_POST['subjects']);
+
+ $authors = [];
+ foreach ((array) $_POST['authorname'] as $num => $name) {
+ if ($name) {
+ $as = $_POST['authoras'][$num];
+ if (!$as) {
+ $as = $name;
+ }
+ $authors[$as] = $name;
+ }
+ }
+ $epub->setAuthors($authors);
+
+ // handle image
+ $cover = '';
+ if (preg_match('/^https?:\/\//i', $_POST['coverurl'])) {
+ $data = @file_get_contents($_POST['coverurl']);
+ if ($data) {
+ $cover = tempnam(sys_get_temp_dir(), 'epubcover');
+ file_put_contents($cover, $data);
+ unset($data);
+ }
+ } elseif(is_uploaded_file($_FILES['coverfile']['tmp_name'])) {
+ $cover = $_FILES['coverfile']['tmp_name'];
+ }
+ if ($cover) {
+ $info = @getimagesize($cover);
+ if (preg_match('/^image\/(gif|jpe?g|png)$/', $info['mime'])) {
+ $epub->setCoverInfo($cover, $info['mime']);
+ } else {
+ $this->error = 'Not a valid image file' . $cover;
+ }
+ }
+
+ // save the ebook
+ try {
+ $epub->save();
+ } catch (Exception $e) {
+ $this->error = $e->getMessage();
+ }
+
+ // clean up temporary cover file
+ if ($cover) {
+ @unlink($cover);
+ }
+
+ return $epub;
+ }
+
+ /**
+ * Rename Epub file
+ * @param EPub $epub
+ * @return string
+ */
+ protected function renameEpubFile($epub)
+ {
+ $author = array_keys($epub->getAuthors())[0];
+ $title = $epub->getTitle();
+ $new = Util::to_file($author . '-' . $title);
+ $new = $this->bookdir . $new . '.epub';
+ $old = $epub->file();
+ if (realpath($new) != realpath($old)) {
+ if (!@rename($old, $new)) {
+ $new = $old; //rename failed, stay here
+ }
+ }
+ return $new;
+ }
+
+ /**
+ * Render template with data
+ * @param string $template
+ * @param array<string, string> $data
+ * @return string
+ */
+ protected function renderTemplate($template, $data)
+ {
+ if (!file_exists($template)) {
+ throw new Exception('Invalid template ' . htmlspecialchars($template));
+ }
+ $content = file_get_contents($template);
+ foreach ($data as $name => $value) {
+ $content = preg_replace('/{{\s*' . $name . '\s*}}/', $value, $content);
+ }
+ return $content;
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/App/Util.php b/vendor/mikespub/php-epub-meta/src/App/Util.php
new file mode 100644
index 000000000..730e9ec95
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/App/Util.php
@@ -0,0 +1,55 @@
+<?php
+/**
+ * PHP EPub Meta utility functions for App interface
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Sébastien Lucas <sebastien@slucas.fr>
+ * @author Simon Schrape <simon@epubli.com> © 2015
+ * @author mikespub
+ */
+
+namespace SebLucas\EPubMeta\App;
+
+class Util
+{
+ /**
+ * Summary of to_file
+ * @param string $input
+ * @return string
+ */
+ public static function to_file($input)
+ {
+ $input = str_replace(' ', '_', $input);
+ $input = str_replace('__', '_', $input);
+ $input = str_replace(',_', ',', $input);
+ $input = str_replace('_,', ',', $input);
+ $input = str_replace('-_', '-', $input);
+ $input = str_replace('_-', '-', $input);
+ $input = str_replace(',', '__', $input);
+ return $input;
+ }
+
+ /**
+ * Summary of book_output
+ * @param string $input
+ * @return string
+ */
+ public static function book_output($input)
+ {
+ $input = str_replace('__', ',', $input);
+ $input = str_replace('_', ' ', $input);
+ $input = str_replace(',', ', ', $input);
+ $input = str_replace('-', ' - ', $input);
+ [$author, $title] = explode('-', $input, 2);
+ $author = trim($author);
+ $title = trim($title);
+
+ if (!$title) {
+ $title = $author;
+ $author = '';
+ }
+
+ return '<span class="title">' . htmlspecialchars($title) . '</span>' .
+ '<span class="author">' . htmlspecialchars($author) . '</author>';
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Contents/Nav.php b/vendor/mikespub/php-epub-meta/src/Contents/Nav.php
new file mode 100644
index 000000000..e8eb980a6
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Contents/Nav.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace SebLucas\EPubMeta\Contents;
+
+/**
+ * EPUB NAV structure for EPUB 3
+ *
+ * @author Simon Schrape <simon@epubli.com>
+ */
+class Nav
+{
+ /** @var string from main document */
+ protected $docTitle;
+ /** @var string from main document */
+ protected $docAuthor;
+ /** @var NavPointList */
+ protected $navMap;
+
+ /**
+ * Summary of __construct
+ * @param string $title
+ * @param string $author
+ */
+ public function __construct($title, $author)
+ {
+ $this->docTitle = $title;
+ $this->docAuthor = $author;
+ $this->navMap = new NavPointList();
+ }
+
+ /**
+ * @return string
+ */
+ public function getDocTitle()
+ {
+ return $this->docTitle;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDocAuthor()
+ {
+ return $this->docAuthor;
+ }
+
+ /**
+ * @return NavPointList
+ */
+ public function getNavMap()
+ {
+ return $this->navMap;
+ }
+
+ /**
+ * @param string $file
+ * @return array|NavPoint[]
+ */
+ public function findNavPointsForFile($file)
+ {
+ return $this->getNavMap()->findNavPointsForFile($file);
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Contents/NavPoint.php b/vendor/mikespub/php-epub-meta/src/Contents/NavPoint.php
new file mode 100644
index 000000000..7ffb29dca
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Contents/NavPoint.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace SebLucas\EPubMeta\Contents;
+
+/**
+ * An EPUB TOC navigation point.
+ *
+ * @author Simon Schrape <simon@epubli.com>
+ */
+class NavPoint
+{
+ /** @var string */
+ protected $id;
+ /** @var string */
+ protected $class;
+ /** @var int */
+ protected $playOrder;
+ /** @var string */
+ protected $navLabel;
+ /** @var string */
+ protected $contentSourceFile;
+ /** @var string */
+ protected $contentSourceFragment;
+ /** @var NavPointList */
+ protected $children;
+
+ /**
+ * @param string $id
+ * @param string $class
+ * @param int $playOrder
+ * @param string $label
+ * @param string $contentSource
+ */
+ public function __construct($id, $class, $playOrder, $label, $contentSource)
+ {
+ $this->id = $id;
+ $this->class = $class;
+ $this->playOrder = $playOrder;
+ $this->navLabel = $label;
+ $contentSourceParts = explode('#', $contentSource, 2);
+ $this->contentSourceFile = $contentSourceParts[0];
+ $this->contentSourceFragment = $contentSourceParts[1] ?? null;
+ $this->children = new NavPointList();
+ }
+
+ /**
+ * @return string
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @return string
+ */
+ public function getClass()
+ {
+ return $this->class;
+ }
+
+ /**
+ * @return int
+ */
+ public function getPlayOrder()
+ {
+ return $this->playOrder;
+ }
+
+ /**
+ * @return string
+ */
+ public function getNavLabel()
+ {
+ return $this->navLabel;
+ }
+
+ /**
+ * @return string
+ */
+ public function getContentSource()
+ {
+ return $this->contentSourceFile . ($this->contentSourceFragment ? '#' . $this->contentSourceFragment : '');
+ }
+
+ /**
+ * @return string
+ */
+ public function getContentSourceFile()
+ {
+ return $this->contentSourceFile;
+ }
+
+ /**
+ * @return string
+ */
+ public function getContentSourceFragment()
+ {
+ return $this->contentSourceFragment;
+ }
+
+ /**
+ * @return NavPointList
+ */
+ public function getChildren()
+ {
+ return $this->children;
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Contents/NavPointList.php b/vendor/mikespub/php-epub-meta/src/Contents/NavPointList.php
new file mode 100644
index 000000000..540d2f876
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Contents/NavPointList.php
@@ -0,0 +1,65 @@
+<?php
+
+namespace SebLucas\EPubMeta\Contents;
+
+use ArrayIterator;
+
+/**
+ * A list of EPUB TOC navigation points.
+ *
+ * @author Simon Schrape <simon@epubli.com>
+ * @author mikespub
+ * @extends ArrayIterator<int, NavPoint>
+ */
+class NavPointList extends ArrayIterator
+{
+ public function __construct() {}
+
+ /**
+ * @return NavPoint
+ */
+ public function first()
+ {
+ $this->rewind();
+ return $this->current();
+ }
+
+ /**
+ * @return NavPoint
+ */
+ public function last()
+ {
+ $this->seek($this->count() - 1);
+ return $this->current();
+ }
+
+ /**
+ * @param NavPoint $navPoint
+ * @return void
+ * @deprecated 2.1.0 use normal append() instead
+ */
+ public function addNavPoint(NavPoint $navPoint)
+ {
+ $this->append($navPoint);
+ }
+
+ /**
+ * @param string $file
+ *
+ * @return array|NavPoint[]
+ */
+ public function findNavPointsForFile($file)
+ {
+ $matches = [];
+ foreach ($this as $navPoint) {
+ if ($navPoint->getContentSourceFile() == $file) {
+ $matches[] = $navPoint;
+ }
+ $childMatches = $navPoint->getChildren()->findNavPointsForFile($file);
+ if (count($childMatches)) {
+ $matches = array_merge($matches, $childMatches);
+ }
+ }
+ return $matches;
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Contents/Spine.php b/vendor/mikespub/php-epub-meta/src/Contents/Spine.php
new file mode 100644
index 000000000..e6dfc2a84
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Contents/Spine.php
@@ -0,0 +1,198 @@
+<?php
+
+namespace SebLucas\EPubMeta\Contents;
+
+use SebLucas\EPubMeta\Data\Item;
+use ArrayAccess;
+use Countable;
+use Iterator;
+use BadMethodCallException;
+
+/**
+ * EPUB spine structure
+ *
+ * @author Simon Schrape <simon@epubli.com>
+ * @implements \Iterator<int, Item>
+ * @implements \ArrayAccess<int, Item>
+ */
+class Spine implements Iterator, Countable, ArrayAccess
+{
+ /** @var Item */
+ protected $tocItem;
+ protected string $tocFormat;
+ /** @var array|Item[] The ordered list of all Items in this Spine. */
+ protected $items = [];
+
+ /**
+ * Spine Constructor.
+ *
+ * @param Item $tocItem The TOC Item of this Spine.
+ * @param string $tocFormat The TOC Format of this Spine (Toc or Nav).
+ */
+ public function __construct(Item $tocItem, string $tocFormat)
+ {
+ $this->tocItem = $tocItem;
+ $this->tocFormat = $tocFormat;
+ }
+
+ /**
+ * Get the TOC Item of this Spine.
+ *
+ * @return Item
+ */
+ public function getTocItem()
+ {
+ return $this->tocItem;
+ }
+
+ /**
+ * Get the TOC Format of this Spine.
+ *
+ * @return string
+ */
+ public function getTocFormat()
+ {
+ return $this->tocFormat;
+ }
+
+ /**
+ * Append an Item to this Spine.
+ *
+ * @param Item $item The Item to append to this Spine.
+ * @return void
+ */
+ public function appendItem(Item $item)
+ {
+ $this->items[] = $item;
+ }
+
+ /**
+ * Return the current Item while iterating this Spine.
+ *
+ * @link http://php.net/manual/en/iterator.current.php
+ * @return Item
+ */
+ public function current(): Item
+ {
+ return current($this->items);
+ }
+
+ /**
+ * Move forward to next Item while iterating this Spine.
+ * @link http://php.net/manual/en/iterator.next.php
+ * @return void Any returned value is ignored.
+ */
+ public function next(): void
+ {
+ next($this->items);
+ }
+
+ /**
+ * Return the index of the current Item while iterating this Spine.
+ *
+ * @link http://php.net/manual/en/iterator.key.php
+ * @return int|null on success, or null on failure.
+ */
+ public function key(): ?int
+ {
+ return key($this->items);
+ }
+
+ /**
+ * Checks if current Iterator position is valid.
+ *
+ * @link http://php.net/manual/en/iterator.valid.php
+ * @return boolean true on success or false on failure.
+ */
+ public function valid(): bool
+ {
+ return (bool) current($this->items);
+ }
+
+ /**
+ * Rewind the Iterator to the first element.
+ *
+ * @link http://php.net/manual/en/iterator.rewind.php
+ * @return void Any returned value is ignored.
+ */
+ public function rewind(): void
+ {
+ reset($this->items);
+ }
+
+ /**
+ * Get the first Item of this Spine.
+ *
+ * @return Item
+ */
+ public function first()
+ {
+ return reset($this->items);
+ }
+
+ /**
+ * Get the last Item of this Spine.
+ *
+ * @return Item
+ */
+ public function last()
+ {
+ return end($this->items);
+ }
+
+ /**
+ * Count items of this Spine.
+ *
+ * @link https://php.net/manual/en/countable.count.php
+ * @return int The number of Items contained in this Spine.
+ */
+ public function count(): int
+ {
+ return count($this->items);
+ }
+
+ /**
+ * Whether a offset exists
+ * @link https://php.net/manual/en/arrayaccess.offsetexists.php
+ * @param int $offset An offset to check for.
+ * @return boolean true on success or false on failure.
+ */
+ public function offsetExists($offset): bool
+ {
+ return isset($this->items[$offset]);
+ }
+
+ /**
+ * Offset to retrieve
+ * @link https://php.net/manual/en/arrayaccess.offsetget.php
+ * @param int $offset The offset to retrieve.
+ * @return Item
+ */
+ public function offsetGet($offset): Item
+ {
+ return $this->items[$offset];
+ }
+
+ /**
+ * Offset to set
+ * @link https://php.net/manual/en/arrayaccess.offsetset.php
+ * @param mixed $offset The offset to assign the value to.
+ * @param mixed $value The value to set.
+ * @throws BadMethodCallException
+ */
+ public function offsetSet($offset, $value): void
+ {
+ throw new BadMethodCallException("Only reading array access is supported!");
+ }
+
+ /**
+ * Offset to unset
+ * @link https://php.net/manual/en/arrayaccess.offsetunset.php
+ * @param mixed $offset The offset to unset.
+ * @throws BadMethodCallException
+ */
+ public function offsetUnset($offset): void
+ {
+ throw new BadMethodCallException("Only reading array access is supported!");
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Contents/Toc.php b/vendor/mikespub/php-epub-meta/src/Contents/Toc.php
new file mode 100644
index 000000000..7992c4a8e
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Contents/Toc.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace SebLucas\EPubMeta\Contents;
+
+/**
+ * EPUB TOC structure for EPUB 2
+ *
+ * @author Simon Schrape <simon@epubli.com>
+ */
+class Toc
+{
+ /** @var string */
+ protected $docTitle;
+ /** @var string */
+ protected $docAuthor;
+ /** @var NavPointList */
+ protected $navMap;
+
+ /**
+ * Summary of __construct
+ * @param string $title
+ * @param string $author
+ */
+ public function __construct($title, $author)
+ {
+ $this->docTitle = $title;
+ $this->docAuthor = $author;
+ $this->navMap = new NavPointList();
+ }
+
+ /**
+ * @return string
+ */
+ public function getDocTitle()
+ {
+ return $this->docTitle;
+ }
+
+ /**
+ * @return string
+ */
+ public function getDocAuthor()
+ {
+ return $this->docAuthor;
+ }
+
+ /**
+ * @return NavPointList
+ */
+ public function getNavMap()
+ {
+ return $this->navMap;
+ }
+
+ /**
+ * @param string $file
+ * @return array|NavPoint[]
+ */
+ public function findNavPointsForFile($file)
+ {
+ return $this->getNavMap()->findNavPointsForFile($file);
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Data/Item.php b/vendor/mikespub/php-epub-meta/src/Data/Item.php
new file mode 100644
index 000000000..271462920
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Data/Item.php
@@ -0,0 +1,193 @@
+<?php
+
+namespace SebLucas\EPubMeta\Data;
+
+use SebLucas\EPubMeta\Tools\HtmlTools;
+use DOMDocument;
+use DOMElement;
+use DOMText;
+use DOMXPath;
+use Exception;
+
+/**
+ * An item of the EPUB manifest.
+ *
+ * @author Simon Schrape <simon@epubli.com>
+ */
+class Item
+{
+ public const XHTML = 'application/xhtml+xml';
+ /** @var string */
+ protected $id;
+ /** @var string The path to the corresponding file. */
+ protected $href;
+ /** @var string */
+ protected $mediaType;
+ /** @var callable|null A callable to get data from the referenced file. */
+ protected $dataCallable;
+ /** @var string The data read from the referenced file. */
+ protected $data;
+ /** @var int The size of the referenced file. */
+ protected $size;
+
+ /**
+ * @param string $id This Item’s identifier.
+ * @param string $href The path to the corresponding file.
+ * @param callable $dataCallable A callable to get data from the referenced file.
+ * @param int $size The size of the referenced file.
+ * @param string|null $mediaType The media type of the corresponding file. If omitted XHTML is assumed.
+ */
+ public function __construct($id, $href, $dataCallable, $size, $mediaType = null)
+ {
+ $this->id = $id;
+ $this->href = $href;
+ $this->dataCallable = $dataCallable;
+ $this->size = $size;
+ $this->mediaType = $mediaType ?: static::XHTML;
+ }
+
+ /**
+ * @return string
+ */
+ public function getId()
+ {
+ return $this->id;
+ }
+
+ /**
+ * @return string
+ */
+ public function getHref()
+ {
+ return $this->href;
+ }
+
+ /**
+ * @return string
+ */
+ public function getMediaType()
+ {
+ return $this->mediaType;
+ }
+
+ /**
+ * Extract (a part of) the contents from the referenced XML file.
+ *
+ * @param string|null $fragmentBegin ID of the element where to start reading the contents.
+ * @param string|null $fragmentEnd ID of the element where to stop reading the contents.
+ * @param bool $keepMarkup Whether to keep the XHTML markup rather than extracted plain text.
+ * @return string The contents of that fragment.
+ * @throws Exception
+ */
+ public function getContents($fragmentBegin = null, $fragmentEnd = null, $keepMarkup = false)
+ {
+ $dom = new DOMDocument();
+ $dom->loadXML(HtmlTools::convertEntitiesNamedToNumeric($this->getData()));
+
+ // get the starting point
+ if ($fragmentBegin) {
+ $xp = new DOMXPath($dom);
+ $node = $xp->query("//*[@id='$fragmentBegin']")->item(0);
+ if (!$node) {
+ throw new Exception("Begin of fragment not found: No element with ID $fragmentBegin!");
+ }
+ } else {
+ $node = $dom->getElementsByTagName('body')->item(0) ?: $dom->documentElement;
+ }
+
+ $allowableTags = [
+ 'br',
+ 'p',
+ 'h1',
+ 'h2',
+ 'h3',
+ 'h4',
+ 'h5',
+ 'span',
+ 'div',
+ 'i',
+ 'strong',
+ 'b',
+ 'table',
+ 'td',
+ 'th',
+ 'tr',
+ ];
+ $contents = '';
+ $endTags = [];
+ /** @var DOMElement|DOMText $node */
+ // traverse DOM structure till end point is reached, accumulating the contents
+ while ($node && (!$fragmentEnd || !$node->hasAttributes() || $node->getAttribute('id') != $fragmentEnd)) {
+ if ($node instanceof DOMText) {
+ // when encountering a text node append its value to the contents
+ $contents .= $keepMarkup ? htmlspecialchars($node->nodeValue) : $node->nodeValue;
+ } elseif ($node instanceof DOMElement) {
+ $tag = $node->localName;
+ if ($keepMarkup && in_array($tag, $allowableTags)) {
+ $contents .= "<$tag>";
+ $endTags[] = "</$tag>";
+ } elseif (HtmlTools::isBlockLevelElement($tag)) {
+ // add whitespace between contents of adjacent blocks
+ $endTags[] = PHP_EOL;
+ } else {
+ $endTags[] = '';
+ }
+
+ if ($node->hasChildNodes()) {
+ // step into
+ $node = $node->firstChild;
+ continue;
+ }
+ }
+
+ // leave node
+ while ($node) {
+ if ($node instanceof DOMElement) {
+ $contents .= array_pop($endTags);
+ }
+
+ if ($node->nextSibling) {
+ // step right
+ $node = $node->nextSibling;
+ break;
+ } elseif ($node = $node->parentNode) {
+ // step out
+ continue;
+ } elseif ($fragmentEnd) {
+ // reached end of DOM without finding fragment end
+ throw new Exception("End of fragment not found: No element with ID $fragmentEnd!");
+ }
+ }
+ }
+ while ($endTags) {
+ $contents .= array_pop($endTags);
+ }
+
+ return $contents;
+ }
+
+ /**
+ * Get the file data.
+ *
+ * @return string The binary data of the corresponding file.
+ */
+ public function getData()
+ {
+ if ($this->dataCallable) {
+ $this->data = call_user_func($this->dataCallable);
+ $this->dataCallable = null;
+ }
+
+ return $this->data;
+ }
+
+ /**
+ * Get the size of the corresponding file.
+ *
+ * @return int
+ */
+ public function getSize()
+ {
+ return $this->size ?: strlen($this->getData());
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Data/Manifest.php b/vendor/mikespub/php-epub-meta/src/Data/Manifest.php
new file mode 100644
index 000000000..428b2cc02
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Data/Manifest.php
@@ -0,0 +1,174 @@
+<?php
+
+namespace SebLucas\EPubMeta\Data;
+
+use ArrayAccess;
+use Countable;
+use Exception;
+use BadMethodCallException;
+use Iterator;
+
+/**
+ * EPUB manifest structure
+ *
+ * @author Simon Schrape <simon@epubli.com>
+ * @implements \Iterator<string, Item>
+ * @implements \ArrayAccess<string, Item>
+ */
+class Manifest implements Iterator, Countable, ArrayAccess
+{
+ /** @var array|Item[] The map of all Items in this Manifest indexed by their IDs. */
+ protected $items = [];
+
+ /**
+ * Create and add an Item with the given properties.
+ *
+ * @param string $id The identifier of the new item.
+ * @param string $href The relative path of the referenced file in the EPUB.
+ * @param callable $callable A callable to get data from the referenced file in the EPUB.
+ * @param int $size The size of the referenced file in the EPUB.
+ * @param string|null $mediaType
+ * @return Item The newly created Item.
+ * @throws Exception If $id is already taken.
+ */
+ public function createItem($id, $href, $callable, $size, $mediaType = null)
+ {
+ if (isset($this->items[$id])) {
+ throw new Exception("Item with ID $id already exists!");
+ }
+ $item = new Item($id, $href, $callable, $size, $mediaType);
+ $this->items[$id] = $item;
+
+ return $item;
+ }
+
+ /**
+ * Return the current Item while iterating this Manifest.
+ *
+ * @link http://php.net/manual/en/iterator.current.php
+ * @return Item
+ */
+ public function current(): Item
+ {
+ return current($this->items);
+ }
+
+ /**
+ * Move forward to next Item while iterating this Manifest.
+ * @link http://php.net/manual/en/iterator.next.php
+ * @return void Any returned value is ignored.
+ */
+ public function next(): void
+ {
+ next($this->items);
+ }
+
+ /**
+ * Return the ID of the current Item while iterating this Manifest.
+ *
+ * @link http://php.net/manual/en/iterator.key.php
+ * @return string|null on success, or null on failure.
+ */
+ public function key(): ?string
+ {
+ return key($this->items);
+ }
+
+ /**
+ * Checks if current Iterator position is valid.
+ *
+ * @link http://php.net/manual/en/iterator.valid.php
+ * @return boolean true on success or false on failure.
+ */
+ public function valid(): bool
+ {
+ return (bool) current($this->items);
+ }
+
+ /**
+ * Rewind the Iterator to the first element.
+ *
+ * @link http://php.net/manual/en/iterator.rewind.php
+ * @return void Any returned value is ignored.
+ */
+ public function rewind(): void
+ {
+ reset($this->items);
+ }
+
+ /**
+ * Get the first Item of this Manifest.
+ *
+ * @return Item
+ */
+ public function first()
+ {
+ return reset($this->items);
+ }
+
+ /**
+ * Get the last Item of this Manifest.
+ *
+ * @return Item
+ */
+ public function last()
+ {
+ return end($this->items);
+ }
+
+ /**
+ * Count items of this Manifest.
+ *
+ * @link https://php.net/manual/en/countable.count.php
+ * @return int The number of Items contained in this Manifest.
+ */
+ public function count(): int
+ {
+ return count($this->items);
+ }
+
+ /**
+ * Whether a offset exists
+ * @link https://php.net/manual/en/arrayaccess.offsetexists.php
+ * @param string $offset An offset to check for.
+ * @return boolean true on success or false on failure.
+ */
+ public function offsetExists($offset): bool
+ {
+ return isset($this->items[$offset]);
+ }
+
+ /**
+ * Offset to retrieve
+ * @link https://php.net/manual/en/arrayaccess.offsetget.php
+ * @param string $offset The offset to retrieve.
+ * @return Item
+ */
+ public function offsetGet($offset): Item
+ {
+ return $this->items[$offset];
+ }
+
+ /**
+ * Offset to set
+ * @link https://php.net/manual/en/arrayaccess.offsetset.php
+ * @param mixed $offset The offset to assign the value to.
+ * @param mixed $value The value to set.
+ * @throws BadMethodCallException
+ */
+ public function offsetSet($offset, $value): void
+ {
+ throw new BadMethodCallException("Only reading array access is supported!");
+ }
+
+ /**
+ * Offset to unset
+ * @link https://php.net/manual/en/arrayaccess.offsetunset.php
+ * @param mixed $offset The offset to unset.
+ * @throws BadMethodCallException
+ */
+ public function offsetUnset($offset): void
+ {
+ throw new BadMethodCallException("Only reading array access is supported!");
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Dom/Element.php b/vendor/mikespub/php-epub-meta/src/Dom/Element.php
new file mode 100644
index 000000000..2a7058eaa
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Dom/Element.php
@@ -0,0 +1,196 @@
+<?php
+/**
+ * PHP EPub Meta library
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Sébastien Lucas <sebastien@slucas.fr>
+ */
+
+namespace SebLucas\EPubMeta\Dom;
+
+use DOMElement;
+
+/**
+ * EPUB-specific subclass of DOMElement
+ *
+ * Source: https://github.com/splitbrain/php-epub-meta
+ * @author Andreas Gohr <andi@splitbrain.org> © 2012
+ * @author Simon Schrape <simon@epubli.com> © 2015–2018
+ * @author Sébastien Lucas <sebastien@slucas.fr>
+ *
+ * @property string $nodeValueUnescaped
+ */
+class Element extends DOMElement
+{
+ /** @var array<string, string> */
+ public static $namespaces = [
+ 'n' => 'urn:oasis:names:tc:opendocument:xmlns:container',
+ 'opf' => 'http://www.idpf.org/2007/opf',
+ 'dc' => 'http://purl.org/dc/elements/1.1/',
+ 'ncx' => 'http://www.daisy.org/z3986/2005/ncx/',
+ ];
+
+ /**
+ * Summary of __construct
+ * @param string $name
+ * @param string $value
+ * @param string $namespaceUri
+ */
+ public function __construct($name, $value = '', $namespaceUri = '')
+ {
+ [$prefix, $name] = $this->splitQualifiedName($name);
+ $value = htmlspecialchars($value);
+ if (!$namespaceUri && $prefix) {
+ //$namespaceUri = XmlNamespace::getUri($prefix);
+ $namespaceUri = static::$namespaces[$prefix];
+ }
+ parent::__construct($name, $value, $namespaceUri);
+ }
+
+ /**
+ * Summary of __get
+ * @param string $name
+ * @return string|null
+ */
+ public function __get($name)
+ {
+ switch ($name) {
+ case 'nodeValueUnescaped':
+ return htmlspecialchars_decode($this->nodeValue);
+ }
+
+ return null;
+ }
+
+ /**
+ * Summary of __set
+ * @param string $name
+ * @param mixed $value
+ * @return void
+ */
+ public function __set($name, $value)
+ {
+ switch ($name) {
+ case 'nodeValueUnescaped':
+ $this->nodeValue = htmlspecialchars($value);
+ }
+ }
+
+ /**
+ * Create and append a new child
+ *
+ * Works with our epub namespaces and omits default namespaces
+ * @param string $name
+ * @param string $value
+ * @return Element|bool
+ */
+ public function newChild($name, $value = '')
+ {
+ [$localName, $namespaceUri] = $this->getNameContext($name);
+
+ // this doesn't call the constructor: $node = $this->ownerDocument->createElement($name,$value);
+ $node = new Element($namespaceUri ? $name : $localName, $value, $namespaceUri);
+
+ /** @var Element $node */
+ $node = $this->appendChild($node);
+ return $node;
+ }
+
+ /**
+ * Simple EPUB namespace aware attribute getter
+ * @param string $name
+ * @return string
+ */
+ public function getAttrib($name)
+ {
+ [$localName, $namespaceUri] = $this->getNameContext($name);
+
+ // return value if none was given
+ if ($namespaceUri) {
+ return $this->getAttributeNS($namespaceUri, $localName);
+ } else {
+ return $this->getAttribute($localName);
+ }
+ }
+
+ /**
+ * Simple EPUB namespace aware attribute setter
+ * @param string $name
+ * @param mixed $value
+ * @return void
+ */
+ public function setAttrib($name, $value)
+ {
+ [$localName, $namespaceUri] = $this->getNameContext($name);
+
+ if ($namespaceUri) {
+ $this->setAttributeNS($namespaceUri, $localName, $value);
+ } else {
+ $this->setAttribute($localName, $value);
+ }
+ }
+
+ /**
+ * Simple EPUB namespace aware attribute remover
+ * @param string $name
+ * @return void
+ */
+ public function removeAttrib($name)
+ {
+ [$localName, $namespaceUri] = $this->getNameContext($name);
+
+ if ($namespaceUri) {
+ $this->removeAttributeNS($namespaceUri, $localName);
+ } else {
+ $this->removeAttribute($localName);
+ }
+ }
+
+ /**
+ * Remove this node from the DOM
+ * @return void
+ */
+ public function delete()
+ {
+ $this->parentNode->removeChild($this);
+ }
+
+ /**
+ * Split given name in namespace prefix and local part
+ *
+ * @param string $name
+ * @return array<string> (prefix, name)
+ */
+ protected function splitQualifiedName($name)
+ {
+ $list = explode(':', $name, 2);
+ if (count($list) < 2) {
+ array_unshift($list, '');
+ }
+
+ return $list;
+ }
+
+ /**
+ * @param string $name
+ * @return array<string>
+ */
+ protected function getNameContext($name)
+ {
+ [$prefix, $localName] = $this->splitQualifiedName($name);
+
+ $namespaceUri = '';
+ if ($prefix) {
+ //$namespaceUri = XmlNamespace::getUri($prefix);
+ $namespaceUri = static::$namespaces[$prefix];
+ if (
+ !$this->namespaceURI && $this->isDefaultNamespace($namespaceUri)
+ || $this->namespaceURI == $namespaceUri
+ ) {
+ $namespaceUri = '';
+ }
+ }
+
+ return [$localName, $namespaceUri];
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Dom/XPath.php b/vendor/mikespub/php-epub-meta/src/Dom/XPath.php
new file mode 100644
index 000000000..4d208c1cd
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Dom/XPath.php
@@ -0,0 +1,32 @@
+<?php
+/**
+ * PHP EPub Meta library
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Sébastien Lucas <sebastien@slucas.fr>
+ */
+
+namespace SebLucas\EPubMeta\Dom;
+
+use DOMDocument;
+use DOMXPath;
+
+/**
+ * EPUB-specific subclass of DOMXPath
+ *
+ * Source: https://github.com/splitbrain/php-epub-meta
+ * @author Andreas Gohr <andi@splitbrain.org> © 2012
+ * @author Simon Schrape <simon@epubli.com> © 2015–2018
+ * @author Sébastien Lucas <sebastien@slucas.fr>
+ */
+class XPath extends DOMXPath
+{
+ public function __construct(DOMDocument $doc)
+ {
+ parent::__construct($doc);
+
+ foreach (Element::$namespaces as $prefix => $namespaceUri) {
+ $this->registerNamespace($prefix, $namespaceUri);
+ }
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/EPub.php b/vendor/mikespub/php-epub-meta/src/EPub.php
new file mode 100644
index 000000000..171fd7641
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/EPub.php
@@ -0,0 +1,2126 @@
+<?php
+/**
+ * PHP EPub Meta library
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Sébastien Lucas <sebastien@slucas.fr>
+ * @author Simon Schrape <simon@epubli.com> © 2015
+ */
+
+namespace SebLucas\EPubMeta;
+
+use SebLucas\EPubMeta\Dom\Element as EpubDomElement;
+use SebLucas\EPubMeta\Dom\XPath as EpubDomXPath;
+use SebLucas\EPubMeta\Data\Manifest;
+use SebLucas\EPubMeta\Contents\Nav;
+use SebLucas\EPubMeta\Contents\Spine;
+use SebLucas\EPubMeta\Contents\NavPoint as TocNavPoint;
+use SebLucas\EPubMeta\Contents\NavPointList as TocNavPointList;
+use SebLucas\EPubMeta\Contents\Toc;
+use SebLucas\EPubMeta\Tools\ZipEdit;
+use SebLucas\EPubMeta\Tools\ZipFile;
+use DOMDocument;
+use DOMElement;
+use DOMNodeList;
+use Exception;
+use InvalidArgumentException;
+use JsonException;
+use ZipArchive;
+
+class EPub
+{
+ /** Identifier for cover image inserted by this lib. */
+ public const COVER_ID = 'php-epub-meta-cover';
+ /** Identifier for title page inserted by this lib. */
+ public const TITLE_PAGE_ID = 'php-epub-meta-titlepage';
+ public const METADATA_FILE = 'META-INF/container.xml';
+ public const MIME_TYPE = 'application/epub+zip';
+ public const BOOKMARK_FILE = 'META-INF/calibre_bookmarks.txt';
+ public const EPUB_FILE_TYPE_MAGIC = "encoding=json+base64:\n";
+ /** @var array<int, array<string>> */
+ public static $encodeNameReplace = [
+ ['/', '-'],
+ ['~SLASH~', '~DASH~'],
+ ];
+ /** @var array<int, array<string>> */
+ public static $decodeNameReplace = [
+ ['~SLASH~', '~DASH~'],
+ ['/', '-'],
+ ];
+
+ /** @var DOMDocument */
+ public $xml; //FIXME: change to protected, later
+ /** @var DOMDocument|null */
+ public $toc;
+ /** @var DOMDocument|null */
+ public $nav;
+ /** @var EpubDomXPath */
+ protected $xpath;
+ /** @var EpubDomXPath */
+ protected $toc_xpath;
+ /** @var EpubDomXPath */
+ protected $nav_xpath;
+ protected string $file;
+ protected string $meta;
+ /** @var ZipEdit|ZipFile */
+ protected $zip;
+ protected string $zipClass;
+ protected string $coverpath = '';
+ /** @var mixed */
+ protected $namespaces;
+ protected string $imagetoadd = '';
+ /** @var array<mixed> A map of ZIP items mapping filenames to file sizes */
+ protected $zipSizeMap;
+ /** @var Manifest|null The manifest (catalog of files) of this EPUB */
+ protected $manifest;
+ /** @var Spine|null The spine structure of this EPUB */
+ protected $spine;
+ /** @var Toc|Nav|null The TOC structure of this EPUB */
+ protected $tocnav;
+ protected int $epubVersion = 0;
+
+ /**
+ * Constructor
+ *
+ * @param string $file path to epub file to work on
+ * @param string $zipClass class to handle zip - ZipFile is read-only
+ * @throws Exception if metadata could not be loaded
+ */
+ public function __construct($file, $zipClass = ZipFile::class)
+ {
+ if (!is_file($file)) {
+ throw new Exception("Epub file does not exist!");
+ }
+ if (filesize($file) <= 0) {
+ throw new Exception("Epub file is empty!");
+ }
+ // open file
+ $this->file = $file;
+ $this->openZipFile($zipClass);
+
+ // read container data
+ $this->loadMetadata();
+ }
+
+ /**
+ * Summary of openZipFile
+ * @param string $zipClass
+ * @throws \Exception
+ * @return void
+ */
+ public function openZipFile($zipClass)
+ {
+ $this->zip = new $zipClass();
+ if (!$this->zip->Open($this->file)) {
+ throw new Exception('Failed to read epub file');
+ }
+ $this->zipClass = $zipClass;
+ }
+
+ /**
+ * Summary of loadMetadata
+ * @throws \Exception
+ * @return void
+ */
+ public function loadMetadata()
+ {
+ if (!$this->zip->FileExists(static::METADATA_FILE)) {
+ throw new Exception('Unable to find ' . static::METADATA_FILE);
+ }
+
+ $data = $this->zip->FileRead(static::METADATA_FILE);
+ if ($data == false) {
+ throw new Exception('Failed to access epub container data');
+ }
+ $xml = new DOMDocument();
+ $xml->registerNodeClass(DOMElement::class, EpubDomElement::class);
+ $xml->loadXML($data);
+ $xpath = new EpubDomXPath($xml);
+ $nodes = $xpath->query('//n:rootfiles/n:rootfile[@media-type="application/oebps-package+xml"]');
+ $this->meta = static::getAttr($nodes, 'full-path');
+
+ // load metadata
+ if (!$this->zip->FileExists($this->meta)) {
+ throw new Exception('Unable to find ' . $this->meta);
+ }
+
+ $data = $this->zip->FileRead($this->meta);
+ if (!$data) {
+ throw new Exception('Failed to access epub metadata');
+ }
+ $this->loadXmlData($data);
+
+ $this->zipSizeMap = $this->loadSizeMap($this->file);
+ }
+
+ /**
+ * Summary of loadXmlData
+ * @param string $data
+ * @return void
+ */
+ public function loadXmlData($data)
+ {
+ $this->xml = new DOMDocument();
+ $this->xml->registerNodeClass(DOMElement::class, EpubDomElement::class);
+ $this->xml->loadXML($data);
+ $this->xml->formatOutput = true;
+ $this->xpath = new EpubDomXPath($this->xml);
+ }
+
+ /**
+ * Summary of initSpineComponent
+ * @throws \Exception
+ * @return void
+ */
+ public function initSpineComponent()
+ {
+ $nodes = $this->xpath->query('//opf:spine');
+ $tocid = static::getAttr($nodes, 'toc');
+ if (empty($tocid)) {
+ $nodes = $this->xpath->query('//opf:manifest/opf:item[@properties="nav"]');
+ $navhref = static::getAttr($nodes, 'href');
+ $navpath = $this->getFullPath($navhref);
+ // read epub nav doc
+ if (!$this->zip->FileExists($navpath)) {
+ throw new Exception('Unable to find ' . $navpath);
+ }
+ $data = $this->zip->FileRead($navpath);
+ $this->loadNavData($data);
+ return;
+ }
+ $nodes = $this->xpath->query('//opf:manifest/opf:item[@id="' . $tocid . '"]');
+ $tochref = static::getAttr($nodes, 'href');
+ $tocpath = $this->getFullPath($tochref);
+ // read epub toc
+ if (!$this->zip->FileExists($tocpath)) {
+ throw new Exception('Unable to find ' . $tocpath);
+ }
+
+ $data = $this->zip->FileRead($tocpath);
+ $this->loadTocData($data);
+ }
+
+ /**
+ * Summary of loadNavData
+ * @param string $data
+ * @return void
+ */
+ public function loadNavData($data)
+ {
+ $this->nav = new DOMDocument();
+ $this->nav->registerNodeClass(DOMElement::class, EpubDomElement::class);
+ $this->nav->loadXML($data);
+ $this->nav_xpath = new EpubDomXPath($this->nav);
+ $rootNamespace = $this->nav->lookupNamespaceUri($this->nav->namespaceURI);
+ $this->nav_xpath->registerNamespace('x', $rootNamespace);
+ }
+
+ /**
+ * Summary of loadTocData
+ * @param string $data
+ * @return void
+ */
+ public function loadTocData($data)
+ {
+ $this->toc = new DOMDocument();
+ $this->toc->registerNodeClass(DOMElement::class, EpubDomElement::class);
+ $this->toc->loadXML($data);
+ $this->toc_xpath = new EpubDomXPath($this->toc);
+ $rootNamespace = $this->toc->lookupNamespaceUri($this->toc->namespaceURI);
+ $this->toc_xpath->registerNamespace('x', $rootNamespace);
+ }
+
+ /**
+ * Get the ePub version
+ *
+ * @return int The number of the ePub version (2 or 3 for now) or 0 if not found
+ */
+ public function getEpubVersion()
+ {
+ if ($this->epubVersion) {
+ return $this->epubVersion;
+ }
+
+ $this->epubVersion = 0;
+ $nodes = $this->xpath->query('//opf:package[@unique-identifier="BookId"]');
+ if ($nodes->length) {
+ $this->epubVersion = (int) static::getAttr($nodes, 'version');
+ } else {
+ $nodes = $this->xpath->query('//opf:package');
+ if ($nodes->length) {
+ $this->epubVersion = (int) static::getAttr($nodes, 'version');
+ }
+ }
+
+ return $this->epubVersion;
+ }
+
+ /**
+ * file name getter
+ * @return string
+ */
+ public function file()
+ {
+ return $this->file;
+ }
+
+ /**
+ * meta file getter
+ * @return string
+ */
+ public function meta()
+ {
+ return $this->meta;
+ }
+
+ /**
+ * Close the epub file
+ * @return void
+ */
+ public function close()
+ {
+ $this->zip->FileCancelModif($this->meta);
+ // TODO: Add cancelation of cover image
+ $this->zip->Close();
+ }
+
+ /**
+ * Remove iTunes files
+ * @return void
+ */
+ public function cleanITunesCrap()
+ {
+ if ($this->zip->FileExists('iTunesMetadata.plist')) {
+ $this->zip->FileDelete('iTunesMetadata.plist');
+ }
+ if ($this->zip->FileExists('iTunesArtwork')) {
+ $this->zip->FileDelete('iTunesArtwork');
+ }
+ }
+
+ /**
+ * Writes back all meta data changes
+ * @return void
+ */
+ public function save()
+ {
+ $this->download();
+ $this->zip->close();
+ }
+
+ /**
+ * Get the updated epub
+ * @param mixed $file
+ * @param bool $sendHeaders
+ * @return void
+ */
+ public function download($file = false, $sendHeaders = true)
+ {
+ $this->zip->FileReplace($this->meta, $this->xml->saveXML());
+ // add the cover image
+ if ($this->imagetoadd) {
+ $this->zip->FileAddPath($this->coverpath, $this->imagetoadd);
+ $this->imagetoadd = '';
+ }
+ if ($file) {
+ $render = $this->zipClass::DOWNLOAD;
+ $this->zip->Flush($render, $file, static::MIME_TYPE, $sendHeaders);
+ } elseif ($this->zipClass == ZipEdit::class) {
+ $this->zip->SaveBeforeClose();
+ }
+ }
+
+ /**
+ * Get the components list as an array
+ * @return array<mixed>
+ */
+ public function components()
+ {
+ $spine = [];
+ $nodes = $this->xpath->query('//opf:spine/opf:itemref');
+ foreach ($nodes as $node) {
+ /** @var EpubDomElement $node */
+ $idref = $node->getAttribute('idref');
+ /** @var EpubDomElement $item */
+ $item = $this->xpath->query('//opf:manifest/opf:item[@id="' . $idref . '"]')->item(0);
+ $spine[] = $this->encodeComponentName($item->getAttribute('href'));
+ }
+ return $spine;
+ }
+
+ /**
+ * Get the component content
+ * @param mixed $comp
+ * @return mixed
+ */
+ public function component($comp)
+ {
+ $path = $this->decodeComponentName($comp);
+ $path = $this->getFullPath($path);
+ if (!$this->zip->FileExists($path)) {
+ $status = $this->zip->FileGetState($path);
+ throw new Exception('Unable to find ' . $path . ' <' . $comp . '> = ' . $status);
+ }
+
+ $data = $this->zip->FileRead($path);
+ return $data;
+ }
+
+ /**
+ * Summary of getComponentName
+ * @param mixed $comp
+ * @param mixed $elementPath
+ * @return bool|string
+ */
+ public function getComponentName($comp, $elementPath)
+ {
+ $path = $this->decodeComponentName($comp);
+ $path = $this->getFullPath($path, $elementPath);
+ if (!$this->zip->FileExists($path)) {
+ error_log('Unable to find ' . $path);
+ return false;
+ }
+ $ref = dirname('/' . $this->meta);
+ $ref = ltrim($ref, '\\');
+ $ref = ltrim($ref, '/');
+ if (strlen($ref) > 0) {
+ $path = str_replace($ref . '/', '', $path);
+ }
+ return $this->encodeComponentName($path);
+ }
+
+ /**
+ * Encode the component name (to replace / and -)
+ * @param mixed $src
+ * @return string
+ */
+ protected static function encodeComponentName($src)
+ {
+ return str_replace(
+ static::$encodeNameReplace[0],
+ static::$encodeNameReplace[1],
+ $src
+ );
+ }
+
+ /**
+ * Decode the component name (to replace / and -)
+ * @param mixed $src
+ * @return string
+ */
+ protected static function decodeComponentName($src)
+ {
+ return str_replace(
+ static::$decodeNameReplace[0],
+ static::$decodeNameReplace[1],
+ $src
+ );
+ }
+
+
+ /**
+ * Get the component content type
+ * @param mixed $comp
+ * @return string
+ */
+ public function componentContentType($comp)
+ {
+ $comp = $this->decodeComponentName($comp);
+ $nodes = $this->xpath->query('//opf:manifest/opf:item[@href="' . $comp . '"]');
+ if ($nodes->length) {
+ return static::getAttr($nodes, 'media-type');
+ }
+
+ // I had at least one book containing %20 instead of spaces in the opf file
+ $comp = str_replace(' ', '%20', $comp);
+ $nodes = $this->xpath->query('//opf:manifest/opf:item[@href="' . $comp . '"]');
+ if ($nodes->length) {
+ return static::getAttr($nodes, 'media-type');
+ }
+ return 'application/octet-stream';
+ }
+
+ /**
+ * Summary of getComponentSize
+ * @param mixed $comp
+ * @return bool|int
+ */
+ public function getComponentSize($comp)
+ {
+ $path = $this->decodeComponentName($comp);
+ $path = $this->getFullPath($path);
+ if (!$this->zip->FileExists($path)) {
+ error_log('Unable to find ' . $path);
+ return false;
+ }
+
+ $sizeMap = $this->loadSizeMap();
+ return $sizeMap[$path];
+ }
+
+ /**
+ * EPUB 2 navigation control file (NCX format)
+ * See https://idpf.org/epub/20/spec/OPF_2.0_latest.htm#Section2.4.1
+ * @param mixed $node
+ * @return array<string, string>
+ */
+ protected function getNavPointDetail($node)
+ {
+ $title = $this->toc_xpath->query('x:navLabel/x:text', $node)->item(0)->nodeValue;
+ $nodes = $this->toc_xpath->query('x:content', $node);
+ $src = static::getAttr($nodes, 'src');
+ $src = $this->encodeComponentName($src);
+ $item = ['title' => preg_replace('~[\r\n]+~', '', $title), 'src' => $src];
+ $insidenodes = $this->toc_xpath->query('x:navPoint', $node);
+ if (count($insidenodes) < 1) {
+ return $item;
+ }
+ $item['children'] = [];
+ foreach ($insidenodes as $insidenode) {
+ $item['children'][] = $this->getNavPointDetail($insidenode);
+ }
+ return $item;
+ }
+
+ /**
+ * EPUB 3 navigation document (toc nav element)
+ * See https://www.w3.org/TR/epub-33/#sec-nav-toc
+ * @param mixed $node
+ * @return array<string, string>
+ */
+ protected function getNavTocListItem($node)
+ {
+ $nodes = $this->nav_xpath->query('x:a', $node);
+ $title = $nodes->item(0)->nodeValue;
+ $src = static::getAttr($nodes, 'href');
+ $src = $this->encodeComponentName($src);
+ $item = ['title' => preg_replace('~[\r\n]+~', '', $title), 'src' => $src];
+ $insidenodes = $this->nav_xpath->query('x:ol/x:li', $node);
+ if (count($insidenodes) < 1) {
+ return $item;
+ }
+ $item['children'] = [];
+ foreach ($insidenodes as $insidenode) {
+ $item['children'][] = $this->getNavTocListItem($insidenode);
+ }
+ return $item;
+ }
+
+ /**
+ * Get the Epub content (TOC) as an array
+ *
+ * For each chapter there is a "title" and a "src", and optional "children"
+ * See https://github.com/joseph/Monocle/wiki/Book-data-object for details
+ * @return mixed
+ */
+ public function contents()
+ {
+ $contents = [];
+ if (!empty($this->nav)) {
+ $toc = $this->nav_xpath->query('//x:nav[@epub:type="toc"]')->item(0);
+ $nodes = $this->nav_xpath->query('x:ol/x:li', $toc);
+ foreach ($nodes as $node) {
+ $contents[] = $this->getNavTocListItem($node);
+ }
+ return $contents;
+ }
+ $nodes = $this->toc_xpath->query('//x:ncx/x:navMap/x:navPoint');
+ foreach ($nodes as $node) {
+ $contents[] = $this->getNavPointDetail($node);
+ }
+ return $contents;
+ }
+
+ /**
+ * Set the book author(s)
+ *
+ * Authors should be given with a "file-as" and a real name. The file as
+ * is used for sorting in e-readers.
+ *
+ * Example:
+ *
+ * array(
+ * 'Pratchett, Terry' => 'Terry Pratchett',
+ * 'Simpson, Jacqueline' => 'Jacqueline Simpson',
+ * )
+ *
+ * @param mixed $authors
+ * @return void
+ */
+ public function setAuthors($authors)
+ {
+ // Author where given as a comma separated list
+ if (is_string($authors)) {
+ if ($authors == '') {
+ $authors = [];
+ } else {
+ $authors = explode(',', $authors);
+ $authors = array_map('trim', $authors);
+ }
+ }
+
+ // delete existing nodes
+ $nodes = $this->xpath->query('//opf:metadata/dc:creator[@opf:role="aut"]');
+ static::deleteNodes($nodes);
+
+ // add new nodes
+ /** @var EpubDomElement $parent */
+ $parent = $this->xpath->query('//opf:metadata')->item(0);
+ foreach ($authors as $as => $name) {
+ if (is_int($as)) {
+ $as = $name; //numeric array given
+ }
+ $node = $parent->newChild('dc:creator', $name);
+ $node->setAttrib('opf:role', 'aut');
+ $node->setAttrib('opf:file-as', $as);
+ }
+
+ $this->reparse();
+ }
+
+ /**
+ * Get the book author(s)
+ * @return array<string>
+ */
+ public function getAuthors()
+ {
+ $rolefix = false;
+ $authors = [];
+ $nodes = $this->xpath->query('//opf:metadata/dc:creator[@opf:role="aut"]');
+ if ($nodes->length == 0) {
+ // no nodes where found, let's try again without role
+ $nodes = $this->xpath->query('//opf:metadata/dc:creator');
+ $rolefix = true;
+ }
+ foreach ($nodes as $node) {
+ /** @var EpubDomElement $node */
+ $name = $node->nodeValue;
+ $as = $node->getAttrib('opf:file-as');
+ if (!$as) {
+ $as = $name;
+ $node->setAttrib('opf:file-as', $as);
+ }
+ if ($rolefix) {
+ $node->setAttrib('opf:role', 'aut');
+ }
+ $authors[$as] = $name;
+ }
+ return $authors;
+ }
+
+ /**
+ * Set or get the Google Books ID
+ *
+ * @param string|bool $google
+ * @return mixed
+ */
+ public function Google($google = false)
+ {
+ return $this->getset('dc:identifier', $google, 'opf:scheme', 'GOOGLE');
+ }
+
+ /**
+ * Set or get the Amazon ID of the book
+ *
+ * @param string|bool $amazon
+ * @return mixed
+ */
+ public function Amazon($amazon = false)
+ {
+ return $this->getset('dc:identifier', $amazon, 'opf:scheme', 'AMAZON');
+ }
+
+ /**
+ * Set the Series of the book
+ *
+ * @param string $serie
+ * @return void
+ */
+ public function setSeries($serie)
+ {
+ $this->setMetaDestination('opf:meta', 'name', 'calibre:series', 'content', $serie);
+ }
+
+ /**
+ * Get the Series of the book
+ *
+ * @return mixed
+ */
+ public function getSeries()
+ {
+ return $this->getMetaDestination('opf:meta', 'name', 'calibre:series', 'content');
+ }
+
+ /**
+ * Set the Series Index of the book
+ *
+ * @param string $seriesIndex
+ * @return void
+ */
+ public function setSeriesIndex($seriesIndex)
+ {
+ $this->setMetaDestination('opf:meta', 'name', 'calibre:series_index', 'content', $seriesIndex);
+ }
+
+ /**
+ * Get the Series Index of the book
+ *
+ * @return mixed
+ */
+ public function getSeriesIndex()
+ {
+ return $this->getMetaDestination('opf:meta', 'name', 'calibre:series_index', 'content');
+ }
+
+ /**
+ * Set the book's subjects (aka. tags)
+ *
+ * Subject should be given as array, but a comma separated string will also
+ * be accepted.
+ *
+ * @param array<string>|string $subjects
+ * @return void
+ */
+ public function setSubjects($subjects)
+ {
+ if (is_string($subjects)) {
+ if ($subjects === '') {
+ $subjects = [];
+ } else {
+ $subjects = explode(',', $subjects);
+ $subjects = array_map('trim', $subjects);
+ }
+ }
+
+ // delete previous
+ $nodes = $this->xpath->query('//opf:metadata/dc:subject');
+ static::deleteNodes($nodes);
+ // add new ones
+ $parent = $this->xpath->query('//opf:metadata')->item(0);
+ foreach ($subjects as $subj) {
+ $node = $this->xml->createElement('dc:subject', htmlspecialchars($subj));
+ $node = $parent->appendChild($node);
+ }
+
+ $this->reparse();
+ }
+
+ /**
+ * Get the book's subjects (aka. tags)
+ * @return array<mixed>
+ */
+ public function getSubjects()
+ {
+ $subjects = [];
+ $nodes = $this->xpath->query('//opf:metadata/dc:subject');
+ foreach ($nodes as $node) {
+ $subjects[] = $node->nodeValue;
+ }
+ return $subjects;
+ }
+
+ /**
+ * Update the cover data
+ *
+ * When adding a new image this function return no or old data because the
+ * image contents are not in the epub file, yet. The image will be added when
+ * the save() method is called.
+ *
+ * @param string $path local filesystem path to a new cover image
+ * @param string $mime mime type of the given file
+ * @return void
+ */
+ public function setCoverInfo($path, $mime)
+ {
+ // remove current pointer
+ $nodes = $this->xpath->query('//opf:metadata/opf:meta[@name="cover"]');
+ static::deleteNodes($nodes);
+ // remove previous manifest entries if they where made by us
+ $nodes = $this->xpath->query('//opf:manifest/opf:item[@id="' . static::COVER_ID . '"]');
+ static::deleteNodes($nodes);
+
+ // add pointer
+ /** @var EpubDomElement $parent */
+ $parent = $this->xpath->query('//opf:metadata')->item(0);
+ $node = $parent->newChild('opf:meta');
+ $node->setAttrib('opf:name', 'cover');
+ $node->setAttrib('opf:content', static::COVER_ID);
+
+ // add manifest
+ /** @var EpubDomElement $parent */
+ $parent = $this->xpath->query('//opf:manifest')->item(0);
+ $node = $parent->newChild('opf:item');
+ $node->setAttrib('id', static::COVER_ID);
+ $node->setAttrib('opf:href', static::COVER_ID . '.img');
+ $node->setAttrib('opf:media-type', $mime);
+
+ // remember path for save action
+ $this->imagetoadd = $path;
+ $this->coverpath = $this->getFullPath(static::COVER_ID . '.img');
+
+ $this->reparse();
+ }
+
+ /**
+ * Read the cover data
+ *
+ * Returns an associative array with the following keys:
+ *
+ * mime - filetype (usually image/jpeg)
+ * data - the binary image data
+ * found - the internal path, or false if no image is set in epub
+ *
+ * When no image is set in the epub file, the binary data for a transparent
+ * GIF pixel is returned.
+ *
+ * @return array<mixed>
+ */
+ public function getCoverInfo()
+ {
+ $item = $this->getCoverItem();
+ if (!$item) {
+ return $this->no_cover();
+ }
+
+ $mime = $item->getAttrib('opf:media-type');
+ $path = $item->getAttrib('opf:href');
+ $path = dirname('/' . $this->meta) . '/' . $path; // image path is relative to meta file
+ $path = ltrim($path, '/');
+
+ $zip = new ZipArchive();
+ if (!@$zip->open($this->file)) {
+ throw new Exception('Failed to read epub file');
+ }
+ $data = $zip->getFromName($path);
+
+ return [
+ 'mime' => $mime,
+ 'data' => $data,
+ 'found' => $path,
+ ];
+ }
+
+ /**
+ * Summary of getCoverId
+ * @return string|null
+ */
+ public function getCoverId()
+ {
+ $nodes = $this->xpath->query('//opf:metadata/opf:meta[@name="cover"]');
+ if (!$nodes->length) {
+ return null;
+ }
+
+ $coverid = (string) static::getAttr($nodes, 'opf:content');
+ if (!$coverid) {
+ return null;
+ }
+
+ return $coverid;
+ }
+
+ /**
+ * Summary of getCoverItem
+ * @return EpubDomElement|null
+ */
+ public function getCoverItem()
+ {
+ $coverid = $this->getCoverId();
+ if (!$coverid) {
+ return null;
+ }
+
+ $nodes = $this->xpath->query('//opf:manifest/opf:item[@id="' . $coverid . '"]');
+ if (!$nodes->length) {
+ return null;
+ }
+
+ /** @var EpubDomElement $node */
+ $node = $nodes->item(0);
+ return $node;
+ }
+
+ /**
+ * Get the internal path of the cover image file.
+ *
+ * @return string|null
+ */
+ public function getCoverPath()
+ {
+ $item = $this->getCoverItem();
+ if (!$item) {
+ return null;
+ }
+
+ return $item->getAttrib('opf:href');
+ }
+
+ /**
+ * Summary of Combine
+ * @param mixed $a
+ * @param mixed $b
+ * @throws \InvalidArgumentException
+ * @return string
+ */
+ public static function Combine($a, $b)
+ {
+ $isAbsolute = false;
+ if ($a[0] == '/') {
+ $isAbsolute = true;
+ }
+
+ if ($b[0] == '/') {
+ throw new InvalidArgumentException('Second path part must not start with /');
+ }
+
+ $splittedA = preg_split('#/#', $a);
+ $splittedB = preg_split('#/#', $b);
+
+ $pathParts = [];
+ $mergedPath = array_merge($splittedA, $splittedB);
+
+ foreach ($mergedPath as $item) {
+ if ($item == null || $item == '' || $item == '.') {
+ continue;
+ }
+
+ if ($item == '..') {
+ array_pop($pathParts);
+ continue;
+ }
+
+ array_push($pathParts, $item);
+ }
+
+ $path = implode('/', $pathParts);
+ if ($isAbsolute) {
+ return('/' . $path);
+ } else {
+ return($path);
+ }
+ }
+
+ /**
+ * Summary of getFullPath
+ * @param mixed $file
+ * @param mixed $context
+ * @return string
+ */
+ protected function getFullPath($file, $context = null)
+ {
+ $path = dirname('/' . $this->meta) . '/' . $file;
+ $path = ltrim($path, '\\');
+ $path = ltrim($path, '/');
+ if (!empty($context)) {
+ $path = $this->combine(dirname($path), $context);
+ }
+ //error_log ("FullPath : $path ($file / $context)");
+ return $path;
+ }
+
+ /**
+ * Summary of updateForKepub
+ * @return void
+ */
+ public function updateForKepub()
+ {
+ $item = $this->getCoverItem();
+ if (!is_null($item)) {
+ $item->setAttrib('opf:properties', 'cover-image');
+ }
+ }
+
+ /**
+ * Summary of setCoverFile
+ * @param string $path
+ * @param string $mime
+ * @return array<mixed>|void
+ */
+ public function setCoverFile($path, $mime)
+ {
+ $hascover = true;
+ $item = $this->getCoverItem();
+ if (is_null($item)) {
+ $hascover = false;
+ return; // TODO For now only update
+ } else {
+ $mime = $item->getAttrib('opf:media-type');
+ $this->coverpath = $item->getAttrib('opf:href');
+ $this->coverpath = dirname('/' . $this->meta) . '/' . $this->coverpath; // image path is relative to meta file
+ $this->coverpath = ltrim($this->coverpath, '\\');
+ $this->coverpath = ltrim($this->coverpath, '/');
+ }
+
+ // set cover
+
+ $item->setAttrib('opf:media-type', $mime);
+
+ // remember path for save action
+ $this->imagetoadd = $path;
+
+ $this->reparse();
+
+ // not very useful here, but data gets added in download() if needed
+ return [
+ 'data' => null,
+ 'mime' => $mime,
+ 'found' => $this->coverpath,
+ ];
+ }
+
+ /**
+ * Summary of getAttr
+ * @param DOMNodeList<EpubDomElement> $nodes list of Element items
+ * @param string $att Attribute name
+ * @return string
+ */
+ protected static function getAttr($nodes, $att)
+ {
+ $node = $nodes->item(0);
+ return $node->getAttrib($att);
+ }
+
+ /**
+ * Summary of deleteNodes
+ * @param DOMNodeList<EpubDomElement> $nodes list of Element items
+ * @return void
+ */
+ protected static function deleteNodes($nodes)
+ {
+ foreach ($nodes as $node) {
+ $node->delete();
+ }
+ }
+
+ /**
+ * A simple getter/setter for simple meta attributes
+ *
+ * It should only be used for attributes that are expected to be unique
+ *
+ * @param string $item XML node to set/get
+ * @param string|bool $value New node value
+ * @param string|bool $att Attribute name
+ * @param string|bool|array<mixed> $aval Attribute value
+ * @param string|bool $datt Destination attribute
+ * @return string|void
+ */
+ protected function getset($item, $value = false, $att = false, $aval = false, $datt = false)
+ {
+ // construct xpath
+ $xpath = '//opf:metadata/' . $item;
+ if ($att) {
+ if (is_array($aval)) {
+ $xpath .= '[@' . $att . '="';
+ $xpath .= implode("\" or @$att=\"", $aval);
+ $xpath .= '"]';
+ } else {
+ $xpath .= '[@' . $att . '="' . $aval . '"]';
+ }
+ }
+
+ // set value
+ if ($value !== false) {
+ $value = htmlspecialchars($value);
+ $nodes = $this->xpath->query($xpath);
+ if ($nodes->length == 1) {
+ /** @var EpubDomElement $node */
+ $node = $nodes->item(0);
+ if ($value === '') {
+ // the user want's to empty this value -> delete the node
+ $node->delete();
+ } else {
+ // replace value
+ if ($datt) {
+ $node->setAttrib($datt, $value);
+ } else {
+ $node->nodeValue = $value;
+ }
+ }
+ } else {
+ // if there are multiple matching nodes for some reason delete
+ // them. we'll replace them all with our own single one
+ static::deleteNodes($nodes);
+ // readd them
+ if ($value) {
+ /** @var EpubDomElement $parent */
+ $parent = $this->xpath->query('//opf:metadata')->item(0);
+
+ $node = $parent->newChild($item);
+ if ($att) {
+ $node->setAttrib($att, $aval);
+ }
+ if ($datt) {
+ $node->setAttrib($datt, $value);
+ } else {
+ $node->nodeValue = $value;
+ }
+ }
+ }
+
+ $this->reparse();
+ }
+
+ // get value
+ $nodes = $this->xpath->query($xpath);
+ if ($nodes->length) {
+ /** @var EpubDomElement $node */
+ $node = $nodes->item(0);
+ if ($datt) {
+ return $node->getAttrib($datt);
+ } else {
+ return $node->nodeValue;
+ }
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * Return a not found response for Cover()
+ * @return array<string, mixed>
+ */
+ protected function no_cover()
+ {
+ return [
+ 'data' => base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'),
+ 'mime' => 'image/gif',
+ 'found' => false,
+ ];
+ }
+
+ /**
+ * Reparse the DOM tree
+ *
+ * I had to rely on this because otherwise xpath failed to find the newly
+ * added nodes
+ * @return void
+ */
+ protected function reparse()
+ {
+ $this->xml->loadXML($this->xml->saveXML());
+ $this->xpath = new EpubDomXPath($this->xml);
+ // reset structural members
+ $this->manifest = null;
+ $this->spine = null;
+ $this->tocnav = null;
+ }
+
+ /** based on slightly more updated version at https://github.com/epubli/epub */
+
+ /**
+ * A simple setter for simple meta attributes
+ *
+ * It should only be used for attributes that are expected to be unique
+ *
+ * @param string $item XML node to set
+ * @param string $value New node value
+ * @param bool|string $attribute Attribute name
+ * @param bool|string $attributeValue Attribute value
+ * @param bool $caseSensitive
+ * @return mixed
+ */
+ protected function setMeta($item, $value, $attribute = false, $attributeValue = false, $caseSensitive = true)
+ {
+ /**
+ if ($attributeValue !== false && !$caseSensitive) {
+ $attval = is_array($attributeValue) ? $attributeValue : [ $attributeValue ];
+ $vallist = [];
+ foreach ($attval as $val) {
+ $vallist[] = strtoupper($val);
+ $vallist[] = strtolower($val);
+ }
+ $attributeValue = $vallist;
+ }
+ */
+ return $this->getset($item, $value, $attribute, $attributeValue);
+ }
+
+ /**
+ * A simple getter for simple meta attributes
+ *
+ * It should only be used for attributes that are expected to be unique
+ *
+ * @param string $item XML node to get
+ * @param bool|string $att Attribute name
+ * @param bool|string $aval Attribute value
+ * @param bool $caseSensitive
+ * @return string
+ */
+ protected function getMeta($item, $att = false, $aval = false, $caseSensitive = true)
+ {
+ /**
+ if ($aval !== false && !$caseSensitive) {
+ $attval = is_array($aval) ? $aval : [ $aval ];
+ $vallist = [];
+ foreach ($attval as $val) {
+ $vallist[] = strtoupper($val);
+ $vallist[] = strtolower($val);
+ }
+ $aval = $vallist;
+ }
+ */
+ return $this->getset($item, false, $att, $aval);
+ }
+
+ /**
+ * A simple setter for simple meta attributes - with destination attribute (for Serie)
+ *
+ * It should only be used for attributes that are expected to be unique
+ *
+ * @param string $item XML node to set
+ * @param string $attribute Attribute name
+ * @param string $attributeValue Attribute value
+ * @param string $datt Destination attribute
+ * @param string $value New node value
+ * @return mixed
+ */
+ protected function setMetaDestination($item, $attribute, $attributeValue, $datt, $value)
+ {
+ return $this->getset($item, $value, $attribute, $attributeValue, $datt);
+ }
+
+ /**
+ * A simple getter for simple meta attributes - with destination attribute (for Serie)
+ *
+ * It should only be used for attributes that are expected to be unique
+ *
+ * @param string $item XML node to get
+ * @param string $att Attribute name
+ * @param string $aval Attribute value
+ * @param string $datt Destination attribute
+ * @return string
+ */
+ protected function getMetaDestination($item, $att, $aval, $datt)
+ {
+ return $this->getset($item, false, $att, $aval, $datt);
+ }
+
+ /**
+ * Set the book title
+ *
+ * @param string $title
+ * @return mixed
+ */
+ public function setTitle($title)
+ {
+ return $this->getset('dc:title', $title);
+ }
+
+ /**
+ * Get the book title
+ *
+ * @return mixed
+ */
+ public function getTitle()
+ {
+ return $this->getset('dc:title');
+ }
+
+ /**
+ * Set the book's language
+ *
+ * @param string $lang
+ * @return mixed
+ */
+ public function setLanguage($lang)
+ {
+ return $this->getset('dc:language', $lang);
+ }
+
+ /**
+ * Get the book's language
+ *
+ * @return mixed
+ */
+ public function getLanguage()
+ {
+ return $this->getset('dc:language');
+ }
+
+ /**
+ * Set the book's publisher info
+ *
+ * @param string $publisher
+ * @return void
+ */
+ public function setPublisher($publisher)
+ {
+ $this->setMeta('dc:publisher', $publisher);
+ }
+
+ /**
+ * Get the book's publisher info
+ *
+ * @return string
+ */
+ public function getPublisher()
+ {
+ return $this->getMeta('dc:publisher');
+ }
+
+ /**
+ * Set the book's copyright info
+ *
+ * @param string $rights
+ * @return void
+ */
+ public function setCopyright($rights)
+ {
+ $this->setMeta('dc:rights', $rights);
+ }
+
+ /**
+ * Get the book's copyright info
+ *
+ * @return string
+ */
+ public function getCopyright()
+ {
+ return $this->getMeta('dc:rights');
+ }
+
+ /**
+ * Set the book's description
+ *
+ * @param string $description
+ * @return void
+ */
+ public function setDescription($description)
+ {
+ $this->setMeta('dc:description', $description);
+ }
+
+ /**
+ * Get the book's description
+ *
+ * @return string
+ */
+ public function getDescription()
+ {
+ return $this->getMeta('dc:description');
+ }
+
+ /**
+ * Set a date for an event in the package file’s meta section.
+ *
+ * @param string $event
+ * @param string $date Date eg: 2012-05-19T12:54:25Z
+ * @return void
+ */
+ public function setEventDate($event, $date)
+ {
+ $this->getset('dc:date', $date, 'opf:event', $event);
+ }
+
+ /**
+ * Get a date for an event in the package file’s meta section.
+ *
+ * @param string $event
+ * @return mixed
+ */
+ public function getEventDate($event)
+ {
+ $res = $this->getset('dc:date', false, 'opf:event', $event);
+
+ return $res;
+ }
+
+ /**
+ * Set the book's creation date
+ *
+ * @param string $date Date eg: 2012-05-19T12:54:25Z
+ * @return void
+ */
+ public function setCreationDate($date)
+ {
+ $this->setEventDate('creation', $date);
+ }
+
+ /**
+ * Get the book's creation date
+ *
+ * @return mixed
+ */
+ public function getCreationDate()
+ {
+ $res = $this->getEventDate('creation');
+
+ return $res;
+ }
+
+ /**
+ * Set the book's modification date
+ *
+ * @param string $date Date eg: 2012-05-19T12:54:25Z
+ * @return void
+ */
+ public function setModificationDate($date)
+ {
+ $this->setEventDate('modification', $date);
+ }
+
+ /**
+ * Get the book's modification date
+ *
+ * @return mixed
+ */
+ public function getModificationDate()
+ {
+ $res = $this->getEventDate('modification');
+
+ return $res;
+ }
+
+ /**
+ * Set an identifier in the package file’s meta section.
+ *
+ * @param string|array<string> $idScheme The identifier’s scheme. If an array is given
+ * all matching identifiers are replaced by one with the first value as scheme.
+ * @param string $value
+ * @param bool $caseSensitive
+ * @return void
+ */
+ public function setIdentifier($idScheme, $value, $caseSensitive = false)
+ {
+ $this->setMeta('dc:identifier', $value, 'opf:scheme', $idScheme, $caseSensitive);
+ }
+
+ /**
+ * Set an identifier from the package file’s meta section.
+ *
+ * @param string|array<string> $idScheme The identifier’s scheme. If an array is given
+ * the scheme can be any of its values.
+ * @param bool $caseSensitive - @todo changed to true here
+ * @return string The value of the first matching element.
+ */
+ public function getIdentifier($idScheme, $caseSensitive = true)
+ {
+ return $this->getMeta('dc:identifier', 'opf:scheme', $idScheme, $caseSensitive);
+ }
+
+ /**
+ * Set the book's unique identifier
+ *
+ * @param string $value
+ * @return void
+ */
+ public function setUniqueIdentifier($value)
+ {
+ //$nodes = $this->xpath->query('/opf:package');
+ $idRef = $this->xpath->document->documentElement->getAttribute('unique-identifier');
+ $this->setMeta('dc:identifier', $value, 'id', $idRef);
+ }
+
+ /**
+ * Get the book's unique identifier
+ *
+ * @param bool $normalize
+ * @return string
+ */
+ public function getUniqueIdentifier($normalize = false)
+ {
+ //$nodes = $this->xpath->query('/opf:package');
+ $idRef = $this->xpath->document->documentElement->getAttribute('unique-identifier');
+ $idVal = $this->getMeta('dc:identifier', 'id', $idRef);
+ if ($normalize) {
+ $idVal = strtolower($idVal);
+ $idVal = str_replace('urn:uuid:', '', $idVal);
+ }
+
+ return $idVal;
+ }
+
+ /**
+ * Set the book's UUID - @todo pick one + case sensitive
+ *
+ * @param string $uuid
+ * @return void
+ */
+ public function setUuid($uuid)
+ {
+ //$this->setIdentifier(['UUID', 'uuid', 'URN', 'urn'], $uuid);
+ $this->setIdentifier('URN', $uuid);
+ }
+
+ /**
+ * Get the book's UUID - @todo pick one + case sensitive
+ *
+ * @return string
+ */
+ public function getUuid()
+ {
+ //return $this->getIdentifier(['uuid', 'urn']);
+ return $this->getIdentifier(['UUID', 'URN']);
+ }
+
+ /**
+ * Set the book's URI
+ *
+ * @param string $uri
+ * @return void
+ */
+ public function setUri($uri)
+ {
+ $this->setIdentifier('URI', $uri);
+ }
+
+ /**
+ * Get the book's URI
+ *
+ * @return string
+ */
+ public function getUri()
+ {
+ return $this->getIdentifier('URI');
+ }
+
+ /**
+ * Set the book's ISBN
+ *
+ * @param string $isbn
+ * @return void
+ */
+ public function setIsbn($isbn)
+ {
+ $this->setIdentifier('ISBN', $isbn);
+ }
+
+ /**
+ * Get the book's ISBN
+ *
+ * @return string
+ */
+ public function getIsbn()
+ {
+ return $this->getIdentifier('ISBN');
+ }
+
+ /**
+ * Set the Calibre UUID of the book
+ *
+ * @param string $uuid
+ * @return void
+ */
+ public function setCalibre($uuid)
+ {
+ $this->setIdentifier('calibre', $uuid);
+ }
+
+ /**
+ * Get the Calibre UUID of the book
+ *
+ * @return string
+ */
+ public function getCalibre()
+ {
+ return $this->getIdentifier('calibre');
+ }
+
+ /**
+ * Remove the cover image
+ *
+ * If the actual image file was added by this library it will be removed. Otherwise only the
+ * reference to it is removed from the metadata, since the same image might be referenced
+ * by other parts of the EPUB file.
+ * @return void
+ */
+ public function clearCover()
+ {
+ if (!$this->hasCover()) {
+ return;
+ }
+
+ $manifest = $this->getManifest();
+
+ // remove any cover image file added by us
+ if (isset($manifest[static::COVER_ID])) {
+ $name = $this->getFullPath(static::COVER_ID . '.img');
+ if (!$this->zip->FileDelete($name)) {
+ throw new Exception('Unable to remove ' . $name);
+ }
+ }
+
+ // remove metadata cover pointer
+ $nodes = $this->xpath->query('//opf:metadata/opf:meta[@name="cover"]');
+ static::deleteNodes($nodes);
+
+ // remove previous manifest entries if they where made by us
+ $nodes = $this->xpath->query('//opf:manifest/opf:item[@id="' . static::COVER_ID . '"]');
+ static::deleteNodes($nodes);
+
+ $this->reparse();
+ }
+
+ /**
+ * Set the cover image
+ *
+ * @param string $path local filesystem path to a new cover image
+ * @param string $mime mime type of the given file
+ * @return void
+ */
+ public function setCover($path, $mime)
+ {
+ if (!$path) {
+ throw new InvalidArgumentException('Parameter $path must not be empty!');
+ }
+
+ if (!is_readable($path)) {
+ throw new InvalidArgumentException("Cannot add $path as new cover image since that file is not readable!");
+ }
+
+ $this->clearCover();
+
+ // add metadata cover pointer
+ /** @var EpubDomElement $parent */
+ $parent = $this->xpath->query('//opf:metadata')->item(0);
+ $node = $parent->newChild('opf:meta');
+ $node->setAttrib('opf:name', 'cover');
+ $node->setAttrib('opf:content', static::COVER_ID);
+
+ // add manifest item
+ /** @var EpubDomElement $parent */
+ $parent = $this->xpath->query('//opf:manifest')->item(0);
+ $node = $parent->newChild('opf:item');
+ $node->setAttrib('id', static::COVER_ID);
+ $node->setAttrib('opf:href', static::COVER_ID . '.img');
+ $node->setAttrib('opf:media-type', $mime);
+
+ // add the cover image
+ $name = $this->getFullPath(static::COVER_ID . '.img');
+ if (!$this->zip->FileAddPath($name, $path)) {
+ throw new Exception('Unable to add ' . $name);
+ }
+
+ $this->reparse();
+ }
+
+ /**
+ * Get the cover image
+ *
+ * @return string|null The binary image data or null if no image exists.
+ */
+ public function getCover()
+ {
+ $comp = $this->getCoverPath();
+
+ return $comp ? $this->component($comp) : null;
+ }
+
+ /**
+ * Whether a cover image meta entry does exist.
+ *
+ * @return bool
+ */
+ public function hasCover()
+ {
+ return !empty($this->getCoverId());
+ }
+
+ /**
+ * Add a title page with the cover image to the EPUB.
+ *
+ * @param string $templatePath The path to the template file. Defaults to an XHTML file contained in this library.
+ * @return void
+ */
+ public function addCoverImageTitlePage($templatePath = __DIR__ . '/../templates/titlepage.xhtml')
+ {
+ $xhtmlFilename = static::TITLE_PAGE_ID . '.xhtml';
+
+ // add title page file to zip
+ $template = file_get_contents($templatePath);
+ $xhtml = strtr($template, ['{{ title }}' => $this->getTitle(), '{{ coverPath }}' => $this->getCoverPath()]);
+ $name = $this->getFullPath($xhtmlFilename);
+ if (!$this->zip->FileReplace($name, $xhtml)) {
+ throw new Exception('Unable to replace ' . $name);
+ }
+
+ // prepend title page file to manifest
+ $parent = $this->xpath->query('//opf:manifest')->item(0);
+ $node = new EpubDomElement('opf:item');
+ $parent->insertBefore($node, $parent->firstChild);
+ $node->setAttrib('id', static::TITLE_PAGE_ID);
+ $node->setAttrib('opf:href', $xhtmlFilename);
+ $node->setAttrib('opf:media-type', 'application/xhtml+xml');
+
+ // prepend title page spine item
+ $parent = $this->xpath->query('//opf:spine')->item(0);
+ $node = new EpubDomElement('opf:itemref');
+ $parent->insertBefore($node, $parent->firstChild);
+ $node->setAttrib('idref', static::TITLE_PAGE_ID);
+
+ // prepend title page guide reference
+ $parent = $this->xpath->query('//opf:guide')->item(0);
+ $node = new EpubDomElement('opf:reference');
+ $parent->insertBefore($node, $parent->firstChild);
+ $node->setAttrib('opf:href', $xhtmlFilename);
+ $node->setAttrib('opf:type', 'cover');
+ $node->setAttrib('opf:title', 'Title Page');
+ }
+
+ /**
+ * Remove the title page added by this library (determined by a certain manifest item ID).
+ * @return void
+ */
+ public function removeTitlePage()
+ {
+ $xhtmlFilename = static::TITLE_PAGE_ID . '.xhtml';
+
+ // remove title page file from zip
+ $name = $this->getFullPath($xhtmlFilename);
+ if (!$this->zip->FileDelete($name)) {
+ throw new Exception('Unable to remove ' . $name);
+ }
+
+ // remove title page file from manifest
+ $nodes = $this->xpath->query('//opf:manifest/opf:item[@id="' . static::TITLE_PAGE_ID . '"]');
+ static::deleteNodes($nodes);
+
+ // remove title page spine item
+ $nodes = $this->xpath->query('//opf:spine/opf:itemref[@idref="' . static::TITLE_PAGE_ID . '"]');
+ static::deleteNodes($nodes);
+
+ // remove title page guide reference
+ $nodes = $this->xpath->query('//opf:guide/opf:reference[@href="' . $xhtmlFilename . '"]');
+ static::deleteNodes($nodes);
+ }
+
+ /**
+ * Get the Calibre book annotations from opf:metadata (if saved)
+ * @param ?string $data
+ * @return array<mixed>
+ */
+ public function getCalibreAnnotations($data = null)
+ {
+ if (!empty($data)) {
+ $this->loadXmlData($data);
+ }
+ $annotations = [];
+ $nodes = $this->xpath->query('//opf:metadata/opf:meta[@name="calibre:annotation"]');
+ if ($nodes->length == 0) {
+ return $annotations;
+ }
+ foreach ($nodes as $node) {
+ /** @var EpubDomElement $node */
+ $content = $node->getAttribute('content');
+ try {
+ $annotations[] = json_decode($content, true, 512, JSON_THROW_ON_ERROR);
+ } catch (JsonException $e) {
+ $annotations[] = $content;
+ }
+ }
+ return $annotations;
+ }
+
+ /**
+ * Get the Calibre bookmarks from META-INF/calibre_bookmarks.txt (if saved)
+ * @param ?string $data
+ * @return array<mixed>
+ */
+ public function getCalibreBookmarks($data = null)
+ {
+ if (empty($data)) {
+ if (!$this->zip->FileExists(static::BOOKMARK_FILE)) {
+ throw new Exception('Unable to find ' . static::BOOKMARK_FILE);
+ }
+ $data = $this->zip->FileRead(static::BOOKMARK_FILE);
+ if ($data == false) {
+ throw new Exception('Failed to access epub bookmark file');
+ }
+ }
+ if (!str_starts_with($data, static::EPUB_FILE_TYPE_MAGIC)) {
+ throw new Exception('Invalid format for epub bookmark file');
+ }
+ $content = substr($data, strlen(static::EPUB_FILE_TYPE_MAGIC));
+ $content = base64_decode($content);
+ try {
+ $bookmarks = json_decode($content, true, 512, JSON_THROW_ON_ERROR);
+ } catch (JsonException $e) {
+ $bookmarks = $content;
+ }
+ return $bookmarks;
+ }
+
+ /**
+ * Get the manifest of this EPUB.
+ *
+ * @return Manifest
+ * @throws Exception
+ */
+ public function getManifest()
+ {
+ if ($this->manifest) {
+ return $this->manifest;
+ }
+
+ /** @var EpubDomElement|null $manifestNode */
+ $manifestNode = $this->xpath->query('//opf:manifest')->item(0);
+ if (is_null($manifestNode)) {
+ throw new Exception('No manifest element found in EPUB!');
+ }
+
+ $this->manifest = new Manifest();
+ /** @var EpubDomElement $item */
+ foreach ($manifestNode->getElementsByTagName('item') as $item) {
+ $id = $item->getAttribute('id');
+ $href = urldecode($item->getAttribute('href'));
+ $fullPath = $this->getFullPath($href);
+ // this won't work with clsTbsZip - $this->zip->getStream($fullPath);
+ //$handle = $this->zip->FileStream($fullPath);
+ $callable = function () use ($fullPath) {
+ // Automatic binding of $this
+ return $this->zip->FileRead($fullPath);
+ };
+ $size = $this->zipSizeMap[$fullPath] ?? 0;
+ $mediaType = $item->getAttribute('media-type');
+ $this->manifest->createItem($id, $href, $callable, $size, $mediaType);
+ }
+
+ return $this->manifest;
+ }
+
+ /**
+ * Get the spine structure of this EPUB.
+ *
+ * @return Spine
+ * @throws Exception
+ */
+ public function getSpine()
+ {
+ if ($this->spine) {
+ return $this->spine;
+ }
+
+ $nodes = $this->xpath->query('//opf:spine');
+ if (!$nodes->length) {
+ throw new Exception('No spine element found in EPUB!');
+ }
+ $tocId = static::getAttr($nodes, 'toc');
+ $tocFormat = Toc::class;
+ if (empty($tocId)) {
+ $nodes = $this->xpath->query('//opf:manifest/opf:item[@properties="nav"]');
+ $tocId = static::getAttr($nodes, 'id');
+ $tocFormat = Nav::class;
+ }
+
+ $manifest = $this->getManifest();
+
+ if (!isset($manifest[$tocId])) {
+ throw new Exception('TOC or NAV item referenced in spine missing in manifest!');
+ }
+
+ $this->spine = new Spine($manifest[$tocId], $tocFormat);
+
+ /** @var EpubDomElement $spineNode */
+ $spineNode = $this->xpath->query('//opf:spine')->item(0);
+
+ $itemRefNodes = $spineNode->getElementsByTagName('itemref');
+ foreach ($itemRefNodes as $itemRef) {
+ /** @var EpubDomElement $itemRef */
+ $id = $itemRef->getAttribute('idref');
+ if (!isset($manifest[$id])) {
+ throw new Exception("Item $id referenced in spine missing in manifest!");
+ }
+ // Link the item from the manifest to the spine.
+ $this->spine->appendItem($manifest[$id]);
+ }
+
+ return $this->spine;
+ }
+
+ /**
+ * Get the table of contents structure of this EPUB.
+ *
+ * @return Toc|Nav
+ * @throws Exception
+ */
+ public function getToc()
+ {
+ if ($this->tocnav) {
+ return $this->tocnav;
+ }
+
+ // @todo support Nav structure as well, see initSpineComponent
+ if ($this->getSpine()->getTocFormat() === Nav::class) {
+ throw new Exception('TODO: support NAV structure as well');
+ }
+
+ $tocpath = $this->getFullPath($this->getSpine()->getTocItem()->getHref());
+ $data = $this->zip->FileRead($tocpath);
+ $toc = new DOMDocument();
+ $toc->registerNodeClass(DOMElement::class, EpubDomElement::class);
+ $toc->loadXML($data);
+ $xpath = new EpubDomXPath($toc);
+ //$rootNamespace = $toc->lookupNamespaceUri($toc->namespaceURI);
+ //$xpath->registerNamespace('x', $rootNamespace);
+
+ $titleNode = $xpath->query('//ncx:docTitle/ncx:text')->item(0);
+ $title = $titleNode ? $titleNode->nodeValue : '';
+ $authorNode = $xpath->query('//ncx:docAuthor/ncx:text')->item(0);
+ $author = $authorNode ? $authorNode->nodeValue : '';
+ $this->tocnav = new Toc($title, $author);
+
+ $navPointNodes = $xpath->query('//ncx:navMap/ncx:navPoint');
+
+ $this->loadNavPoints($navPointNodes, $this->tocnav->getNavMap(), $xpath);
+
+ return $this->tocnav;
+ }
+
+ /**
+ * Load navigation points from TOC XML DOM into TOC object structure.
+ *
+ * @param DOMNodeList<EPubDomElement> $navPointNodes List of nodes to load from.
+ * @param TocNavPointList $navPointList List structure to load into.
+ * @param EpubDomXPath $xp The XPath of the TOC document.
+ * @return void
+ */
+ protected static function loadNavPoints(DOMNodeList $navPointNodes, TocNavPointList $navPointList, EpubDomXPath $xp)
+ {
+ foreach ($navPointNodes as $navPointNode) {
+ /** @var EpubDomElement $navPointNode */
+ $id = $navPointNode->getAttribute('id');
+ $class = $navPointNode->getAttribute('class');
+ $playOrder = (int) $navPointNode->getAttribute('playOrder');
+ $labelTextNode = $xp->query('ncx:navLabel/ncx:text', $navPointNode)->item(0);
+ $label = $labelTextNode ? $labelTextNode->nodeValue : '';
+ /** @var EpubDomElement|null $contentNode */
+ $contentNode = $xp->query('ncx:content', $navPointNode)->item(0);
+ $contentSource = $contentNode ? $contentNode->getAttribute('src') : '';
+ $navPoint = new TocNavPoint($id, $class, $playOrder, $label, $contentSource);
+ $navPointList->append($navPoint);
+ $childNavPointNodes = $xp->query('ncx:navPoint', $navPointNode);
+ $childNavPoints = $navPoint->getChildren();
+
+ static::loadNavPoints($childNavPointNodes, $childNavPoints, $xp);
+ }
+ }
+
+ /**
+ * Summary of getNav
+ * @return Toc|Nav
+ */
+ public function getNav()
+ {
+ if ($this->tocnav) {
+ return $this->tocnav;
+ }
+
+ $navpath = $this->getFullPath($this->getSpine()->getTocItem()->getHref());
+ $data = $this->zip->FileRead($navpath);
+ $nav = new DOMDocument();
+ $nav->registerNodeClass(DOMElement::class, EpubDomElement::class);
+ $nav->loadXML($data);
+ $xpath = new EpubDomXPath($nav);
+ $rootNamespace = $nav->lookupNamespaceUri($nav->namespaceURI);
+ $xpath->registerNamespace('x', $rootNamespace);
+
+ // nav documents don't contain mandatory title or author - look in main doc
+ $title = $this->getTitle();
+ $author = implode(', ', $this->getAuthors());
+ $this->tocnav = new Nav($title, $author);
+
+ $toc = $xpath->query('//x:nav[@epub:type="toc"]')->item(0);
+ $navListNodes = $xpath->query('x:ol/x:li', $toc);
+ if ($navListNodes->length > 0) {
+ $this->loadNavList($navListNodes, $this->tocnav->getNavMap(), $xpath);
+ }
+
+ return $this->tocnav;
+ }
+
+ /**
+ * Load navigation points from NAV XML DOM into NAV object structure.
+ *
+ * @param DOMNodeList<EPubDomElement> $navListNodes List of nodes to load from.
+ * @param TocNavPointList $navPointList List structure to load into.
+ * @param EpubDomXPath $xp The XPath of the NAV document.
+ * @param int $depth Current depth of this list (recursive)
+ * @param int $order Current start order for this list
+ * @return void
+ */
+ protected static function loadNavList(DOMNodeList $navListNodes, TocNavPointList $navPointList, EpubDomXPath $xp, int $depth = 0, int $order = 0)
+ {
+ // h1 - h6 are supported as title for the list
+ $className = 'h' . strval($depth + 1);
+ if ($depth > 5) {
+ throw new Exception("We're at maximum depth for NAV DOC here!?");
+ }
+ foreach ($navListNodes as $navPointNode) {
+ $order += 1;
+ $nodes = $xp->query('x:a', $navPointNode);
+ $label = trim($nodes->item(0)->nodeValue);
+ if (empty($label)) {
+ // do we have an image with title or alt available?
+ $images = $xp->query('x:a/x:img', $navPointNode);
+ if ($images->length) {
+ $label = static::getAttr($images, 'alt');
+ if (empty($label)) {
+ $label = static::getAttr($images, 'title');
+ }
+ }
+ }
+ $contentSource = static::getAttr($nodes, 'href');
+ /** @var EpubDomElement $navPointNode */
+ $id = $navPointNode->getAttribute('id');
+ $class = $className;
+ $playOrder = $order;
+ $navPoint = new TocNavPoint($id, $class, $playOrder, $label, $contentSource);
+ $navPointList->append($navPoint);
+ $childNavPointNodes = $xp->query('x:ol/x:li', $navPointNode);
+ $childNavPoints = $navPoint->getChildren();
+
+ static::loadNavList($childNavPointNodes, $childNavPoints, $xp, $depth + 1, $order);
+ }
+ }
+
+ /**
+ * Extract the contents of this EPUB.
+ *
+ * This concatenates contents of items according to their order in the spine.
+ *
+ * @param bool $keepMarkup Whether to keep the XHTML markup rather than extracted plain text.
+ * @param float $fraction If less than 1, only the respective part from the beginning of the book is extracted.
+ * @return string The contents of this EPUB.
+ * @throws Exception
+ */
+ public function getContents($keepMarkup = false, $fraction = 1.0)
+ {
+ $contents = '';
+ if ($fraction < 1) {
+ $totalSize = 0;
+ foreach ($this->getSpine() as $item) {
+ $totalSize += $item->getSize();
+ }
+ $fractionSize = $totalSize * $fraction;
+ $contentsSize = 0;
+ foreach ($this->spine as $item) {
+ $itemSize = $item->getSize();
+ if ($contentsSize + $itemSize > $fractionSize) {
+ break;
+ }
+ $contentsSize += $itemSize;
+ $contents .= $item->getContents(null, null, $keepMarkup);
+ }
+ } else {
+ foreach ($this->getSpine() as $item) {
+ $contents .= $item->getContents(null, null, $keepMarkup);
+ }
+ }
+
+ return $contents;
+ }
+
+ /**
+ * Build an XPath expression to select certain nodes in the metadata section.
+ *
+ * @param string $element The node name of the elements to select.
+ * @param string $attribute If set, the attribute required in the element.
+ * @param string|array<string> $value If set, the value of the above named attribute. If an array is given
+ * all of its values will be allowed in the selector.
+ * @param bool $caseSensitive If false, attribute values are matched case insensitively.
+ * (This is not completely true, as only full upper or lower case strings are matched, not mixed case.
+ * A lower-case function is missing in XPath 1.0.)
+ * @return string
+ */
+ protected static function buildMetaXPath($element, $attribute, $value, $caseSensitive = true)
+ {
+ $xpath = '//opf:metadata/' . $element;
+ if ($attribute) {
+ $xpath .= "[@$attribute";
+ if ($value) {
+ $values = is_array($value) ? $value : [$value];
+ if (!$caseSensitive) {
+ $temp = [];
+ foreach ($values as $item) {
+ $temp[] = strtolower($item);
+ $temp[] = strtoupper($item);
+ }
+ $values = $temp;
+ }
+
+ $xpath .= '="';
+ $xpath .= implode("\" or @$attribute=\"", $values);
+ $xpath .= '"';
+ }
+ $xpath .= ']';
+ }
+
+ return $xpath;
+ }
+
+ /**
+ * Load an XML file from the EPUB/ZIP archive into a new XPath object.
+ *
+ * @param string $path The XML file to load from the ZIP archive.
+ * @return EpubDomXPath The XPath representation of the XML file.
+ * @throws Exception If the given path could not be read.
+ */
+ protected function loadXPathFromItem($path)
+ {
+ $data = $this->zip->FileRead($path);
+ if (!$data) {
+ throw new Exception("Failed to read from EPUB container: $path.");
+ }
+ $xml = new DOMDocument();
+ $xml->registerNodeClass(DOMElement::class, EpubDomElement::class);
+ $xml->loadXML($data);
+
+ return new EpubDomXPath($xml);
+ }
+
+ /**
+ * Get the stat entries for all files in a ZIP file
+ *
+ * @param string $file|null Path to a ZIP file or null for current file
+ * @return array<mixed> (filename => details of the entry)
+ */
+ public function getZipEntries($file = null)
+ {
+ $file ??= $this->file;
+ $entries = [];
+
+ $zip = new ZipArchive();
+ $result = $zip->open($file, ZipArchive::RDONLY);
+ if ($result !== true) {
+ throw new Exception("Unable to open file", $result);
+ }
+ for ($i = 0; $i < $zip->numFiles; $i++) {
+ $stat = $zip->statIndex($i);
+ $entries[$stat['name']] = $stat;
+ }
+ $zip->close();
+
+ return $entries;
+ }
+
+ /**
+ * Map the items of a ZIP file to their respective file sizes.
+ *
+ * @param string $file|null Path to a ZIP file or null for current ZIP file
+ * @return array<mixed> (filename => file size)
+ */
+ protected function loadSizeMap($file = null)
+ {
+ $entries = $this->getZipEntries($file);
+
+ $sizeMap = [];
+ foreach ($entries as $filename => $entry) {
+ $sizeMap[$filename] = $entry['size'];
+ }
+
+ return $sizeMap;
+ }
+
+ /**
+ * @return int
+ */
+ public function getImageCount()
+ {
+ $entries = $this->getZipEntries();
+ $images = array_filter($entries, static function ($k) {
+ return preg_match('/(.jpeg|.jpg|.png|.gif)/', $k);
+ }, ARRAY_FILTER_USE_KEY);
+
+ return count($images);
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Other.php b/vendor/mikespub/php-epub-meta/src/Other.php
new file mode 100644
index 000000000..6d60197ce
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Other.php
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Representation of an EPUB document.
+ *
+ * @author Andreas Gohr <andi@splitbrain.org> © 2012
+ * @author Simon Schrape <simon@epubli.com> © 2015
+ */
+
+//namespace Epubli\Epub;
+
+namespace SebLucas\EPubMeta;
+
+use SebLucas\EPubMeta\Dom\Element as EpubDomElement;
+use SebLucas\EPubMeta\Dom\XPath as EpubDomXPath;
+use SebLucas\EPubMeta\Data\Manifest;
+use SebLucas\EPubMeta\Contents\Spine;
+use SebLucas\EPubMeta\Contents\Toc;
+use DOMDocument;
+use DOMElement;
+use Exception;
+use InvalidArgumentException;
+use ZipArchive;
+
+/**
+ * @todo These are the methods that haven't been integrated with EPub here...
+ */
+class Other extends EPub
+{
+ /**
+ * A simple setter for simple meta attributes
+ *
+ * It should only be used for attributes that are expected to be unique
+ *
+ * @param string $item XML node to set
+ * @param string $value New node value
+ * @param bool|string $attribute Attribute name
+ * @param bool|string $attributeValue Attribute value
+ * @param bool $caseSensitive
+ */
+ protected function setMeta($item, $value, $attribute = false, $attributeValue = false, $caseSensitive = true)
+ {
+ $xpath = $this->buildMetaXPath($item, $attribute, $attributeValue, $caseSensitive);
+
+ // set value
+ $nodes = $this->xpath->query($xpath);
+ if ($nodes->length == 1) {
+ /** @var EpubDomElement $node */
+ $node = $nodes->item(0);
+ if ($value === '') {
+ // the user wants to empty this value -> delete the node
+ $node->delete();
+ } else {
+ // replace value
+ $node->nodeValueUnescaped = $value;
+ }
+ } else {
+ // if there are multiple matching nodes for some reason delete
+ // them. we'll replace them all with our own single one
+ foreach ($nodes as $node) {
+ /** @var EpubDomElement $node */
+ $node->delete();
+ }
+ // re-add them
+ if ($value) {
+ $parent = $this->xpath->query('//opf:metadata')->item(0);
+ $node = new EpubDomElement($item, $value);
+ $node = $parent->appendChild($node);
+ if ($attribute) {
+ if (is_array($attributeValue)) {
+ // use first given value for new attribute
+ $attributeValue = reset($attributeValue);
+ }
+ $node->setAttrib($attribute, $attributeValue);
+ }
+ }
+ }
+
+ $this->sync();
+ }
+
+ /**
+ * A simple getter for simple meta attributes
+ *
+ * It should only be used for attributes that are expected to be unique
+ *
+ * @param string $item XML node to get
+ * @param bool|string $att Attribute name
+ * @param bool|string $aval Attribute value
+ * @param bool $caseSensitive
+ * @return string
+ */
+ protected function getMeta($item, $att = false, $aval = false, $caseSensitive = true)
+ {
+ $xpath = $this->buildMetaXPath($item, $att, $aval, $caseSensitive);
+
+ // get value
+ $nodes = $this->xpath->query($xpath);
+ if ($nodes->length) {
+ /** @var EpubDomElement $node */
+ $node = $nodes->item(0);
+
+ return $node->nodeValueUnescaped;
+ } else {
+ return '';
+ }
+ }
+
+ /**
+ * Sync XPath object with updated DOM.
+ */
+ protected function sync()
+ {
+ $dom = $this->xpath->document;
+ $dom->loadXML($dom->saveXML());
+ $this->xpath = new EpubDomXPath($dom);
+ // reset structural members
+ $this->manifest = null;
+ $this->spine = null;
+ $this->tocnav = null;
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Tools/HtmlTools.php b/vendor/mikespub/php-epub-meta/src/Tools/HtmlTools.php
new file mode 100644
index 000000000..f905d265a
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Tools/HtmlTools.php
@@ -0,0 +1,97 @@
+<?php
+
+namespace SebLucas\EPubMeta\Tools;
+
+/**
+ * From Epubli\Common\Tools - see https://github.com/epubli/common
+ * @author Epubli Developers <devs@epubli.com>
+ */
+class HtmlTools
+{
+ /**
+ * @param string $html
+ * @return string
+ */
+ public static function convertEntitiesNamedToNumeric($html)
+ {
+ return strtr($html, include(__DIR__ . '/htmlEntityMap.php'));
+ }
+
+ /**
+ * @param string $name
+ * @return bool
+ */
+ public static function isBlockLevelElement($name)
+ {
+ return in_array($name, include(__DIR__ . '/htmlBlockLevelElements.php'));
+ }
+
+ /**
+ * performs a tag-aware truncation of (html-) strings, preserving tag integrity
+ * @param array<string>|string $html
+ * @param int|string $length
+ * @return bool|string
+ */
+ public static function truncate($html, $length = "20%")
+ {
+ $htmls = is_array($html) ? $html : [$html];
+ foreach ($htmls as &$htmlString) {
+ if (is_string($length)) {
+ $length = trim($length);
+ /* interpret percentage value */
+ if (substr($length, -1) == '%') {
+ $length = (int) (strlen($htmlString) * intval(substr($length, 0, -1)) / 100);
+ }
+ }
+ $htmlString = substr($htmlString, 0, $length);
+ /* eliminate trailing truncated tag fragment if present */
+ $htmlString = preg_replace('/<[^>]*$/is', '', $htmlString);
+ }
+
+ return is_array($html) ? $htmls : array_pop($htmls);
+ }
+
+ /**
+ * strips all occurring html tags from $html (which can either be a string or an array of strings),
+ * preserving all content enclosed by all tags in $keep and
+ * dumping the content residing in all tags listed in $drop
+ * @param array<string>|string $html
+ * @param array<string> $keep
+ * @param array<string> $drop
+ * @return array<string>|string
+ */
+ public static function stripHtmlTags(
+ $html,
+ $keep =
+ ['title', 'br', 'p', 'h1','h2','h3','h4','h5','span','div','i','strong','b', 'table', 'td', 'th', 'tr'],
+ $drop =
+ ['head','style']
+ ) {
+ $htmls = is_array($html) ? $html : [$html];
+ foreach ($htmls as &$htmlString) {
+ foreach ($drop as $dumpTag) {
+ $htmlString = preg_replace("/<$dumpTag.*$dumpTag>/is", "\n", $htmlString);
+ }
+ $htmlString = preg_replace("/[\n\r ]{2,}/i", "\n", $htmlString);
+ $htmlString = preg_replace("/[\n|\r]/i", '<br />', $htmlString);
+
+ /* @TODO: remove style tags and only keep body content (drop head) */
+ $tempFunc = function ($matches) use ($keep) {
+ $htmlNode = "<" . $matches[1] . ">" . strip_tags($matches[2]) . "</" . $matches[1] . ">";
+ if (in_array($matches[1], $keep)) {
+ return " " . $htmlNode . " ";
+ } else {
+ return "";
+ }
+ };
+
+ $allowedTags = implode("|", array_values($keep));
+ $regExp = '@<(' . $allowedTags . ')[^>]*?>(.*?)<\/\1>@i';
+ $htmlString = preg_replace_callback($regExp, $tempFunc, $htmlString);
+
+ $htmlString = strip_tags($htmlString, "<" . implode("><", $keep) . ">");
+ }
+ /* preserve injected variable cast type (string|array) when returning processed entity */
+ return is_array($html) ? $htmls : array_pop($htmls);
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Tools/ZipEdit.php b/vendor/mikespub/php-epub-meta/src/Tools/ZipEdit.php
new file mode 100644
index 000000000..ff9f607cf
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Tools/ZipEdit.php
@@ -0,0 +1,450 @@
+<?php
+/**
+ * ZipEdit class
+ *
+ * @author mikespub
+ */
+
+namespace SebLucas\EPubMeta\Tools;
+
+use ZipStream\ZipStream;
+use DateTime;
+use Exception;
+use ZipArchive;
+
+/**
+ * ZipEdit class allows to edit zip files on the fly and stream them afterwards
+ */
+class ZipEdit
+{
+ public const DOWNLOAD = 1; // download (default)
+ public const NOHEADER = 4; // option to use with DOWNLOAD: no header is sent
+ public const FILE = 8; // output to file , or add from file
+ public const STRING = 32; // output to string, or add from string
+ public const MIME_TYPE = 'application/epub+zip';
+
+ /** @var ZipArchive|null */
+ private $mZip;
+ /** @var array<string, mixed>|null */
+ private $mEntries;
+ /** @var array<string, mixed> */
+ private $mChanges = [];
+ /** @var string|null */
+ private $mFileName;
+ private bool $mSaveMe = false;
+
+ public function __construct()
+ {
+ $this->mZip = null;
+ $this->mEntries = null;
+ $this->mFileName = null;
+ }
+
+ /**
+ * Destructor
+ */
+ public function __destruct()
+ {
+ $this->Close();
+ }
+
+ /**
+ * Open a zip file and read it's entries
+ *
+ * @param string $inFileName
+ * @param int|null $inFlags
+ * @return boolean True if zip file has been correctly opended, else false
+ */
+ public function Open($inFileName, $inFlags = 0) // ZipArchive::RDONLY)
+ {
+ $this->Close();
+
+ $this->mZip = new ZipArchive();
+ $result = $this->mZip->open($inFileName, ZipArchive::RDONLY);
+ if ($result !== true) {
+ return false;
+ }
+
+ $this->mFileName = $inFileName;
+
+ $this->mEntries = [];
+ $this->mChanges = [];
+
+ for ($i = 0; $i < $this->mZip->numFiles; $i++) {
+ $entry = $this->mZip->statIndex($i);
+ $fileName = $entry['name'];
+ $this->mEntries[$fileName] = $entry;
+ $this->mChanges[$fileName] = ['status' => 'unchanged'];
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if a file exist in the zip entries
+ *
+ * @param string $inFileName File to search
+ *
+ * @return boolean True if the file exist, else false
+ */
+ public function FileExists($inFileName)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if (!isset($this->mEntries[$inFileName])) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Read the content of a file in the zip entries
+ *
+ * @param string $inFileName File to search
+ *
+ * @return mixed File content the file exist, else false
+ */
+ public function FileRead($inFileName)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if (!isset($this->mEntries[$inFileName])) {
+ return false;
+ }
+
+ $data = false;
+
+ $changes = $this->mChanges[$inFileName] ?? ['status' => 'unchanged'];
+ switch ($changes['status']) {
+ case 'unchanged':
+ $data = $this->mZip->getFromName($inFileName);
+ break;
+ case 'added':
+ case 'modified':
+ if (isset($changes['data'])) {
+ $data = $changes['data'];
+ } elseif (isset($changes['path'])) {
+ $data = file_get_contents($changes['path']);
+ }
+ break;
+ case 'deleted':
+ default:
+ break;
+ }
+ return $data;
+ }
+
+ /**
+ * Get a file handler to a file in the zip entries (read-only)
+ *
+ * @param string $inFileName File to search
+ *
+ * @return resource|bool File handler if the file exist, else false
+ */
+ public function FileStream($inFileName)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if (!isset($this->mEntries[$inFileName])) {
+ return false;
+ }
+
+ // @todo streaming of added/modified data?
+ return $this->mZip->getStream($inFileName);
+ }
+
+ /**
+ * Summary of FileAdd
+ * @param string $inFileName
+ * @param mixed $inData
+ * @return bool
+ */
+ public function FileAdd($inFileName, $inData)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ $this->mEntries[$inFileName] = [
+ 'name' => $inFileName, // 'foobar/baz',
+ 'size' => strlen($inData),
+ 'mtime' => time(), // 1123164748,
+ ];
+ $this->mChanges[$inFileName] = ['status' => 'added', 'data' => $inData];
+ return true;
+ }
+
+ /**
+ * Summary of FileAddPath
+ * @param string $inFileName
+ * @param string $inFilePath
+ * @return bool
+ */
+ public function FileAddPath($inFileName, $inFilePath)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ $this->mEntries[$inFileName] = [
+ 'name' => $inFileName, // 'foobar/baz',
+ 'size' => filesize($inFilePath),
+ 'mtime' => filemtime($inFilePath), // 1123164748,
+ ];
+ $this->mChanges[$inFileName] = ['status' => 'added', 'path' => $inFilePath];
+ return true;
+ }
+
+ /**
+ * Summary of FileDelete
+ * @param string $inFileName
+ * @return bool
+ */
+ public function FileDelete($inFileName)
+ {
+ if (!$this->FileExists($inFileName)) {
+ return false;
+ }
+
+ $this->mEntries[$inFileName]['size'] = 0;
+ $this->mEntries[$inFileName]['mtime'] = time();
+ $this->mChanges[$inFileName] = ['status' => 'deleted'];
+ return true;
+ }
+
+ /**
+ * Replace the content of a file in the zip entries
+ *
+ * @param string $inFileName File with content to replace
+ * @param string|bool $inData Data content to replace, or false to delete
+ * @return bool
+ */
+ public function FileReplace($inFileName, $inData)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if ($inData === false) {
+ return $this->FileDelete($inFileName);
+ }
+
+ $this->mEntries[$inFileName] ??= [];
+ $this->mEntries[$inFileName]['name'] = $inFileName;
+ $this->mEntries[$inFileName]['size'] = strlen($inData);
+ $this->mEntries[$inFileName]['mtime'] = time();
+ $this->mChanges[$inFileName] = ['status' => 'modified', 'data' => $inData];
+ return true;
+ }
+
+ /**
+ * Return the state of the file.
+ * @param mixed $inFileName
+ * @return string|bool 'u'=unchanged, 'm'=modified, 'd'=deleted, 'a'=added, false=unknown
+ */
+ public function FileGetState($inFileName)
+ {
+ $changes = $this->mChanges[$inFileName] ?? ['status' => false];
+ return $changes['status'];
+ }
+
+ /**
+ * Summary of FileCancelModif
+ * @param string $inFileName
+ * @param bool $ReplacedAndDeleted
+ * @return int
+ */
+ public function FileCancelModif($inFileName, $ReplacedAndDeleted = true)
+ {
+ // cancel added, modified or deleted modifications on a file in the archive
+ // return the number of cancels
+
+ $nbr = 0;
+
+ $this->mChanges[$inFileName] = ['status' => 'unchanged'];
+ $nbr += 1;
+ return $nbr;
+ }
+
+ /**
+ * Close the zip file
+ *
+ * @return void
+ * @throws Exception
+ */
+ public function Close()
+ {
+ if (!isset($this->mZip)) {
+ return;
+ }
+
+ $outFileName = $this->mFileName . '.copy';
+ if ($this->mSaveMe) {
+ $outFileStream = fopen($outFileName, 'wb+');
+ if ($outFileStream === false) {
+ throw new Exception('Unable to open zip copy ' . $outFileName);
+ }
+ $this->Flush(self::DOWNLOAD, $this->mFileName, self::MIME_TYPE, false, $outFileStream);
+ $result = fclose($outFileStream);
+ if ($result === false) {
+ throw new Exception('Unable to close zip copy ' . $outFileName);
+ }
+ }
+
+ if (!$this->mZip->close()) {
+ $status = $this->mZip->getStatusString();
+ $this->mZip = null;
+ throw new Exception($status);
+ }
+ if ($this->mSaveMe) {
+ $result = rename($outFileName, $this->mFileName);
+ if ($result === false) {
+ throw new Exception('Unable to rename zip copy ' . $outFileName);
+ }
+ $this->mSaveMe = false;
+ }
+ $this->mZip = null;
+ }
+
+ /**
+ * Summary of SaveBeforeClose
+ * @return void
+ */
+ public function SaveBeforeClose()
+ {
+ // Coming from EPub()->download() without fileName, called in EPub()->save()
+ // This comes right before EPub()->zip->close(), at which point we're lost
+ $this->mSaveMe = true;
+ }
+
+ /**
+ * Summary of Flush
+ * @param mixed $render
+ * @param mixed $outFileName
+ * @param mixed $contentType
+ * @param bool $sendHeaders
+ * @param resource|null $outFileStream
+ * @return void
+ */
+ public function Flush($render = self::DOWNLOAD, $outFileName = '', $contentType = '', $sendHeaders = true, $outFileStream = null)
+ {
+ // we don't want to close the zip file to save all changes here - probably what you needed :-)
+ //$this->Close();
+
+ $outFileName = $outFileName ?: $this->mFileName;
+ $contentType = $contentType ?: self::MIME_TYPE;
+ if ($outFileStream) {
+ $sendHeaders = false;
+ }
+ if (!$sendHeaders) {
+ $render = $render | self::NOHEADER;
+ }
+ if (($render & self::NOHEADER) !== self::NOHEADER) {
+ $sendHeaders = true;
+ } else {
+ $sendHeaders = false;
+ }
+
+ $outZipStream = new ZipStream(
+ outputName: basename($outFileName),
+ outputStream: $outFileStream,
+ sendHttpHeaders: $sendHeaders,
+ contentType: $contentType,
+ );
+ foreach ($this->mEntries as $fileName => $entry) {
+ $changes = $this->mChanges[$fileName];
+ switch ($changes['status']) {
+ case 'unchanged':
+ // Automatic binding of $this
+ $callback = function () use ($fileName) {
+ // this expects a stream as result, not the actual data
+ return $this->mZip->getStream($fileName);
+ };
+ $date = new DateTime();
+ $date->setTimestamp($entry['mtime']);
+ $outZipStream->addFileFromCallback(
+ fileName: $fileName,
+ exactSize: $entry['size'],
+ lastModificationDateTime: $date,
+ callback: $callback,
+ );
+ break;
+ case 'added':
+ case 'modified':
+ if (isset($changes['data'])) {
+ $outZipStream->addFile(
+ fileName: $fileName,
+ data: $changes['data'],
+ );
+ } elseif (isset($changes['path'])) {
+ $outZipStream->addFileFromPath(
+ fileName: $fileName,
+ path: $changes['path'],
+ );
+ }
+ break;
+ case 'deleted':
+ default:
+ break;
+ }
+ }
+
+ $outZipStream->finish();
+ }
+
+ /**
+ * Summary of copyTest
+ * @param string $inFileName
+ * @param string $outFileName
+ * @return void
+ */
+ public static function copyTest($inFileName, $outFileName)
+ {
+ $inZipFile = new ZipArchive();
+ $result = $inZipFile->open($inFileName, ZipArchive::RDONLY);
+ if ($result !== true) {
+ throw new Exception('Unable to open zip file ' . $inFileName);
+ }
+
+ $entries = [];
+ for ($i = 0; $i < $inZipFile->numFiles; $i++) {
+ $entry = $inZipFile->statIndex($i);
+ $fileName = $entry['name'];
+ $entries[$fileName] = $entry;
+ }
+
+ // see ZipStreamTest.php
+ $outFileStream = fopen($outFileName, 'wb+');
+
+ $outZipStream = new ZipStream(
+ outputName: basename($outFileName),
+ outputStream: $outFileStream,
+ sendHttpHeaders: false,
+ );
+ foreach ($entries as $fileName => $entry) {
+ $date = new DateTime();
+ $date->setTimestamp($entry['mtime']);
+ // does not work in v2 - the zip stream is not seekable, but ZipStream checks for it in Stream.php
+ // does work in v3 - implemented using addFileFromCallback, so we might as well use that :-)
+ $outZipStream->addFileFromCallback(
+ fileName: $fileName,
+ exactSize: $entry['size'],
+ lastModificationDateTime: $date,
+ callback: function () use ($inZipFile, $fileName) {
+ // this expects a stream as result, not the actual data
+ return $inZipFile->getStream($fileName);
+ },
+ );
+ }
+
+ $outZipStream->finish();
+ fclose($outFileStream);
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Tools/ZipFile.php b/vendor/mikespub/php-epub-meta/src/Tools/ZipFile.php
new file mode 100644
index 000000000..b083b0c4f
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Tools/ZipFile.php
@@ -0,0 +1,343 @@
+<?php
+/**
+ * ZipFile class
+ *
+ * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author Didier Corbière <contact@atoll-digital-library.org>
+ * @author mikespub
+ */
+
+namespace SebLucas\EPubMeta\Tools;
+
+use Exception;
+use ZipArchive;
+
+/**
+ * ZipFile class allows to open files inside a zip file with the standard php zip functions
+ *
+ * This class also supports adding/replacing/deleting files inside the zip file, but changes
+ * will *not* be reflected correctly until you close the zip file, and open it again if needed
+ *
+ * Note: this is not meant to handle a massive amount of files inside generic archive files.
+ * It is specifically meant for EPUB files which typically contain hundreds/thousands of pages,
+ * not millions or more. And any changes you make are kept in memory, so don't re-write every
+ * page of War and Peace either - better to unzip that locally and then re-zip it afterwards.
+ */
+class ZipFile
+{
+ public const DOWNLOAD = 1; // download (default)
+ public const NOHEADER = 4; // option to use with DOWNLOAD: no header is sent
+ public const FILE = 8; // output to file , or add from file
+ public const STRING = 32; // output to string, or add from string
+ public const MIME_TYPE = 'application/epub+zip';
+
+ /** @var ZipArchive|null */
+ protected $mZip;
+ /** @var array<string, mixed>|null */
+ protected $mEntries;
+ /** @var array<string, mixed> */
+ protected $mChanges = [];
+ /** @var string|null */
+ protected $mFileName;
+
+ public function __construct()
+ {
+ $this->mZip = null;
+ $this->mEntries = null;
+ $this->mFileName = null;
+ }
+
+ /**
+ * Destructor
+ */
+ public function __destruct()
+ {
+ $this->Close();
+ }
+
+ /**
+ * Open a zip file and read it's entries
+ *
+ * @param string $inFileName
+ * @param int|null $inFlags
+ * @return boolean True if zip file has been correctly opended, else false
+ */
+ public function Open($inFileName, $inFlags = 0) // ZipArchive::RDONLY)
+ {
+ $this->Close();
+ $inFileName = realpath($inFileName);
+
+ $this->mZip = new ZipArchive();
+ $result = $this->mZip->open($inFileName, $inFlags);
+ if ($result !== true) {
+ return false;
+ }
+
+ $this->mFileName = $inFileName;
+
+ $this->mEntries = [];
+ $this->mChanges = [];
+
+ for ($i = 0; $i < $this->mZip->numFiles; $i++) {
+ $entry = $this->mZip->statIndex($i);
+ $fileName = $entry['name'];
+ $this->mEntries[$fileName] = $entry;
+ $this->mChanges[$fileName] = ['status' => 'unchanged'];
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if a file exist in the zip entries
+ *
+ * @param string $inFileName File to search
+ *
+ * @return boolean True if the file exist, else false
+ */
+ public function FileExists($inFileName)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if (!isset($this->mEntries[$inFileName])) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Read the content of a file in the zip entries
+ *
+ * @param string $inFileName File to search
+ *
+ * @return mixed File content the file exist, else false
+ */
+ public function FileRead($inFileName)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if (!isset($this->mEntries[$inFileName])) {
+ return false;
+ }
+
+ $data = false;
+
+ $changes = $this->mChanges[$inFileName] ?? ['status' => 'unchanged'];
+ switch ($changes['status']) {
+ case 'unchanged':
+ $data = $this->mZip->getFromName($inFileName);
+ break;
+ case 'added':
+ case 'modified':
+ if (isset($changes['data'])) {
+ $data = $changes['data'];
+ } elseif (isset($changes['path'])) {
+ $data = file_get_contents($changes['path']);
+ }
+ break;
+ case 'deleted':
+ default:
+ break;
+ }
+ return $data;
+ }
+
+ /**
+ * Get a file handler to a file in the zip entries (read-only)
+ *
+ * @param string $inFileName File to search
+ *
+ * @return resource|bool File handler if the file exist, else false
+ */
+ public function FileStream($inFileName)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if (!isset($this->mEntries[$inFileName])) {
+ return false;
+ }
+
+ // @todo streaming of added/modified data?
+ return $this->mZip->getStream($inFileName);
+ }
+
+ /**
+ * Summary of FileAdd
+ * @param string $inFileName
+ * @param mixed $inData
+ * @return bool
+ */
+ public function FileAdd($inFileName, $inData)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if (!$this->mZip->addFromString($inFileName, $inData)) {
+ return false;
+ }
+ $this->mEntries[$inFileName] = $this->mZip->statName($inFileName);
+ $this->mChanges[$inFileName] = ['status' => 'added', 'data' => $inData];
+ return true;
+ }
+
+ /**
+ * Summary of FileAddPath
+ * @param string $inFileName
+ * @param string $inFilePath
+ * @return mixed
+ */
+ public function FileAddPath($inFileName, $inFilePath)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if (!$this->mZip->addFile($inFilePath, $inFileName)) {
+ return false;
+ }
+ $this->mEntries[$inFileName] = $this->mZip->statName($inFileName);
+ $this->mChanges[$inFileName] = ['status' => 'added', 'path' => $inFilePath];
+ return true;
+ }
+
+ /**
+ * Summary of FileDelete
+ * @param string $inFileName
+ * @return bool
+ */
+ public function FileDelete($inFileName)
+ {
+ if (!$this->FileExists($inFileName)) {
+ return false;
+ }
+
+ if (!$this->mZip->deleteName($inFileName)) {
+ return false;
+ }
+ unset($this->mEntries[$inFileName]);
+ $this->mChanges[$inFileName] = ['status' => 'deleted'];
+ return true;
+ }
+
+ /**
+ * Replace the content of a file in the zip entries
+ *
+ * @param string $inFileName File with content to replace
+ * @param string|bool $inData Data content to replace, or false to delete
+ * @return bool
+ */
+ public function FileReplace($inFileName, $inData)
+ {
+ if (!isset($this->mZip)) {
+ return false;
+ }
+
+ if ($inData === false) {
+ return $this->FileDelete($inFileName);
+ }
+
+ if (!$this->mZip->addFromString($inFileName, $inData)) {
+ return false;
+ }
+ $this->mEntries[$inFileName] = $this->mZip->statName($inFileName);
+ $this->mChanges[$inFileName] = ['status' => 'modified', 'data' => $inData];
+ return true;
+ }
+
+ /**
+ * Return the state of the file.
+ * @param mixed $inFileName
+ * @return string|bool 'u'=unchanged, 'm'=modified, 'd'=deleted, 'a'=added, false=unknown
+ */
+ public function FileGetState($inFileName)
+ {
+ $changes = $this->mChanges[$inFileName] ?? ['status' => false];
+ return $changes['status'];
+ }
+
+ /**
+ * Summary of FileCancelModif
+ * @param string $inFileName
+ * @param bool $ReplacedAndDeleted
+ * @return int
+ */
+ public function FileCancelModif($inFileName, $ReplacedAndDeleted = true)
+ {
+ // cancel added, modified or deleted modifications on a file in the archive
+ // return the number of cancels
+
+ $nbr = 0;
+
+ if (!$this->mZip->unchangeName($inFileName)) {
+ return $nbr;
+ }
+ $nbr += 1;
+ $this->mChanges[$inFileName] = ['status' => 'unchanged'];
+ return $nbr;
+ }
+
+ /**
+ * Close the zip file
+ *
+ * @return void
+ * @throws Exception
+ */
+ public function Close()
+ {
+ if (!isset($this->mZip)) {
+ return;
+ }
+
+ if (!$this->mZip->close()) {
+ $status = $this->mZip->getStatusString();
+ $this->mZip = null;
+ throw new Exception($status);
+ }
+ $this->mZip = null;
+ }
+
+ /**
+ * Summary of Flush
+ * @param mixed $render
+ * @param mixed $outFileName
+ * @param mixed $contentType
+ * @param bool $sendHeaders
+ * @return void
+ */
+ public function Flush($render = self::DOWNLOAD, $outFileName = '', $contentType = '', $sendHeaders = true)
+ {
+ // we need to close the zip file to save all changes here - probably not what you wanted :-()
+ $this->Close();
+
+ $outFileName = $outFileName ?: $this->mFileName;
+ $contentType = $contentType ?: static::MIME_TYPE;
+ if (!$sendHeaders) {
+ $render = $render | static::NOHEADER;
+ }
+ $inFilePath = realpath($this->mFileName);
+
+ if (($render & static::NOHEADER) !== static::NOHEADER) {
+ $expires = 60 * 60 * 24 * 14;
+ header('Pragma: public');
+ header('Cache-Control: max-age=' . $expires);
+ header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires) . ' GMT');
+
+ header('Content-Type: ' . $contentType);
+ header('Content-Disposition: attachment; filename="' . basename($outFileName) . '"');
+
+ // see fetch.php for use of Config::get('x_accel_redirect')
+ header('Content-Length: ' . filesize($inFilePath));
+ //header(Config::get('x_accel_redirect') . ': ' . $inFilePath);
+ }
+
+ readfile($inFilePath);
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/src/Tools/htmlBlockLevelElements.php b/vendor/mikespub/php-epub-meta/src/Tools/htmlBlockLevelElements.php
new file mode 100644
index 000000000..6e96a6b0f
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Tools/htmlBlockLevelElements.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * List of HTML block level elements.
+ * Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements
+ */
+return [
+ 'address',
+ 'article',
+ 'aside',
+ 'audio',
+ 'video',
+ 'blockquote',
+ 'canvas',
+ 'dd',
+ 'div',
+ 'dl',
+ 'fieldset',
+ 'figcaption',
+ 'figure',
+ 'footer',
+ 'form',
+ 'h1',
+ 'h2',
+ 'h3',
+ 'h4',
+ 'h5',
+ 'h6',
+ 'header',
+ 'hgroup',
+ 'hr',
+ 'li',
+ 'noscript',
+ 'ol',
+ 'output',
+ 'p',
+ 'pre',
+ 'section',
+ 'table',
+ 'tfoot',
+ 'ul',
+ 'video',
+];
diff --git a/vendor/mikespub/php-epub-meta/src/Tools/htmlEntityMap.php b/vendor/mikespub/php-epub-meta/src/Tools/htmlEntityMap.php
new file mode 100644
index 000000000..6bc3f4653
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/src/Tools/htmlEntityMap.php
@@ -0,0 +1,260 @@
+<?php
+/**
+ * Maps every HTML named entity to its numeric equivalent.
+ * Source: http://stackoverflow.com/questions/11176752/converting-named-html-entities-to-numeric-html-entities#answer-11179875
+ */
+return [
+'&nbsp;' => '&#160;', # no-break space = non-breaking space, U+00A0 ISOnum
+'&iexcl;' => '&#161;', # inverted exclamation mark, U+00A1 ISOnum
+'&cent;' => '&#162;', # cent sign, U+00A2 ISOnum
+'&pound;' => '&#163;', # pound sign, U+00A3 ISOnum
+'&curren;' => '&#164;', # currency sign, U+00A4 ISOnum
+'&yen;' => '&#165;', # yen sign = yuan sign, U+00A5 ISOnum
+'&brvbar;' => '&#166;', # broken bar = broken vertical bar, U+00A6 ISOnum
+'&sect;' => '&#167;', # section sign, U+00A7 ISOnum
+'&uml;' => '&#168;', # diaeresis = spacing diaeresis, U+00A8 ISOdia
+'&copy;' => '&#169;', # copyright sign, U+00A9 ISOnum
+'&ordf;' => '&#170;', # feminine ordinal indicator, U+00AA ISOnum
+'&laquo;' => '&#171;', # left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum
+'&not;' => '&#172;', # not sign, U+00AC ISOnum
+'&shy;' => '&#173;', # soft hyphen = discretionary hyphen, U+00AD ISOnum
+'&reg;' => '&#174;', # registered sign = registered trade mark sign, U+00AE ISOnum
+'&macr;' => '&#175;', # macron = spacing macron = overline = APL overbar, U+00AF ISOdia
+'&deg;' => '&#176;', # degree sign, U+00B0 ISOnum
+'&plusmn;' => '&#177;', # plus-minus sign = plus-or-minus sign, U+00B1 ISOnum
+'&sup2;' => '&#178;', # superscript two = superscript digit two = squared, U+00B2 ISOnum
+'&sup3;' => '&#179;', # superscript three = superscript digit three = cubed, U+00B3 ISOnum
+'&acute;' => '&#180;', # acute accent = spacing acute, U+00B4 ISOdia
+'&micro;' => '&#181;', # micro sign, U+00B5 ISOnum
+'&para;' => '&#182;', # pilcrow sign = paragraph sign, U+00B6 ISOnum
+'&middot;' => '&#183;', # middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum
+'&cedil;' => '&#184;', # cedilla = spacing cedilla, U+00B8 ISOdia
+'&sup1;' => '&#185;', # superscript one = superscript digit one, U+00B9 ISOnum
+'&ordm;' => '&#186;', # masculine ordinal indicator, U+00BA ISOnum
+'&raquo;' => '&#187;', # right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum
+'&frac14;' => '&#188;', # vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum
+'&frac12;' => '&#189;', # vulgar fraction one half = fraction one half, U+00BD ISOnum
+'&frac34;' => '&#190;', # vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum
+'&iquest;' => '&#191;', # inverted question mark = turned question mark, U+00BF ISOnum
+'&Agrave;' => '&#192;', # latin capital letter A with grave = latin capital letter A grave, U+00C0 ISOlat1
+'&Aacute;' => '&#193;', # latin capital letter A with acute, U+00C1 ISOlat1
+'&Acirc;' => '&#194;', # latin capital letter A with circumflex, U+00C2 ISOlat1
+'&Atilde;' => '&#195;', # latin capital letter A with tilde, U+00C3 ISOlat1
+'&Auml;' => '&#196;', # latin capital letter A with diaeresis, U+00C4 ISOlat1
+'&Aring;' => '&#197;', # latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1
+'&AElig;' => '&#198;', # latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1
+'&Ccedil;' => '&#199;', # latin capital letter C with cedilla, U+00C7 ISOlat1
+'&Egrave;' => '&#200;', # latin capital letter E with grave, U+00C8 ISOlat1
+'&Eacute;' => '&#201;', # latin capital letter E with acute, U+00C9 ISOlat1
+'&Ecirc;' => '&#202;', # latin capital letter E with circumflex, U+00CA ISOlat1
+'&Euml;' => '&#203;', # latin capital letter E with diaeresis, U+00CB ISOlat1
+'&Igrave;' => '&#204;', # latin capital letter I with grave, U+00CC ISOlat1
+'&Iacute;' => '&#205;', # latin capital letter I with acute, U+00CD ISOlat1
+'&Icirc;' => '&#206;', # latin capital letter I with circumflex, U+00CE ISOlat1
+'&Iuml;' => '&#207;', # latin capital letter I with diaeresis, U+00CF ISOlat1
+'&ETH;' => '&#208;', # latin capital letter ETH, U+00D0 ISOlat1
+'&Ntilde;' => '&#209;', # latin capital letter N with tilde, U+00D1 ISOlat1
+'&Ograve;' => '&#210;', # latin capital letter O with grave, U+00D2 ISOlat1
+'&Oacute;' => '&#211;', # latin capital letter O with acute, U+00D3 ISOlat1
+'&Ocirc;' => '&#212;', # latin capital letter O with circumflex, U+00D4 ISOlat1
+'&Otilde;' => '&#213;', # latin capital letter O with tilde, U+00D5 ISOlat1
+'&Ouml;' => '&#214;', # latin capital letter O with diaeresis, U+00D6 ISOlat1
+'&times;' => '&#215;', # multiplication sign, U+00D7 ISOnum
+'&Oslash;' => '&#216;', # latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1
+'&Ugrave;' => '&#217;', # latin capital letter U with grave, U+00D9 ISOlat1
+'&Uacute;' => '&#218;', # latin capital letter U with acute, U+00DA ISOlat1
+'&Ucirc;' => '&#219;', # latin capital letter U with circumflex, U+00DB ISOlat1
+'&Uuml;' => '&#220;', # latin capital letter U with diaeresis, U+00DC ISOlat1
+'&Yacute;' => '&#221;', # latin capital letter Y with acute, U+00DD ISOlat1
+'&THORN;' => '&#222;', # latin capital letter THORN, U+00DE ISOlat1
+'&szlig;' => '&#223;', # latin small letter sharp s = ess-zed, U+00DF ISOlat1
+'&agrave;' => '&#224;', # latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1
+'&aacute;' => '&#225;', # latin small letter a with acute, U+00E1 ISOlat1
+'&acirc;' => '&#226;', # latin small letter a with circumflex, U+00E2 ISOlat1
+'&atilde;' => '&#227;', # latin small letter a with tilde, U+00E3 ISOlat1
+'&auml;' => '&#228;', # latin small letter a with diaeresis, U+00E4 ISOlat1
+'&aring;' => '&#229;', # latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1
+'&aelig;' => '&#230;', # latin small letter ae = latin small ligature ae, U+00E6 ISOlat1
+'&ccedil;' => '&#231;', # latin small letter c with cedilla, U+00E7 ISOlat1
+'&egrave;' => '&#232;', # latin small letter e with grave, U+00E8 ISOlat1
+'&eacute;' => '&#233;', # latin small letter e with acute, U+00E9 ISOlat1
+'&ecirc;' => '&#234;', # latin small letter e with circumflex, U+00EA ISOlat1
+'&euml;' => '&#235;', # latin small letter e with diaeresis, U+00EB ISOlat1
+'&igrave;' => '&#236;', # latin small letter i with grave, U+00EC ISOlat1
+'&iacute;' => '&#237;', # latin small letter i with acute, U+00ED ISOlat1
+'&icirc;' => '&#238;', # latin small letter i with circumflex, U+00EE ISOlat1
+'&iuml;' => '&#239;', # latin small letter i with diaeresis, U+00EF ISOlat1
+'&eth;' => '&#240;', # latin small letter eth, U+00F0 ISOlat1
+'&ntilde;' => '&#241;', # latin small letter n with tilde, U+00F1 ISOlat1
+'&ograve;' => '&#242;', # latin small letter o with grave, U+00F2 ISOlat1
+'&oacute;' => '&#243;', # latin small letter o with acute, U+00F3 ISOlat1
+'&ocirc;' => '&#244;', # latin small letter o with circumflex, U+00F4 ISOlat1
+'&otilde;' => '&#245;', # latin small letter o with tilde, U+00F5 ISOlat1
+'&ouml;' => '&#246;', # latin small letter o with diaeresis, U+00F6 ISOlat1
+'&divide;' => '&#247;', # division sign, U+00F7 ISOnum
+'&oslash;' => '&#248;', # latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1
+'&ugrave;' => '&#249;', # latin small letter u with grave, U+00F9 ISOlat1
+'&uacute;' => '&#250;', # latin small letter u with acute, U+00FA ISOlat1
+'&ucirc;' => '&#251;', # latin small letter u with circumflex, U+00FB ISOlat1
+'&uuml;' => '&#252;', # latin small letter u with diaeresis, U+00FC ISOlat1
+'&yacute;' => '&#253;', # latin small letter y with acute, U+00FD ISOlat1
+'&thorn;' => '&#254;', # latin small letter thorn, U+00FE ISOlat1
+'&yuml;' => '&#255;', # latin small letter y with diaeresis, U+00FF ISOlat1
+'&fnof;' => '&#402;', # latin small f with hook = function = florin, U+0192 ISOtech
+'&Alpha;' => '&#913;', # greek capital letter alpha, U+0391
+'&Beta;' => '&#914;', # greek capital letter beta, U+0392
+'&Gamma;' => '&#915;', # greek capital letter gamma, U+0393 ISOgrk3
+'&Delta;' => '&#916;', # greek capital letter delta, U+0394 ISOgrk3
+'&Epsilon;' => '&#917;', # greek capital letter epsilon, U+0395
+'&Zeta;' => '&#918;', # greek capital letter zeta, U+0396
+'&Eta;' => '&#919;', # greek capital letter eta, U+0397
+'&Theta;' => '&#920;', # greek capital letter theta, U+0398 ISOgrk3
+'&Iota;' => '&#921;', # greek capital letter iota, U+0399
+'&Kappa;' => '&#922;', # greek capital letter kappa, U+039A
+'&Lambda;' => '&#923;', # greek capital letter lambda, U+039B ISOgrk3
+'&Mu;' => '&#924;', # greek capital letter mu, U+039C
+'&Nu;' => '&#925;', # greek capital letter nu, U+039D
+'&Xi;' => '&#926;', # greek capital letter xi, U+039E ISOgrk3
+'&Omicron;' => '&#927;', # greek capital letter omicron, U+039F
+'&Pi;' => '&#928;', # greek capital letter pi, U+03A0 ISOgrk3
+'&Rho;' => '&#929;', # greek capital letter rho, U+03A1
+'&Sigma;' => '&#931;', # greek capital letter sigma, U+03A3 ISOgrk3
+'&Tau;' => '&#932;', # greek capital letter tau, U+03A4
+'&Upsilon;' => '&#933;', # greek capital letter upsilon, U+03A5 ISOgrk3
+'&Phi;' => '&#934;', # greek capital letter phi, U+03A6 ISOgrk3
+'&Chi;' => '&#935;', # greek capital letter chi, U+03A7
+'&Psi;' => '&#936;', # greek capital letter psi, U+03A8 ISOgrk3
+'&Omega;' => '&#937;', # greek capital letter omega, U+03A9 ISOgrk3
+'&alpha;' => '&#945;', # greek small letter alpha, U+03B1 ISOgrk3
+'&beta;' => '&#946;', # greek small letter beta, U+03B2 ISOgrk3
+'&gamma;' => '&#947;', # greek small letter gamma, U+03B3 ISOgrk3
+'&delta;' => '&#948;', # greek small letter delta, U+03B4 ISOgrk3
+'&epsilon;' => '&#949;', # greek small letter epsilon, U+03B5 ISOgrk3
+'&zeta;' => '&#950;', # greek small letter zeta, U+03B6 ISOgrk3
+'&eta;' => '&#951;', # greek small letter eta, U+03B7 ISOgrk3
+'&theta;' => '&#952;', # greek small letter theta, U+03B8 ISOgrk3
+'&iota;' => '&#953;', # greek small letter iota, U+03B9 ISOgrk3
+'&kappa;' => '&#954;', # greek small letter kappa, U+03BA ISOgrk3
+'&lambda;' => '&#955;', # greek small letter lambda, U+03BB ISOgrk3
+'&mu;' => '&#956;', # greek small letter mu, U+03BC ISOgrk3
+'&nu;' => '&#957;', # greek small letter nu, U+03BD ISOgrk3
+'&xi;' => '&#958;', # greek small letter xi, U+03BE ISOgrk3
+'&omicron;' => '&#959;', # greek small letter omicron, U+03BF NEW
+'&pi;' => '&#960;', # greek small letter pi, U+03C0 ISOgrk3
+'&rho;' => '&#961;', # greek small letter rho, U+03C1 ISOgrk3
+'&sigmaf;' => '&#962;', # greek small letter final sigma, U+03C2 ISOgrk3
+'&sigma;' => '&#963;', # greek small letter sigma, U+03C3 ISOgrk3
+'&tau;' => '&#964;', # greek small letter tau, U+03C4 ISOgrk3
+'&upsilon;' => '&#965;', # greek small letter upsilon, U+03C5 ISOgrk3
+'&phi;' => '&#966;', # greek small letter phi, U+03C6 ISOgrk3
+'&chi;' => '&#967;', # greek small letter chi, U+03C7 ISOgrk3
+'&psi;' => '&#968;', # greek small letter psi, U+03C8 ISOgrk3
+'&omega;' => '&#969;', # greek small letter omega, U+03C9 ISOgrk3
+'&thetasym;' => '&#977;', # greek small letter theta symbol, U+03D1 NEW
+'&upsih;' => '&#978;', # greek upsilon with hook symbol, U+03D2 NEW
+'&piv;' => '&#982;', # greek pi symbol, U+03D6 ISOgrk3
+'&bull;' => '&#8226;', # bullet = black small circle, U+2022 ISOpub
+'&hellip;' => '&#8230;', # horizontal ellipsis = three dot leader, U+2026 ISOpub
+'&prime;' => '&#8242;', # prime = minutes = feet, U+2032 ISOtech
+'&Prime;' => '&#8243;', # double prime = seconds = inches, U+2033 ISOtech
+'&oline;' => '&#8254;', # overline = spacing overscore, U+203E NEW
+'&frasl;' => '&#8260;', # fraction slash, U+2044 NEW
+'&weierp;' => '&#8472;', # script capital P = power set = Weierstrass p, U+2118 ISOamso
+'&image;' => '&#8465;', # blackletter capital I = imaginary part, U+2111 ISOamso
+'&real;' => '&#8476;', # blackletter capital R = real part symbol, U+211C ISOamso
+'&trade;' => '&#8482;', # trade mark sign, U+2122 ISOnum
+'&alefsym;' => '&#8501;', # alef symbol = first transfinite cardinal, U+2135 NEW
+'&larr;' => '&#8592;', # leftwards arrow, U+2190 ISOnum
+'&uarr;' => '&#8593;', # upwards arrow, U+2191 ISOnum
+'&rarr;' => '&#8594;', # rightwards arrow, U+2192 ISOnum
+'&darr;' => '&#8595;', # downwards arrow, U+2193 ISOnum
+'&harr;' => '&#8596;', # left right arrow, U+2194 ISOamsa
+'&crarr;' => '&#8629;', # downwards arrow with corner leftwards = carriage return, U+21B5 NEW
+'&lArr;' => '&#8656;', # leftwards double arrow, U+21D0 ISOtech
+'&uArr;' => '&#8657;', # upwards double arrow, U+21D1 ISOamsa
+'&rArr;' => '&#8658;', # rightwards double arrow, U+21D2 ISOtech
+'&dArr;' => '&#8659;', # downwards double arrow, U+21D3 ISOamsa
+'&hArr;' => '&#8660;', # left right double arrow, U+21D4 ISOamsa
+'&forall;' => '&#8704;', # for all, U+2200 ISOtech
+'&part;' => '&#8706;', # partial differential, U+2202 ISOtech
+'&exist;' => '&#8707;', # there exists, U+2203 ISOtech
+'&empty;' => '&#8709;', # empty set = null set = diameter, U+2205 ISOamso
+'&nabla;' => '&#8711;', # nabla = backward difference, U+2207 ISOtech
+'&isin;' => '&#8712;', # element of, U+2208 ISOtech
+'&notin;' => '&#8713;', # not an element of, U+2209 ISOtech
+'&ni;' => '&#8715;', # contains as member, U+220B ISOtech
+'&prod;' => '&#8719;', # n-ary product = product sign, U+220F ISOamsb
+'&sum;' => '&#8721;', # n-ary sumation, U+2211 ISOamsb
+'&minus;' => '&#8722;', # minus sign, U+2212 ISOtech
+'&lowast;' => '&#8727;', # asterisk operator, U+2217 ISOtech
+'&radic;' => '&#8730;', # square root = radical sign, U+221A ISOtech
+'&prop;' => '&#8733;', # proportional to, U+221D ISOtech
+'&infin;' => '&#8734;', # infinity, U+221E ISOtech
+'&ang;' => '&#8736;', # angle, U+2220 ISOamso
+'&and;' => '&#8743;', # logical and = wedge, U+2227 ISOtech
+'&or;' => '&#8744;', # logical or = vee, U+2228 ISOtech
+'&cap;' => '&#8745;', # intersection = cap, U+2229 ISOtech
+'&cup;' => '&#8746;', # union = cup, U+222A ISOtech
+'&int;' => '&#8747;', # integral, U+222B ISOtech
+'&there4;' => '&#8756;', # therefore, U+2234 ISOtech
+'&sim;' => '&#8764;', # tilde operator = varies with = similar to, U+223C ISOtech
+'&cong;' => '&#8773;', # approximately equal to, U+2245 ISOtech
+'&asymp;' => '&#8776;', # almost equal to = asymptotic to, U+2248 ISOamsr
+'&ne;' => '&#8800;', # not equal to, U+2260 ISOtech
+'&equiv;' => '&#8801;', # identical to, U+2261 ISOtech
+'&le;' => '&#8804;', # less-than or equal to, U+2264 ISOtech
+'&ge;' => '&#8805;', # greater-than or equal to, U+2265 ISOtech
+'&sub;' => '&#8834;', # subset of, U+2282 ISOtech
+'&sup;' => '&#8835;', # superset of, U+2283 ISOtech
+'&nsub;' => '&#8836;', # not a subset of, U+2284 ISOamsn
+'&sube;' => '&#8838;', # subset of or equal to, U+2286 ISOtech
+'&supe;' => '&#8839;', # superset of or equal to, U+2287 ISOtech
+'&oplus;' => '&#8853;', # circled plus = direct sum, U+2295 ISOamsb
+'&otimes;' => '&#8855;', # circled times = vector product, U+2297 ISOamsb
+'&perp;' => '&#8869;', # up tack = orthogonal to = perpendicular, U+22A5 ISOtech
+'&sdot;' => '&#8901;', # dot operator, U+22C5 ISOamsb
+'&lceil;' => '&#8968;', # left ceiling = apl upstile, U+2308 ISOamsc
+'&rceil;' => '&#8969;', # right ceiling, U+2309 ISOamsc
+'&lfloor;' => '&#8970;', # left floor = apl downstile, U+230A ISOamsc
+'&rfloor;' => '&#8971;', # right floor, U+230B ISOamsc
+'&lang;' => '&#9001;', # left-pointing angle bracket = bra, U+2329 ISOtech
+'&rang;' => '&#9002;', # right-pointing angle bracket = ket, U+232A ISOtech
+'&loz;' => '&#9674;', # lozenge, U+25CA ISOpub
+'&spades;' => '&#9824;', # black spade suit, U+2660 ISOpub
+'&clubs;' => '&#9827;', # black club suit = shamrock, U+2663 ISOpub
+'&hearts;' => '&#9829;', # black heart suit = valentine, U+2665 ISOpub
+'&diams;' => '&#9830;', # black diamond suit, U+2666 ISOpub
+'&quot;' => '&#34;', # quotation mark = APL quote, U+0022 ISOnum
+'&amp;' => '&#38;', # ampersand, U+0026 ISOnum
+'&lt;' => '&#60;', # less-than sign, U+003C ISOnum
+'&gt;' => '&#62;', # greater-than sign, U+003E ISOnum
+'&OElig;' => '&#338;', # latin capital ligature OE, U+0152 ISOlat2
+'&oelig;' => '&#339;', # latin small ligature oe, U+0153 ISOlat2
+'&Scaron;' => '&#352;', # latin capital letter S with caron, U+0160 ISOlat2
+'&scaron;' => '&#353;', # latin small letter s with caron, U+0161 ISOlat2
+'&Yuml;' => '&#376;', # latin capital letter Y with diaeresis, U+0178 ISOlat2
+'&circ;' => '&#710;', # modifier letter circumflex accent, U+02C6 ISOpub
+'&tilde;' => '&#732;', # small tilde, U+02DC ISOdia
+'&ensp;' => '&#8194;', # en space, U+2002 ISOpub
+'&emsp;' => '&#8195;', # em space, U+2003 ISOpub
+'&thinsp;' => '&#8201;', # thin space, U+2009 ISOpub
+'&zwnj;' => '&#8204;', # zero width non-joiner, U+200C NEW RFC 2070
+'&zwj;' => '&#8205;', # zero width joiner, U+200D NEW RFC 2070
+'&lrm;' => '&#8206;', # left-to-right mark, U+200E NEW RFC 2070
+'&rlm;' => '&#8207;', # right-to-left mark, U+200F NEW RFC 2070
+'&ndash;' => '&#8211;', # en dash, U+2013 ISOpub
+'&mdash;' => '&#8212;', # em dash, U+2014 ISOpub
+'&lsquo;' => '&#8216;', # left single quotation mark, U+2018 ISOnum
+'&rsquo;' => '&#8217;', # right single quotation mark, U+2019 ISOnum
+'&sbquo;' => '&#8218;', # single low-9 quotation mark, U+201A NEW
+'&ldquo;' => '&#8220;', # left double quotation mark, U+201C ISOnum
+'&rdquo;' => '&#8221;', # right double quotation mark, U+201D ISOnum
+'&bdquo;' => '&#8222;', # double low-9 quotation mark, U+201E NEW
+'&dagger;' => '&#8224;', # dagger, U+2020 ISOpub
+'&Dagger;' => '&#8225;', # double dagger, U+2021 ISOpub
+'&permil;' => '&#8240;', # per mille sign, U+2030 ISOtech
+'&lsaquo;' => '&#8249;', # single left-pointing angle quotation mark, U+2039 ISO proposed
+'&rsaquo;' => '&#8250;', # single right-pointing angle quotation mark, U+203A ISO proposed
+'&euro;' => '&#8364;', # euro sign, U+20AC NEW
+'&apos;' => '&#39;', # apostrophe = APL quote, U+0027 ISOnum
+];
diff --git a/vendor/mikespub/php-epub-meta/templates/epub.html b/vendor/mikespub/php-epub-meta/templates/epub.html
new file mode 100644
index 000000000..1a088f6c4
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/templates/epub.html
@@ -0,0 +1,81 @@
+<html>
+<head>
+ <title>EPub Manager</title>
+
+ <link rel="stylesheet" type="text/css" href="../assets/css/smoothness/jquery-ui-1.13.2.custom.min.css" />
+ <link rel="stylesheet" type="text/css" href="../assets/css/cleditor/jquery.cleditor-1.4.5.css" />
+ <link rel="stylesheet" type="text/css" href="../assets/css/style.css" />
+
+ <script type="text/javascript">
+ {{ alert }}
+ </script>
+</head>
+<body>
+
+<div id="wrapper">
+ <ul id="booklist">
+ {{ booklist }}
+ </ul>
+
+ <form action="" method="post" id="bookpanel" enctype="multipart/form-data">
+ <input type="hidden" name="book" value="{{ book }}" />
+
+ <table>
+ <tr>
+ <th>Title</th>
+ <td><input type="text" name="title" value="{{ title }}" /></td>
+ </tr>
+ <tr>
+ <th>Authors</th>
+ <td id="authors">
+ {{ authors }}
+ </td>
+ </tr>
+ <tr>
+ <th>Description<br />
+ <img src="{{ cover }}" id="cover" width="90"
+ class="{{ imgclass }}" />
+ </th>
+ <td><textarea name="description">{{ description }}</textarea></td>
+ </tr>
+ <tr>
+ <th>Subjects</th>
+ <td><input type="text" name="subjects" value="{{ subjects }}" /></td>
+ </tr>
+ <tr>
+ <th>Publisher</th>
+ <td><input type="text" name="publisher" value="{{ publisher }}" /></td>
+ </tr>
+ <tr>
+ <th>Copyright</th>
+ <td><input type="text" name="copyright" value="{{ copyright }}" /></td>
+ </tr>
+ <tr>
+ <th>Language</th>
+ <td><p><input type="text" name="language" value="{{ language }}" /></p></td>
+ </tr>
+ <tr>
+ <th>ISBN</th>
+ <td><p><input type="text" name="isbn" value="{{ isbn }}" /></p></td>
+ </tr>
+ <tr>
+ <th>Cover Image</th>
+ <td><p>
+ <input type="file" name="coverfile" />
+ URL: <input type="text" name="coverurl" value="" />
+ </p></td>
+ </table>
+ <div class="center">
+ <input name="save" type="submit" />
+ </div>
+ </form>
+
+ <!-- load at the end, for faster site load -->
+ <script type="text/javascript" src="../assets/js/jquery-3.7.1.min.js"></script>
+ <script type="text/javascript" src="../assets/js/jquery-ui-1.13.2.custom.min.js"></script>
+ <script type="text/javascript" src="../assets/js/jquery.cleditor-1.4.5.min.js"></script>
+ <script type="text/javascript" src="../assets/js/script.js"></script>
+
+</div>
+</body>
+</html>
diff --git a/vendor/mikespub/php-epub-meta/templates/index.html b/vendor/mikespub/php-epub-meta/templates/index.html
new file mode 100644
index 000000000..cc8bdba68
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/templates/index.html
@@ -0,0 +1,35 @@
+<html>
+<head>
+ <title>EPub Manager</title>
+
+ <link rel="stylesheet" type="text/css" href="../assets/css/smoothness/jquery-ui-1.13.2.custom.min.css" />
+ <link rel="stylesheet" type="text/css" href="../assets/css/cleditor/jquery.cleditor-1.4.5.css" />
+ <link rel="stylesheet" type="text/css" href="../assets/css/style.css" />
+
+ <script type="text/javascript">
+ {{ alert }}
+ </script>
+</head>
+<body>
+
+<div id="wrapper">
+ <ul id="booklist">
+ {{ booklist }}
+ </ul>
+
+ <h1>EPub Manager</h1>
+
+ <p>View and edit epub books stored in <code>{{ bookdir }}</code>.</p>
+ <div class="license">
+ <p>{{ license }}</p>
+ </div>
+
+ <!-- load at the end, for faster site load -->
+ <script type="text/javascript" src="../assets/js/jquery-3.7.1.min.js"></script>
+ <script type="text/javascript" src="../assets/js/jquery-ui-1.13.2.custom.min.js"></script>
+ <script type="text/javascript" src="../assets/js/jquery.cleditor-1.4.5.min.js"></script>
+ <script type="text/javascript" src="../assets/js/script.js"></script>
+
+</div>
+</body>
+</html>
diff --git a/vendor/mikespub/php-epub-meta/templates/titlepage.xhtml b/vendor/mikespub/php-epub-meta/templates/titlepage.xhtml
new file mode 100644
index 000000000..c617f676b
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/templates/titlepage.xhtml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<html xmlns="http://www.w3.org/1999/xhtml">
+
+<head>
+ <title>{{ title }}</title>
+</head>
+
+<body>
+ <div style="text-align: center;">
+ <img alt="{{ title }}" src="{{ coverPath }}" style="max-width: 100%; max-height: 100%;" />
+ </div>
+</body>
+
+</html> \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/test/.gitignore b/vendor/mikespub/php-epub-meta/test/.gitignore
new file mode 100644
index 000000000..46e7bc5e7
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/.gitignore
@@ -0,0 +1 @@
+data/test.cover.epub
diff --git a/vendor/mikespub/php-epub-meta/test/data/broken.zip b/vendor/mikespub/php-epub-meta/test/data/broken.zip
new file mode 100644
index 000000000..0c407313c
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/broken.zip
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/test/data/calibre_bookmarks.txt b/vendor/mikespub/php-epub-meta/test/data/calibre_bookmarks.txt
new file mode 100644
index 000000000..f4d518ab8
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/calibre_bookmarks.txt
@@ -0,0 +1,26 @@
+encoding=json+base64:
+W3sidGl0bGUiOiAiQWJvdXQgIzEiLCAicG9zX3R5cGUiOiAiZXB1YmNmaSIsICJwb3MiOiAiZXB1YmNm
+aSgvNi8yLzQvMi82LzI6MzgpIiwgInRpbWVzdGFtcCI6ICIyMDI0LTAzLTExVDExOjU0OjM1LjEyODM5
+NiswMDowMCIsICJ0eXBlIjogImJvb2ttYXJrIn0sIHsicG9zIjogImVwdWJjZmkoLzgvMi80LzIvMltj
+aGFwdGVyXzQ1OF0vNC80LzE6Mjg3KSIsICJwb3NfdHlwZSI6ICJlcHViY2ZpIiwgInRpbWVzdGFtcCI6
+ICIyMDI0LTAzLTExVDExOjU3OjUxLjAwMDM4NyswMDowMCIsICJ0eXBlIjogImxhc3QtcmVhZCJ9LCB7
+ImVuZF9jZmkiOiAiLzIvNC8yLzIvNi8xOjI0IiwgImhpZ2hsaWdodGVkX3RleHQiOiAiQ2hhcmxlcyBM
+dXR3aWRnZSBEb2Rnc29uIiwgIm5vdGVzIjogIkZ1bGwgYXV0aG9yIG5hbWUiLCAic3BpbmVfaW5kZXgi
+OiAyLCAic3BpbmVfbmFtZSI6ICJPUFMvYWJvdXQueG1sIiwgInN0YXJ0X2NmaSI6ICIvMi80LzIvMi82
+LzE6MCIsICJzdHlsZSI6IHsia2luZCI6ICJjb2xvciIsICJ0eXBlIjogImJ1aWx0aW4iLCAid2hpY2gi
+OiAieWVsbG93In0sICJ0aW1lc3RhbXAiOiAiMjAyNC0wMy0xMVQxMTo1Mzo1NS41ODNaIiwgInRvY19m
+YW1pbHlfdGl0bGVzIjogWyJBYm91dCJdLCAidHlwZSI6ICJoaWdobGlnaHQiLCAidXVpZCI6ICI1SEhH
+dW9DT3RwQS11bWFJYkJ1YzBRIn0sIHsiZW5kX2NmaSI6ICIvMi80LzIvMi82LzE6MTA2IiwgImhpZ2hs
+aWdodGVkX3RleHQiOiAiTGV3aXMgQ2Fycm9sbCIsICJzcGluZV9pbmRleCI6IDIsICJzcGluZV9uYW1l
+IjogIk9QUy9hYm91dC54bWwiLCAic3RhcnRfY2ZpIjogIi8yLzQvMi8yLzYvMTo5MyIsICJzdHlsZSI6
+IHsia2luZCI6ICJjb2xvciIsICJ0eXBlIjogImJ1aWx0aW4iLCAid2hpY2giOiAieWVsbG93In0sICJ0
+aW1lc3RhbXAiOiAiMjAyNC0wMy0xMVQxMTo1NTozMi43MzRaIiwgInRvY19mYW1pbHlfdGl0bGVzIjog
+WyJBYm91dCJdLCAidHlwZSI6ICJoaWdobGlnaHQiLCAidXVpZCI6ICJpdUdUeS1XSVhXRGluQnVzenBw
+R3dBIn0sIHsiZW5kX2NmaSI6ICIvMi80LzIvMltjaGFwdGVyXzQ1OF0vNC8yLzE6NSIsICJoaWdobGln
+aHRlZF90ZXh0IjogIkFsaWNlIiwgIm5vdGVzIjogIlByb3RhZ29uaXN0IiwgInNwaW5lX2luZGV4Ijog
+MywgInNwaW5lX25hbWUiOiAiT1BTL21haW4wLnhtbCIsICJzdGFydF9jZmkiOiAiLzIvNC8yLzJbY2hh
+cHRlcl80NThdLzQvMi8xOjAiLCAic3R5bGUiOiB7ImtpbmQiOiAiY29sb3IiLCAidHlwZSI6ICJidWls
+dGluIiwgIndoaWNoIjogInllbGxvdyJ9LCAidGltZXN0YW1wIjogIjIwMjQtMDMtMTFUMTE6NTY6NTIu
+ODkxWiIsICJ0b2NfZmFtaWx5X3RpdGxlcyI6IFsiQ2hhcHRlciAxIC0gRG93biB0aGUgUmFiYml0IEhv
+bGUiXSwgInR5cGUiOiAiaGlnaGxpZ2h0IiwgInV1aWQiOiAiS0ZHTlhWQjJIZWI1M2doc0FqVnF2USJ9
+XQ== \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/test/data/empty.zip b/vendor/mikespub/php-epub-meta/test/data/empty.zip
new file mode 100644
index 000000000..15cb0ecb3
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/empty.zip
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/test/data/eng.components.json b/vendor/mikespub/php-epub-meta/test/data/eng.components.json
new file mode 100644
index 000000000..59e7646f8
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/eng.components.json
@@ -0,0 +1,16 @@
+[
+ "text/titlepage.xhtml",
+ "text/internal_titlepage.xhtml",
+ "text/toc.xhtml",
+ "text/introduction.xhtml",
+ "text/installing_calibre.xhtml",
+ "text/the_main_gui_window.xhtml",
+ "text/common_tasks.xhtml",
+ "text/task_1_organizing.xhtml",
+ "text/task_2_conversion.xhtml",
+ "text/task_3_the_ebook_editor.xhtml",
+ "text/task_4_downloading_news.xhtml",
+ "text/task_5_interacting_with_ebook_readers.xhtml",
+ "text/task_6_the_ebook_viewer.xhtml",
+ "text/where_to_get_help.xhtml"
+] \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/test/data/eng.contents.json b/vendor/mikespub/php-epub-meta/test/data/eng.contents.json
new file mode 100644
index 000000000..90dd2208e
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/eng.contents.json
@@ -0,0 +1,96 @@
+[
+ {
+ "title": "Calibre Quick Start Guide",
+ "src": "text/internal_titlepage.xhtml"
+ },
+ {
+ "title": "Table of Contents",
+ "src": "text/toc.xhtml"
+ },
+ {
+ "title": "Introduction",
+ "src": "text/introduction.xhtml"
+ },
+ {
+ "title": "Installing calibre",
+ "src": "text/installing_calibre.xhtml"
+ },
+ {
+ "title": "The Main Library Window, aka the GUI",
+ "src": "text/the_main_gui_window.xhtml"
+ },
+ {
+ "title": "Common Tasks",
+ "src": "text/common_tasks.xhtml",
+ "children": [
+ {
+ "title": "Task 1: Organizing",
+ "src": "text/task_1_organizing.xhtml"
+ },
+ {
+ "title": "Task 2: Conversion",
+ "src": "text/task_2_conversion.xhtml",
+ "children": [
+ {
+ "title": "2.1: Background",
+ "src": "text/task_2_conversion.xhtml#task2.1"
+ },
+ {
+ "title": "2.2: Why are there different e-book formats?",
+ "src": "text/task_2_conversion.xhtml#task2.2"
+ },
+ {
+ "title": "2.3: Conversion basics",
+ "src": "text/task_2_conversion.xhtml#task2.3"
+ },
+ {
+ "title": "2.4: Auto Conversion",
+ "src": "text/task_2_conversion.xhtml#task2.4"
+ },
+ {
+ "title": "2.5: More robust conversion",
+ "src": "text/task_2_conversion.xhtml#task2.5"
+ },
+ {
+ "title": "2.6: Limitations of conversion",
+ "src": "text/task_2_conversion.xhtml#task2.6"
+ },
+ {
+ "title": "2.7: DRM: the bane of conversion",
+ "src": "text/task_2_conversion.xhtml#task2.7"
+ }
+ ]
+ },
+ {
+ "title": "Task 3: The e-book editor",
+ "src": "text/task_3_the_ebook_editor.xhtml"
+ },
+ {
+ "title": "Task 4: Downloading News",
+ "src": "text/task_4_downloading_news.xhtml"
+ },
+ {
+ "title": "Task 5: Interacting with e-book readers",
+ "src": "text/task_5_interacting_with_ebook_readers.xhtml",
+ "children": [
+ {
+ "title": "5.1: Putting an e-book on your e-book reader",
+ "src": "text/task_5_interacting_with_ebook_readers.xhtml#task5.1"
+ },
+ {
+ "title": "5.2: E-book reader optional configuration",
+ "src": "text/task_5_interacting_with_ebook_readers.xhtml#task5.2"
+ }
+ ]
+ },
+ {
+ "title": "Task 6: The e-book viewer",
+ "src": "text/task_6_the_ebook_viewer.xhtml"
+ }
+ ]
+ },
+ {
+ "title": "Where to get help",
+ "src": "text/where_to_get_help.xhtml"
+ }
+]
diff --git a/vendor/mikespub/php-epub-meta/test/data/eng.epub b/vendor/mikespub/php-epub-meta/test/data/eng.epub
new file mode 100644
index 000000000..fd256d41a
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/eng.epub
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/test/data/eng3.epub b/vendor/mikespub/php-epub-meta/test/data/eng3.epub
new file mode 100644
index 000000000..5fad2dd76
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/eng3.epub
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/test/data/markup.1.xml b/vendor/mikespub/php-epub-meta/test/data/markup.1.xml
new file mode 100644
index 000000000..ac1e50e57
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/markup.1.xml
@@ -0,0 +1,41 @@
+<div>
+ <div>
+ <h3>Act I</h3>
+ <div>
+ <h3>Prologue</h3>
+ <div>
+
+ <p>Two households, both alike in dignity,
+ <br />
+ In fair Verona, where we lay our scene,
+ <br />
+ From ancient grudge break to new mutiny,
+ <br />
+ Where civil blood makes civil hands unclean.
+ <br />
+ From forth the fatal loins of these two foes
+ <br />
+ A pair of star-cross'd lovers take their life;
+ <br />
+ Whole misadventured piteous overthrows
+ <br />
+ Do with their death bury their parents' strife.
+ <br />
+ The fearful passage of their death-mark'd love,
+ <br />
+ And the continuance of their parents' rage,
+ <br />
+ Which, but their children's end, nought could remove,
+ <br />
+ Is now the two hours' traffic of our stage;
+ <br />
+ The which if you with patient ears attend,
+ <br />
+ What here shall miss, our toil shall strive to mend.
+ </p>
+
+
+ </div>
+ </div>
+ </div>
+</div> \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/test/data/markup.2.xml b/vendor/mikespub/php-epub-meta/test/data/markup.2.xml
new file mode 100644
index 000000000..643df54a7
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/markup.2.xml
@@ -0,0 +1,1175 @@
+<div>
+ <div>
+ <h3>SCENE I. Verona. A public place.</h3>
+ <div>
+
+ <p>Enter SAMPSON and GREGORY, of the house of Capulet, armed
+ with swords and bucklers
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>Gregory, o' my word, we'll not carry coals.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>No, for then we should be colliers.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>I mean, an we be in choler, we'll draw.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>Ay, while you live, draw your neck out o' the collar.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>I strike quickly, being moved.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>But thou art not quickly moved to strike.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>A dog of the house of Montague moves me.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>To move is to stir; and to be valiant is to stand:
+ <br />
+ therefore, if thou art moved, thou runn'st away.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>A dog of that house shall move me to stand: I will
+ <br />
+ take the wall of any man or maid of Montague's.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>That shows thee a weak slave; for the weakest goes
+ <br />
+ to the wall.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>True; and therefore women, being the weaker vessels,
+ <br />
+ are ever thrust to the wall: therefore I will push
+ <br />
+ Montague's men from the wall, and thrust his maids
+ <br />
+ to the wall.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>The quarrel is between our masters and us their men.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>'Tis all one, I will show myself a tyrant: when I
+ <br />
+ have fought with the men, I will be cruel with the
+ <br />
+ maids, and cut off their heads.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>The heads of the maids?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>Ay, the heads of the maids, or their maidenheads;
+ <br />
+ take it in what sense thou wilt.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>They must take it in sense that feel it.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>Me they shall feel while I am able to stand: and
+ <br />
+ 'tis known I am a pretty piece of flesh.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>'Tis well thou art not fish; if thou hadst, thou
+ <br />
+ hadst been poor John. Draw thy tool! here comes
+ <br />
+ two of the house of the Montagues.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>My naked weapon is out: quarrel, I will back thee.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>How! turn thy back and run?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>Fear me not.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>No, marry; I fear thee!
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>Let us take the law of our sides; let them begin.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>I will frown as I pass by, and let them take it as
+ <br />
+ they list.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>Nay, as they dare. I will bite my thumb at them;
+ <br />
+ which is a disgrace to them, if they bear it.
+ <br />
+ </p>
+ <p>Enter ABRAHAM and BALTHASAR</p>
+
+
+ <p>
+ <strong>ABRAHAM</strong>
+ </p>
+
+ <p>Do you bite your thumb at us, sir?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>I do bite my thumb, sir.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ABRAHAM</strong>
+ </p>
+
+ <p>Do you bite your thumb at us, sir?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>[Aside to GREGORY] Is the law of our side, if I say
+ <br />
+ ay?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>No.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>No, sir, I do not bite my thumb at you, sir, but I
+ <br />
+ bite my thumb, sir.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>Do you quarrel, sir?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ABRAHAM</strong>
+ </p>
+
+ <p>Quarrel sir! no, sir.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>If you do, sir, I am for you: I serve as good a man as
+ you.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ABRAHAM</strong>
+ </p>
+
+ <p>No better.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>Well, sir.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>GREGORY</strong>
+ </p>
+
+ <p>Say 'better:' here comes one of my master's kinsmen.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>Yes, better, sir.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ABRAHAM</strong>
+ </p>
+
+ <p>You lie.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>SAMPSON</strong>
+ </p>
+
+ <p>Draw, if you be men. Gregory, remember thy swashing
+ blow.
+ <br />
+ </p>
+ <p>They fight</p>
+ <p>Enter BENVOLIO</p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Part, fools!
+ <br />
+ Put up your swords; you know not what you do.
+ <br />
+ </p>
+ <p>Beats down their swords</p>
+ <p>Enter TYBALT</p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>What, art thou drawn among these heartless hinds?
+ <br />
+ Turn thee, Benvolio, look upon thy death.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>I do but keep the peace: put up thy sword,
+ <br />
+ Or manage it to part these men with me.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>What, drawn, and talk of peace! I hate the word,
+ <br />
+ As I hate hell, all Montagues, and thee:
+ <br />
+ Have at thee, coward!
+ <br />
+ </p>
+ <p>They fight</p>
+ <p>Enter, several of both houses, who join the fray; then enter
+ Citizens, with clubs
+ </p>
+
+
+ <p>
+ <strong>First Citizen</strong>
+ </p>
+
+ <p>Clubs, bills, and partisans! strike! beat them down!
+ <br />
+ Down with the Capulets! down with the Montagues!
+ <br />
+ </p>
+ <p>Enter CAPULET in his gown, and LADY CAPULET</p>
+
+
+ <p>
+ <strong>CAPULET</strong>
+ </p>
+
+ <p>What noise is this? Give me my long sword, ho!
+ <br />
+ </p>
+
+
+ <p>
+ <strong>LADY CAPULET</strong>
+ </p>
+
+ <p>A crutch, a crutch! why call you for a sword?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>CAPULET</strong>
+ </p>
+
+ <p>My sword, I say! Old Montague is come,
+ <br />
+ And flourishes his blade in spite of me.
+ <br />
+ </p>
+ <p>Enter MONTAGUE and LADY MONTAGUE</p>
+
+
+ <p>
+ <strong>MONTAGUE</strong>
+ </p>
+
+ <p>Thou villain Capulet,—Hold me not, let me go.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>LADY MONTAGUE</strong>
+ </p>
+
+ <p>Thou shalt not stir a foot to seek a foe.
+ <br />
+ </p>
+ <p>Enter PRINCE, with Attendants</p>
+
+
+ <p>
+ <strong>PRINCE</strong>
+ </p>
+
+ <p>Rebellious subjects, enemies to peace,
+ <br />
+ Profaners of this neighbour-stained steel,—
+ <br />
+ Will they not hear? What, ho! you men, you beasts,
+ <br />
+ That quench the fire of your pernicious rage
+ <br />
+ With purple fountains issuing from your veins,
+ <br />
+ On pain of torture, from those bloody hands
+ <br />
+ Throw your mistemper'd weapons to the ground,
+ <br />
+ And hear the sentence of your moved prince.
+ <br />
+ Three civil brawls, bred of an airy word,
+ <br />
+ By thee, old Capulet, and Montague,
+ <br />
+ Have thrice disturb'd the quiet of our streets,
+ <br />
+ And made Verona's ancient citizens
+ <br />
+ Cast by their grave beseeming ornaments,
+ <br />
+ To wield old partisans, in hands as old,
+ <br />
+ Canker'd with peace, to part your canker'd hate:
+ <br />
+ If ever you disturb our streets again,
+ <br />
+ Your lives shall pay the forfeit of the peace.
+ <br />
+ For this time, all the rest depart away:
+ <br />
+ You Capulet; shall go along with me:
+ <br />
+ And, Montague, come you this afternoon,
+ <br />
+ To know our further pleasure in this case,
+ <br />
+ To old Free-town, our common judgment-place.
+ <br />
+ Once more, on pain of death, all men depart.
+ <br />
+ </p>
+ <p>Exeunt all but MONTAGUE, LADY MONTAGUE, and
+ BENVOLIO
+ </p>
+
+
+ <p>
+ <strong>MONTAGUE</strong>
+ </p>
+
+ <p>Who set this ancient quarrel new abroach?
+ <br />
+ Speak, nephew, were you by when it began?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Here were the servants of your adversary,
+ <br />
+ And yours, close fighting ere I did approach:
+ <br />
+ I drew to part them: in the instant came
+ <br />
+ The fiery Tybalt, with his sword prepared,
+ <br />
+ Which, as he breathed defiance to my ears,
+ <br />
+ He swung about his head and cut the winds,
+ <br />
+ Who nothing hurt withal hiss'd him in scorn:
+ <br />
+ While we were interchanging thrusts and blows,
+ <br />
+ Came more and more and fought on part and part,
+ <br />
+ Till the prince came, who parted either part.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>LADY MONTAGUE</strong>
+ </p>
+
+ <p>O, where is Romeo? saw you him to-day?
+ <br />
+ Right glad I am he was not at this fray.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Madam, an hour before the worshipp'd sun
+ <br />
+ Peer'd forth the golden window of the east,
+ <br />
+ A troubled mind drave me to walk abroad;
+ <br />
+ Where, underneath the grove of sycamore
+ <br />
+ That westward rooteth from the city's side,
+ <br />
+ So early walking did I see your son:
+ <br />
+ Towards him I made, but he was ware of me
+ <br />
+ And stole into the covert of the wood:
+ <br />
+ I, measuring his affections by my own,
+ <br />
+ That most are busied when they're most alone,
+ <br />
+ Pursued my humour not pursuing his,
+ <br />
+ And gladly shunn'd who gladly fled from me.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MONTAGUE</strong>
+ </p>
+
+ <p>Many a morning hath he there been seen,
+ <br />
+ With tears augmenting the fresh morning dew.
+ <br />
+ Adding to clouds more clouds with his deep sighs;
+ <br />
+ But all so soon as the all-cheering sun
+ <br />
+ Should in the furthest east begin to draw
+ <br />
+ The shady curtains from Aurora's bed,
+ <br />
+ Away from the light steals home my heavy son,
+ <br />
+ And private in his chamber pens himself,
+ <br />
+ Shuts up his windows, locks far daylight out
+ <br />
+ And makes himself an artificial night:
+ <br />
+ Black and portentous must this humour prove,
+ <br />
+ Unless good counsel may the cause remove.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>My noble uncle, do you know the cause?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MONTAGUE</strong>
+ </p>
+
+ <p>I neither know it nor can learn of him.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Have you importuned him by any means?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MONTAGUE</strong>
+ </p>
+
+ <p>Both by myself and many other friends:
+ <br />
+ But he, his own affections' counsellor,
+ <br />
+ Is to himself—I will not say how true—
+ <br />
+ But to himself so secret and so close,
+ <br />
+ So far from sounding and discovery,
+ <br />
+ As is the bud bit with an envious worm,
+ <br />
+ Ere he can spread his sweet leaves to the air,
+ <br />
+ Or dedicate his beauty to the sun.
+ <br />
+ Could we but learn from whence his sorrows grow.
+ <br />
+ We would as willingly give cure as know.
+ <br />
+ </p>
+ <p>Enter ROMEO</p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>See, where he comes: so please you, step aside;
+ <br />
+ I'll know his grievance, or be much denied.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MONTAGUE</strong>
+ </p>
+
+ <p>I would thou wert so happy by thy stay,
+ <br />
+ To hear true shrift. Come, madam, let's away.
+ <br />
+ </p>
+ <p>Exeunt MONTAGUE and LADY MONTAGUE</p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Good-morrow, cousin.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Is the day so young?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>But new struck nine.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Ay me! sad hours seem long.
+ <br />
+ Was that my father that went hence so fast?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>It was. What sadness lengthens Romeo's hours?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Not having that, which, having, makes them short.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>In love?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Out—
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Of love?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Out of her favour, where I am in love.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Alas, that love, so gentle in his view,
+ <br />
+ Should be so tyrannous and rough in proof!
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Alas, that love, whose view is muffled still,
+ <br />
+ Should, without eyes, see pathways to his will!
+ <br />
+ Where shall we dine? O me! What fray was here?
+ <br />
+ Yet tell me not, for I have heard it all.
+ <br />
+ Here's much to do with hate, but more with love.
+ <br />
+ Why, then, O brawling love! O loving hate!
+ <br />
+ O any thing, of nothing first create!
+ <br />
+ O heavy lightness! serious vanity!
+ <br />
+ Mis-shapen chaos of well-seeming forms!
+ <br />
+ Feather of lead, bright smoke, cold fire,
+ <br />
+ sick health!
+ <br />
+ Still-waking sleep, that is not what it is!
+ <br />
+ This love feel I, that feel no love in this.
+ <br />
+ Dost thou not laugh?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>No, coz, I rather weep.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Good heart, at what?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>At thy good heart's oppression.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Why, such is love's transgression.
+ <br />
+ Griefs of mine own lie heavy in my breast,
+ <br />
+ Which thou wilt propagate, to have it prest
+ <br />
+ With more of thine: this love that thou hast shown
+ <br />
+ Doth add more grief to too much of mine own.
+ <br />
+ Love is a smoke raised with the fume of sighs;
+ <br />
+ Being purged, a fire sparkling in lovers' eyes;
+ <br />
+ Being vex'd a sea nourish'd with lovers' tears:
+ <br />
+ What is it else? a madness most discreet,
+ <br />
+ A choking gall and a preserving sweet.
+ <br />
+ Farewell, my coz.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Soft! I will go along;
+ <br />
+ An if you leave me so, you do me wrong.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Tut, I have lost myself; I am not here;
+ <br />
+ This is not Romeo, he's some other where.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Tell me in sadness, who is that you love.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>What, shall I groan and tell thee?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Groan! why, no.
+ <br />
+ But sadly tell me who.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Bid a sick man in sadness make his will:
+ <br />
+ Ah, word ill urged to one that is so ill!
+ <br />
+ In sadness, cousin, I do love a woman.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>I aim'd so near, when I supposed you loved.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>A right good mark-man! And she's fair I love.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>A right fair mark, fair coz, is soonest hit.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Well, in that hit you miss: she'll not be hit
+ <br />
+ With Cupid's arrow; she hath Dian's wit;
+ <br />
+ And, in strong proof of chastity well arm'd,
+ <br />
+ From love's weak childish bow she lives unharm'd.
+ <br />
+ She will not stay the siege of loving terms,
+ <br />
+ Nor bide the encounter of assailing eyes,
+ <br />
+ Nor ope her lap to saint-seducing gold:
+ <br />
+ O, she is rich in beauty, only poor,
+ <br />
+ That when she dies with beauty dies her store.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Then she hath sworn that she will still live chaste?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>She hath, and in that sparing makes huge waste,
+ <br />
+ For beauty starved with her severity
+ <br />
+ Cuts beauty off from all posterity.
+ <br />
+ She is too fair, too wise, wisely too fair,
+ <br />
+ To merit bliss by making me despair:
+ <br />
+ She hath forsworn to love, and in that vow
+ <br />
+ Do I live dead that live to tell it now.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Be ruled by me, forget to think of her.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>O, teach me how I should forget to think.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>By giving liberty unto thine eyes;
+ <br />
+ Examine other beauties.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>'Tis the way
+ <br />
+ To call hers exquisite, in question more:
+ <br />
+ These happy masks that kiss fair ladies' brows
+ <br />
+ Being black put us in mind they hide the fair;
+ <br />
+ He that is strucken blind cannot forget
+ <br />
+ The precious treasure of his eyesight lost:
+ <br />
+ Show me a mistress that is passing fair,
+ <br />
+ What doth her beauty serve, but as a note
+ <br />
+ Where I may read who pass'd that passing fair?
+ <br />
+ Farewell: thou canst not teach me to forget.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>I'll pay that doctrine, or else die in debt.
+ <br />
+ </p>
+ <p>Exeunt</p>
+
+
+ </div>
+ </div>
+</div>
+
diff --git a/vendor/mikespub/php-epub-meta/test/data/markup.3.xml b/vendor/mikespub/php-epub-meta/test/data/markup.3.xml
new file mode 100644
index 000000000..58ffb5d11
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/markup.3.xml
@@ -0,0 +1,3 @@
+<div>
+ <h3>Act III</h3>
+</div> \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/test/data/markup.4.xml b/vendor/mikespub/php-epub-meta/test/data/markup.4.xml
new file mode 100644
index 000000000..fdda27bac
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/markup.4.xml
@@ -0,0 +1,5 @@
+<div>
+ <div>
+ <h3>Act III</h3>
+ </div>
+</div> \ No newline at end of file
diff --git a/vendor/mikespub/php-epub-meta/test/data/markup.5.xml b/vendor/mikespub/php-epub-meta/test/data/markup.5.xml
new file mode 100644
index 000000000..52e046b5c
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/markup.5.xml
@@ -0,0 +1,860 @@
+<div>
+ <h3>SCENE I. A public place.</h3>
+ <div>
+
+ <p>Enter MERCUTIO, BENVOLIO, Page, and Servants</p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>I pray thee, good Mercutio, let's retire:
+ <br />
+ The day is hot, the Capulets abroad,
+ <br />
+ And, if we meet, we shall not scape a brawl;
+ <br />
+ For now, these hot days, is the mad blood stirring.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Thou art like one of those fellows that when he
+ <br />
+ enters the confines of a tavern claps me his sword
+ <br />
+ upon the table and says 'God send me no need of
+ <br />
+ thee!' and by the operation of the second cup draws
+ <br />
+ it on the drawer, when indeed there is no need.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Am I like such a fellow?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Come, come, thou art as hot a Jack in thy mood as
+ <br />
+ any in Italy, and as soon moved to be moody, and as
+ <br />
+ soon moody to be moved.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>And what to?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Nay, an there were two such, we should have none
+ <br />
+ shortly, for one would kill the other. Thou! why,
+ <br />
+ thou wilt quarrel with a man that hath a hair more,
+ <br />
+ or a hair less, in his beard, than thou hast: thou
+ <br />
+ wilt quarrel with a man for cracking nuts, having no
+ <br />
+ other reason but because thou hast hazel eyes: what
+ <br />
+ eye but such an eye would spy out such a quarrel?
+ <br />
+ Thy head is as fun of quarrels as an egg is full of
+ <br />
+ meat, and yet thy head hath been beaten as addle as
+ <br />
+ an egg for quarrelling: thou hast quarrelled with a
+ <br />
+ man for coughing in the street, because he hath
+ <br />
+ wakened thy dog that hath lain asleep in the sun:
+ <br />
+ didst thou not fall out with a tailor for wearing
+ <br />
+ his new doublet before Easter? with another, for
+ <br />
+ tying his new shoes with old riband? and yet thou
+ <br />
+ wilt tutor me from quarrelling!
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>An I were so apt to quarrel as thou art, any man
+ <br />
+ should buy the fee-simple of my life for an hour and a
+ quarter.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>The fee-simple! O simple!
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>By my head, here come the Capulets.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>By my heel, I care not.
+ <br />
+ </p>
+ <p>Enter TYBALT and others</p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>Follow me close, for I will speak to them.
+ <br />
+ Gentlemen, good den: a word with one of you.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>And but one word with one of us? couple it with
+ <br />
+ something; make it a word and a blow.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>You shall find me apt enough to that, sir, an you
+ <br />
+ will give me occasion.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Could you not take some occasion without giving?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>Mercutio, thou consort'st with Romeo,—
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Consort! what, dost thou make us minstrels? an
+ <br />
+ thou make minstrels of us, look to hear nothing but
+ <br />
+ discords: here's my fiddlestick; here's that shall
+ <br />
+ make you dance. 'Zounds, consort!
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>We talk here in the public haunt of men:
+ <br />
+ Either withdraw unto some private place,
+ <br />
+ And reason coldly of your grievances,
+ <br />
+ Or else depart; here all eyes gaze on us.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Men's eyes were made to look, and let them gaze;
+ <br />
+ I will not budge for no man's pleasure, I.
+ <br />
+ </p>
+ <p>Enter ROMEO</p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>Well, peace be with you, sir: here comes my man.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>But I'll be hanged, sir, if he wear your livery:
+ <br />
+ Marry, go before to field, he'll be your follower;
+ <br />
+ Your worship in that sense may call him 'man.'
+ <br />
+ </p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>Romeo, the hate I bear thee can afford
+ <br />
+ No better term than this,—thou art a villain.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Tybalt, the reason that I have to love thee
+ <br />
+ Doth much excuse the appertaining rage
+ <br />
+ To such a greeting: villain am I none;
+ <br />
+ Therefore farewell; I see thou know'st me not.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>Boy, this shall not excuse the injuries
+ <br />
+ That thou hast done me; therefore turn and draw.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>I do protest, I never injured thee,
+ <br />
+ But love thee better than thou canst devise,
+ <br />
+ Till thou shalt know the reason of my love:
+ <br />
+ And so, good Capulet,—which name I tender
+ <br />
+ As dearly as my own,—be satisfied.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>O calm, dishonourable, vile submission!
+ <br />
+ Alla stoccata carries it away.
+ <br />
+ </p>
+ <p>Draws</p>
+ <p>Tybalt, you rat-catcher, will you walk?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>What wouldst thou have with me?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Good king of cats, nothing but one of your nine
+ <br />
+ lives; that I mean to make bold withal, and as you
+ <br />
+ shall use me hereafter, drybeat the rest of the
+ <br />
+ eight. Will you pluck your sword out of his pitcher
+ <br />
+ by the ears? make haste, lest mine be about your
+ <br />
+ ears ere it be out.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>I am for you.
+ <br />
+ </p>
+ <p>Drawing</p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Gentle Mercutio, put thy rapier up.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Come, sir, your passado.
+ <br />
+ </p>
+ <p>They fight</p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Draw, Benvolio; beat down their weapons.
+ <br />
+ Gentlemen, for shame, forbear this outrage!
+ <br />
+ Tybalt, Mercutio, the prince expressly hath
+ <br />
+ Forbidden bandying in Verona streets:
+ <br />
+ Hold, Tybalt! good Mercutio!
+ <br />
+ </p>
+ <p>TYBALT under ROMEO's arm stabs MERCUTIO, and flies with his
+ followers
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>I am hurt.
+ <br />
+ A plague o' both your houses! I am sped.
+ <br />
+ Is he gone, and hath nothing?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>What, art thou hurt?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Ay, ay, a scratch, a scratch; marry, 'tis enough.
+ <br />
+ Where is my page? Go, villain, fetch a surgeon.
+ <br />
+ </p>
+ <p>Exit Page</p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Courage, man; the hurt cannot be much.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>No, 'tis not so deep as a well, nor so wide as a
+ <br />
+ church-door; but 'tis enough,'twill serve: ask for
+ <br />
+ me to-morrow, and you shall find me a grave man. I
+ <br />
+ am peppered, I warrant, for this world. A plague o'
+ <br />
+ both your houses! 'Zounds, a dog, a rat, a mouse, a
+ <br />
+ cat, to scratch a man to death! a braggart, a
+ <br />
+ rogue, a villain, that fights by the book of
+ <br />
+ arithmetic! Why the devil came you between us? I
+ <br />
+ was hurt under your arm.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>I thought all for the best.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MERCUTIO</strong>
+ </p>
+
+ <p>Help me into some house, Benvolio,
+ <br />
+ Or I shall faint. A plague o' both your houses!
+ <br />
+ They have made worms' meat of me: I have it,
+ <br />
+ And soundly too: your houses!
+ <br />
+ </p>
+ <p>Exeunt MERCUTIO and BENVOLIO</p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>This gentleman, the prince's near ally,
+ <br />
+ My very friend, hath got his mortal hurt
+ <br />
+ In my behalf; my reputation stain'd
+ <br />
+ With Tybalt's slander,—Tybalt, that an hour
+ <br />
+ Hath been my kinsman! O sweet Juliet,
+ <br />
+ Thy beauty hath made me effeminate
+ <br />
+ And in my temper soften'd valour's steel!
+ <br />
+ </p>
+ <p>Re-enter BENVOLIO</p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>O Romeo, Romeo, brave Mercutio's dead!
+ <br />
+ That gallant spirit hath aspired the clouds,
+ <br />
+ Which too untimely here did scorn the earth.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>This day's black fate on more days doth depend;
+ <br />
+ This but begins the woe, others must end.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Here comes the furious Tybalt back again.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>Alive, in triumph! and Mercutio slain!
+ <br />
+ Away to heaven, respective lenity,
+ <br />
+ And fire-eyed fury be my conduct now!
+ <br />
+ </p>
+ <p>Re-enter TYBALT</p>
+ <p>Now, Tybalt, take the villain back again,
+ <br />
+ That late thou gavest me; for Mercutio's soul
+ <br />
+ Is but a little way above our heads,
+ <br />
+ Staying for thine to keep him company:
+ <br />
+ Either thou, or I, or both, must go with him.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>TYBALT</strong>
+ </p>
+
+ <p>Thou, wretched boy, that didst consort him here,
+ <br />
+ Shalt with him hence.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>This shall determine that.
+ <br />
+ </p>
+ <p>They fight; TYBALT falls</p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Romeo, away, be gone!
+ <br />
+ The citizens are up, and Tybalt slain.
+ <br />
+ Stand not amazed: the prince will doom thee death,
+ <br />
+ If thou art taken: hence, be gone, away!
+ <br />
+ </p>
+
+
+ <p>
+ <strong>ROMEO</strong>
+ </p>
+
+ <p>O, I am fortune's fool!
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Why dost thou stay?
+ <br />
+ </p>
+ <p>Exit ROMEO</p>
+ <p>Enter Citizens, &amp; c</p>
+
+
+ <p>
+ <strong>First Citizen</strong>
+ </p>
+
+ <p>Which way ran he that kill'd Mercutio?
+ <br />
+ Tybalt, that murderer, which way ran he?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>There lies that Tybalt.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>First Citizen</strong>
+ </p>
+
+ <p>Up, sir, go with me;
+ <br />
+ I charge thee in the princes name, obey.
+ <br />
+ </p>
+ <p>Enter Prince, attended; MONTAGUE, CAPULET, their Wives, and
+ others
+ </p>
+
+
+ <p>
+ <strong>PRINCE</strong>
+ </p>
+
+ <p>Where are the vile beginners of this fray?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>O noble prince, I can discover all
+ <br />
+ The unlucky manage of this fatal brawl:
+ <br />
+ There lies the man, slain by young Romeo,
+ <br />
+ That slew thy kinsman, brave Mercutio.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>LADY CAPULET</strong>
+ </p>
+
+ <p>Tybalt, my cousin! O my brother's child!
+ <br />
+ O prince! O cousin! husband! O, the blood is spilt
+ <br />
+ O my dear kinsman! Prince, as thou art true,
+ <br />
+ For blood of ours, shed blood of Montague.
+ <br />
+ O cousin, cousin!
+ <br />
+ </p>
+
+
+ <p>
+ <strong>PRINCE</strong>
+ </p>
+
+ <p>Benvolio, who began this bloody fray?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>BENVOLIO</strong>
+ </p>
+
+ <p>Tybalt, here slain, whom Romeo's hand did slay;
+ <br />
+ Romeo that spoke him fair, bade him bethink
+ <br />
+ How nice the quarrel was, and urged withal
+ <br />
+ Your high displeasure: all this uttered
+ <br />
+ With gentle breath, calm look, knees humbly bow'd,
+ <br />
+ Could not take truce with the unruly spleen
+ <br />
+ Of Tybalt deaf to peace, but that he tilts
+ <br />
+ With piercing steel at bold Mercutio's breast,
+ <br />
+ Who all as hot, turns deadly point to point,
+ <br />
+ And, with a martial scorn, with one hand beats
+ <br />
+ Cold death aside, and with the other sends
+ <br />
+ It back to Tybalt, whose dexterity,
+ <br />
+ Retorts it: Romeo he cries aloud,
+ <br />
+ 'Hold, friends! friends, part!' and, swifter than
+ <br />
+ his tongue,
+ <br />
+ His agile arm beats down their fatal points,
+ <br />
+ And 'twixt them rushes; underneath whose arm
+ <br />
+ An envious thrust from Tybalt hit the life
+ <br />
+ Of stout Mercutio, and then Tybalt fled;
+ <br />
+ But by and by comes back to Romeo,
+ <br />
+ Who had but newly entertain'd revenge,
+ <br />
+ And to 't they go like lightning, for, ere I
+ <br />
+ Could draw to part them, was stout Tybalt slain.
+ <br />
+ And, as he fell, did Romeo turn and fly.
+ <br />
+ This is the truth, or let Benvolio die.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>LADY CAPULET</strong>
+ </p>
+
+ <p>He is a kinsman to the Montague;
+ <br />
+ Affection makes him false; he speaks not true:
+ <br />
+ Some twenty of them fought in this black strife,
+ <br />
+ And all those twenty could but kill one life.
+ <br />
+ I beg for justice, which thou, prince, must give;
+ <br />
+ Romeo slew Tybalt, Romeo must not live.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>PRINCE</strong>
+ </p>
+
+ <p>Romeo slew him, he slew Mercutio;
+ <br />
+ Who now the price of his dear blood doth owe?
+ <br />
+ </p>
+
+
+ <p>
+ <strong>MONTAGUE</strong>
+ </p>
+
+ <p>Not Romeo, prince, he was Mercutio's friend;
+ <br />
+ His fault concludes but what the law should end,
+ <br />
+ The life of Tybalt.
+ <br />
+ </p>
+
+
+ <p>
+ <strong>PRINCE</strong>
+ </p>
+
+ <p>And for that offence
+ <br />
+ Immediately we do exile him hence:
+ <br />
+ I have an interest in your hate's proceeding,
+ <br />
+ My blood for your rude brawls doth lie a-bleeding;
+ <br />
+ But I'll amerce you with so strong a fine
+ <br />
+ That you shall all repent the loss of mine:
+ <br />
+ I will be deaf to pleading and excuses;
+ <br />
+ Nor tears nor prayers shall purchase out abuses:
+ <br />
+ Therefore use none: let Romeo hence in haste,
+ <br />
+ Else, when he's found, that hour is his last.
+ <br />
+ Bear hence this body and attend our will:
+ <br />
+ Mercy but murders, pardoning those that kill.
+ <br />
+ </p>
+ <p>Exeunt</p>
+
+
+ </div>
+</div>
+
+
+
diff --git a/vendor/mikespub/php-epub-meta/test/data/metadata.opf b/vendor/mikespub/php-epub-meta/test/data/metadata.opf
new file mode 100644
index 000000000..dc2f6e011
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/metadata.opf
@@ -0,0 +1,35 @@
+<?xml version='1.0' encoding='utf-8'?>
+<package xmlns="http://www.idpf.org/2007/opf" unique-identifier="uuid_id" version="2.0">
+ <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
+ <dc:identifier opf:scheme="calibre" id="calibre_id">17</dc:identifier>
+ <dc:identifier opf:scheme="uuid" id="uuid_id">d74fec58-06bc-4ba8-b8b4-24a91a58e6f9</dc:identifier>
+ <dc:title>Alice's Adventures in Wonderland</dc:title>
+ <dc:creator opf:file-as="Carroll, Lewis" opf:role="aut">Lewis Carroll</dc:creator>
+ <dc:contributor opf:file-as="calibre" opf:role="bkp">calibre (7.6.0) [https://calibre-ebook.com]</dc:contributor>
+ <dc:date>1897-04-10T23:00:00+00:00</dc:date>
+ <dc:description>&lt;p class="description"&gt;Alice's Adventures in Wonderland (1865) is a novel written by English author Charles Lutwidge Dodgson, better known under the pseudonym Lewis Carroll. It tells the story of a girl named Alice who falls down a rabbit-hole into a fantasy world populated by peculiar and anthropomorphic creatures.&lt;br&gt;The tale is filled with allusions to Dodgson's friends (and enemies), and to the lessons that British schoolchildren were expected to memorize. The tale plays with logic in ways that have made the story of lasting popularity with adults as well as children. It is considered to be one of the most characteristic examples of the genre of literary nonsense, and its narrative course and structure has been enormously influential, mainly in the fantasy genre.&lt;/p&gt;
+
+Alice's Adventures in Wonderland (1865) is a novel written by English author Charles Lutwidge Dodgson, better known under the pseudonym Lewis Carroll. It tells the story of a girl named Alice who falls down a rabbit-hole into a fantasy world populated by peculiar and anthropomorphic creatures.
+The tale is filled with allusions to Dodgson's friends (and enemies), and to the lessons that British schoolchildren were expected to memorize. The tale plays with logic in ways that have made the story of lasting popularity with adults as well as children. It is considered to be one of the most characteristic examples of the genre of literary nonsense, and its narrative course and structure has been enormously influential, mainly in the fantasy genre.</dc:description>
+ <dc:publisher>Macmillan and Co. London</dc:publisher>
+ <dc:language>eng</dc:language>
+ <dc:subject>Fantasy</dc:subject>
+ <dc:subject>Juvenile</dc:subject>
+ <dc:subject>Fiction</dc:subject>
+ <meta name="calibre:link_maps" content="{&quot;authors&quot;: {&quot;Lewis Carroll&quot;: &quot;http://www.wikidata.org/entity/Q38082&quot;}}"/>
+ <meta name="calibre:rating" content="4"/>
+ <meta name="calibre:timestamp" content="2012-04-11T12:12:09+00:00"/>
+ <meta name="calibre:title_sort" content="Alice's Adventures in Wonderland"/>
+ <meta name="calibre:user_metadata:#type1" content="{&quot;table&quot;: &quot;custom_column_3&quot;, &quot;column&quot;: &quot;value&quot;, &quot;datatype&quot;: &quot;text&quot;, &quot;is_multiple&quot;: null, &quot;kind&quot;: &quot;field&quot;, &quot;name&quot;: &quot;Type1&quot;, &quot;search_terms&quot;: [&quot;#type1&quot;], &quot;label&quot;: &quot;type1&quot;, &quot;colnum&quot;: 3, &quot;display&quot;: {&quot;use_decorations&quot;: 0}, &quot;is_custom&quot;: true, &quot;is_category&quot;: true, &quot;link_column&quot;: &quot;value&quot;, &quot;category_sort&quot;: &quot;value&quot;, &quot;is_csp&quot;: false, &quot;is_editable&quot;: true, &quot;rec_index&quot;: 22, &quot;#value#&quot;: &quot;text&quot;, &quot;#extra#&quot;: null, &quot;is_multiple2&quot;: {}}"/>
+ <meta name="calibre:user_metadata:#type2" content="{&quot;table&quot;: &quot;custom_column_2&quot;, &quot;column&quot;: &quot;value&quot;, &quot;datatype&quot;: &quot;text&quot;, &quot;is_multiple&quot;: &quot;|&quot;, &quot;kind&quot;: &quot;field&quot;, &quot;name&quot;: &quot;Type2&quot;, &quot;search_terms&quot;: [&quot;#type2&quot;], &quot;label&quot;: &quot;type2&quot;, &quot;colnum&quot;: 2, &quot;display&quot;: {&quot;is_names&quot;: false}, &quot;is_custom&quot;: true, &quot;is_category&quot;: true, &quot;link_column&quot;: &quot;value&quot;, &quot;category_sort&quot;: &quot;value&quot;, &quot;is_csp&quot;: false, &quot;is_editable&quot;: true, &quot;rec_index&quot;: 23, &quot;#value#&quot;: [&quot;tag1&quot;, &quot;tag2&quot;], &quot;#extra#&quot;: null, &quot;is_multiple2&quot;: {&quot;cache_to_list&quot;: &quot;|&quot;, &quot;ui_to_list&quot;: &quot;,&quot;, &quot;list_to_ui&quot;: &quot;, &quot;}}"/>
+ <meta name="calibre:user_metadata:#type4" content="{&quot;table&quot;: &quot;custom_column_1&quot;, &quot;column&quot;: &quot;value&quot;, &quot;datatype&quot;: &quot;series&quot;, &quot;is_multiple&quot;: null, &quot;kind&quot;: &quot;field&quot;, &quot;name&quot;: &quot;Type4&quot;, &quot;search_terms&quot;: [&quot;#type4&quot;], &quot;label&quot;: &quot;type4&quot;, &quot;colnum&quot;: 1, &quot;display&quot;: {}, &quot;is_custom&quot;: true, &quot;is_category&quot;: true, &quot;link_column&quot;: &quot;value&quot;, &quot;category_sort&quot;: &quot;value&quot;, &quot;is_csp&quot;: false, &quot;is_editable&quot;: true, &quot;rec_index&quot;: 24, &quot;#value#&quot;: &quot;SeriesLike&quot;, &quot;#extra#&quot;: 1.0, &quot;is_multiple2&quot;: {}}"/>
+ <meta name="calibre:annotation" content="{&quot;format&quot;: &quot;EPUB&quot;, &quot;user_type&quot;: &quot;local&quot;, &quot;user&quot;: &quot;viewer&quot;, &quot;annotation&quot;: {&quot;title&quot;: &quot;About #1&quot;, &quot;pos_type&quot;: &quot;epubcfi&quot;, &quot;pos&quot;: &quot;epubcfi(/6/2/4/2/6/2:38)&quot;, &quot;timestamp&quot;: &quot;2024-03-11T11:54:35.128396+00:00&quot;, &quot;type&quot;: &quot;bookmark&quot;}}"/>
+ <meta name="calibre:annotation" content="{&quot;format&quot;: &quot;EPUB&quot;, &quot;user_type&quot;: &quot;local&quot;, &quot;user&quot;: &quot;viewer&quot;, &quot;annotation&quot;: {&quot;end_cfi&quot;: &quot;/2/4/2/2/6/1:24&quot;, &quot;highlighted_text&quot;: &quot;Charles Lutwidge Dodgson&quot;, &quot;notes&quot;: &quot;Full author name&quot;, &quot;spine_index&quot;: 2, &quot;spine_name&quot;: &quot;OPS/about.xml&quot;, &quot;start_cfi&quot;: &quot;/2/4/2/2/6/1:0&quot;, &quot;style&quot;: {&quot;kind&quot;: &quot;color&quot;, &quot;type&quot;: &quot;builtin&quot;, &quot;which&quot;: &quot;yellow&quot;}, &quot;timestamp&quot;: &quot;2024-03-11T11:53:55.583Z&quot;, &quot;toc_family_titles&quot;: [&quot;About&quot;], &quot;type&quot;: &quot;highlight&quot;, &quot;uuid&quot;: &quot;5HHGuoCOtpA-umaIbBuc0Q&quot;}}"/>
+ <meta name="calibre:annotation" content="{&quot;format&quot;: &quot;EPUB&quot;, &quot;user_type&quot;: &quot;local&quot;, &quot;user&quot;: &quot;viewer&quot;, &quot;annotation&quot;: {&quot;end_cfi&quot;: &quot;/2/4/2/2[chapter_458]/4/2/1:5&quot;, &quot;highlighted_text&quot;: &quot;Alice&quot;, &quot;notes&quot;: &quot;Protagonist&quot;, &quot;spine_index&quot;: 3, &quot;spine_name&quot;: &quot;OPS/main0.xml&quot;, &quot;start_cfi&quot;: &quot;/2/4/2/2[chapter_458]/4/2/1:0&quot;, &quot;style&quot;: {&quot;kind&quot;: &quot;color&quot;, &quot;type&quot;: &quot;builtin&quot;, &quot;which&quot;: &quot;yellow&quot;}, &quot;timestamp&quot;: &quot;2024-03-11T11:56:52.891Z&quot;, &quot;toc_family_titles&quot;: [&quot;Chapter 1 - Down the Rabbit Hole&quot;], &quot;type&quot;: &quot;highlight&quot;, &quot;uuid&quot;: &quot;KFGNXVB2Heb53ghsAjVqvQ&quot;}}"/>
+ <meta name="calibre:annotation" content="{&quot;format&quot;: &quot;EPUB&quot;, &quot;user_type&quot;: &quot;local&quot;, &quot;user&quot;: &quot;viewer&quot;, &quot;annotation&quot;: {&quot;end_cfi&quot;: &quot;/2/4/2/2/6/1:106&quot;, &quot;highlighted_text&quot;: &quot;Lewis Carroll&quot;, &quot;spine_index&quot;: 2, &quot;spine_name&quot;: &quot;OPS/about.xml&quot;, &quot;start_cfi&quot;: &quot;/2/4/2/2/6/1:93&quot;, &quot;style&quot;: {&quot;kind&quot;: &quot;color&quot;, &quot;type&quot;: &quot;builtin&quot;, &quot;which&quot;: &quot;yellow&quot;}, &quot;timestamp&quot;: &quot;2024-03-11T11:55:32.734Z&quot;, &quot;toc_family_titles&quot;: [&quot;About&quot;], &quot;type&quot;: &quot;highlight&quot;, &quot;uuid&quot;: &quot;iuGTy-WIXWDinBuszppGwA&quot;}}"/>
+ <meta name="calibre:annotation" content="{&quot;format&quot;: &quot;EPUB&quot;, &quot;user_type&quot;: &quot;web&quot;, &quot;user&quot;: &quot;*&quot;, &quot;annotation&quot;: {&quot;type&quot;: &quot;highlight&quot;, &quot;timestamp&quot;: &quot;2024-03-11T16:24:14.624Z&quot;, &quot;uuid&quot;: &quot;1ZUnS8Bf4uZGH0hS9JOKGQ&quot;, &quot;highlighted_text&quot;: &quot;About Carroll&quot;, &quot;start_cfi&quot;: &quot;/2/4/2/2/2/1:0&quot;, &quot;end_cfi&quot;: &quot;/2/4/2/2/2/1:13&quot;, &quot;style&quot;: {&quot;type&quot;: &quot;builtin&quot;, &quot;kind&quot;: &quot;color&quot;, &quot;which&quot;: &quot;yellow&quot;}, &quot;spine_name&quot;: &quot;OPS/about.xml&quot;, &quot;spine_index&quot;: 2, &quot;notes&quot;: &quot;About note&quot;, &quot;toc_family_titles&quot;: [&quot;About&quot;]}}"/>
+ </metadata>
+ <guide>
+ <reference type="cover" title="Cover" href="cover.jpg"/>
+ </guide>
+</package>
diff --git a/vendor/mikespub/php-epub-meta/test/data/nav-non-text_img_title.epub b/vendor/mikespub/php-epub-meta/test/data/nav-non-text_img_title.epub
new file mode 100644
index 000000000..0670367e3
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/nav-non-text_img_title.epub
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/test/data/test.epub b/vendor/mikespub/php-epub-meta/test/data/test.epub
new file mode 100644
index 000000000..85d60aece
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/test.epub
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/test/data/test.jpg b/vendor/mikespub/php-epub-meta/test/data/test.jpg
new file mode 100644
index 000000000..4ca4a685c
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/data/test.jpg
Binary files differ
diff --git a/vendor/mikespub/php-epub-meta/test/epubTest.php b/vendor/mikespub/php-epub-meta/test/epubTest.php
new file mode 100644
index 000000000..5056fc260
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/epubTest.php
@@ -0,0 +1,807 @@
+<?php
+
+use PHPUnit\Framework\TestCase;
+use SebLucas\EPubMeta\Contents\NavPoint as TocNavPoint;
+use SebLucas\EPubMeta\EPub;
+use SebLucas\EPubMeta\Data\Item as DataItem;
+use SebLucas\EPubMeta\Tools\ZipEdit;
+
+/**
+ * Test for EPUB library
+ *
+ * Source: https://github.com/splitbrain/php-epub-meta
+ * @author Andreas Gohr <andi@splitbrain.org> © 2012
+ * @author Simon Schrape <simon@epubli.com> © 2015
+ */
+class EPubTest extends TestCase
+{
+ public const TEST_EPUB = __DIR__ . '/data/test.epub';
+ public const TEST_EPUB_COPY = __DIR__ . '/data/test.copy.epub';
+ public const TEST_EPUB_COVER = __DIR__ . '/data/test.cover.epub';
+ public const TEST_IMAGE = __DIR__ . '/data/test.jpg';
+ public const EMPTY_ZIP = __DIR__ . '/data/empty.zip';
+ public const BROKEN_ZIP = __DIR__ . '/data/broken.zip';
+ public const MARKUP_XML_1 = __DIR__ . '/data/markup.1.xml';
+ public const MARKUP_XML_2 = __DIR__ . '/data/markup.2.xml';
+ public const MARKUP_XML_3 = __DIR__ . '/data/markup.3.xml';
+ public const MARKUP_XML_4 = __DIR__ . '/data/markup.4.xml';
+ public const MARKUP_XML_5 = __DIR__ . '/data/markup.5.xml';
+
+ protected EPub $epub;
+
+ protected function setUp(): void
+ {
+ // sometime I might have accidentally broken the test file
+ if (filesize(static::TEST_EPUB) != 768780) {
+ die('test.epub has wrong size, make sure it\'s unmodified');
+ }
+
+ // we work on a copy to test saving
+ if (!copy(static::TEST_EPUB, static::TEST_EPUB_COPY)) {
+ die('failed to create copy of the test book');
+ }
+
+ // @see https://github.com/sebastianbergmann/phpunit/issues/5062#issuecomment-1416362657
+ set_error_handler(
+ static function (int $errno, string $errstr) {
+ throw new \Exception($errstr, $errno);
+ },
+ E_ALL
+ );
+
+ $this->epub = new Epub(static::TEST_EPUB_COPY);
+ }
+
+ protected function tearDown(): void
+ {
+ restore_error_handler();
+
+ unlink(static::TEST_EPUB_COPY);
+ }
+
+ public function testGetZipEntries(): void
+ {
+ $entries = $this->epub->getZipEntries();
+ $this->assertCount(49, $entries);
+ $this->assertArrayHasKey(EPub::METADATA_FILE, $entries);
+ $this->assertEquals(250, $entries[EPub::METADATA_FILE]['size']);
+
+ $count = $this->epub->getImageCount();
+ $this->assertEquals(3, $count);
+
+ $coverpath = $this->epub->getCoverPath();
+ $this->assertEquals('images/cover.png', $coverpath);
+
+ $size = $this->epub->getComponentSize($coverpath);
+ $this->assertEquals(657911, $size);
+ }
+
+ public function testLoadNonZip(): void
+ {
+ //$this->expectException(Exception::class);
+ //$this->expectExceptionMessage('Failed to read EPUB file. Not a zip archive.');
+ //$this->expectExceptionMessage('Failed to read epub file');
+ $this->expectException(ValueError::class);
+ $this->expectExceptionMessage('Invalid or uninitialized Zip object');
+ new Epub(static::TEST_IMAGE);
+ }
+
+ public function testLoadBrokenZip(): void
+ {
+ //$this->expectException(Exception::class);
+ //$this->expectExceptionMessage('Failed to read EPUB file. Zip archive inconsistent.');
+ //$this->expectExceptionMessage('Unable to find metadata.xml');
+ $this->expectException(ValueError::class);
+ $this->expectExceptionMessage('Invalid or uninitialized Zip object');
+ new Epub(static::BROKEN_ZIP);
+ }
+
+ public function testLoadMissingFile(): void
+ {
+ $this->expectException(Exception::class);
+ //$this->expectExceptionMessage('Failed to read EPUB file. No such file.');
+ $this->expectExceptionMessage('Epub file does not exist!');
+ new Epub('/a/file/that/is/not_there.epub');
+ }
+
+ /**
+ * We cannot expect a more specific exception message. ZipArchive::open returns 28
+ * which is not known as an error code.
+ */
+ public function testLoadDirectory(): void
+ {
+ $this->expectException(Exception::class);
+ //$this->expectExceptionMessage('Failed to read EPUB file.');
+ $this->expectExceptionMessage('Epub file does not exist!');
+ new Epub(__DIR__);
+ }
+
+ public function testLoadEmptyZip(): void
+ {
+ $this->expectException(Exception::class);
+ //$this->expectExceptionMessage('Failed to read from EPUB container: META-INF/container.xml');
+ //$this->expectExceptionMessage('Failed to read epub file');
+ $this->expectExceptionMessage('Unable to find ' . EPub::METADATA_FILE);
+ new Epub(static::EMPTY_ZIP);
+ }
+
+ public function testFilename(): void
+ {
+ $this->assertEquals(static::TEST_EPUB_COPY, $this->epub->file());
+ }
+
+ public function testAuthors(): void
+ {
+ // read curent value
+ $this->assertEquals(['Shakespeare, William' => 'William Shakespeare'], $this->epub->getAuthors());
+
+ // remove value with string
+ $this->epub->setAuthors('');
+ $this->assertEquals([], $this->epub->getAuthors());
+
+ // set single value by String
+ $this->epub->setAuthors('John Doe');
+ $this->assertEquals(['John Doe' => 'John Doe'], $this->epub->getAuthors());
+
+ // set single value by indexed array
+ $this->epub->setAuthors(['John Doe']);
+ $this->assertEquals(['John Doe' => 'John Doe'], $this->epub->getAuthors());
+
+ // remove value with array
+ $this->epub->setAuthors([]);
+ $this->assertEquals([], $this->epub->getAuthors());
+
+ // set single value by associative array
+ $this->epub->setAuthors(['Doe, John' => 'John Doe']);
+ $this->assertEquals(['Doe, John' => 'John Doe'], $this->epub->getAuthors());
+
+ // set multi value by string
+ $this->epub->setAuthors('John Doe, Jane Smith');
+ $this->assertEquals(['John Doe' => 'John Doe', 'Jane Smith' => 'Jane Smith'], $this->epub->getAuthors());
+
+ // set multi value by indexed array
+ $this->epub->setAuthors(['John Doe', 'Jane Smith']);
+ $this->assertEquals(['John Doe' => 'John Doe', 'Jane Smith' => 'Jane Smith'], $this->epub->getAuthors());
+
+ // set multi value by associative array
+ $this->epub->setAuthors(['Doe, John' => 'John Doe', 'Smith, Jane' => 'Jane Smith']);
+ $this->assertEquals(['Doe, John' => 'John Doe', 'Smith, Jane' => 'Jane Smith'], $this->epub->getAuthors());
+
+ // check escaping
+ $this->epub->setAuthors(['Doe, John&nbsp;' => 'John Doe&nbsp;']);
+ $this->assertEquals(['Doe, John&nbsp;' => 'John Doe&nbsp;'], $this->epub->getAuthors());
+ }
+
+ public function testTitle(): void
+ {
+ // get current value
+ $this->assertEquals('Romeo and Juliet', $this->epub->getTitle());
+
+ // set new value
+ $this->epub->setTitle('Foo Bar');
+ $this->assertEquals('Foo Bar', $this->epub->getTitle());
+
+ // delete current value
+ $this->epub->setTitle('');
+ $this->assertEquals('', $this->epub->getTitle());
+
+ // check escaping
+ $this->epub->setTitle('Foo&nbsp;Bar');
+ $this->assertEquals('Foo&nbsp;Bar', $this->epub->getTitle());
+ }
+
+ public function testLanguage(): void
+ {
+ // get current value
+ $this->assertEquals('en', $this->epub->getLanguage());
+
+ // set new value
+ $this->epub->setLanguage('Foo Bar');
+ $this->assertEquals('Foo Bar', $this->epub->getLanguage());
+
+ // delete current value
+ $this->epub->setLanguage('');
+ $this->assertEquals('', $this->epub->getLanguage());
+
+ // check escaping
+ $this->epub->setLanguage('Foo&nbsp;Bar');
+ $this->assertEquals('Foo&nbsp;Bar', $this->epub->getLanguage());
+ }
+
+ public function testPublisher(): void
+ {
+ // get current value
+ $this->assertEquals('Feedbooks', $this->epub->getPublisher());
+
+ // set new value
+ $this->epub->setPublisher('Foo Bar');
+ $this->assertEquals('Foo Bar', $this->epub->getPublisher());
+
+ // delete current value
+ $this->epub->setPublisher('');
+ $this->assertEquals('', $this->epub->getPublisher());
+
+ // check escaping
+ $this->epub->setPublisher('Foo&nbsp;Bar');
+ $this->assertEquals('Foo&nbsp;Bar', $this->epub->getPublisher());
+ }
+
+ public function testCopyright(): void
+ {
+ // get current value
+ $this->assertEquals('', $this->epub->getCopyright());
+
+ // set new value
+ $this->epub->setCopyright('Foo Bar');
+ $this->assertEquals('Foo Bar', $this->epub->getCopyright());
+
+ // delete current value
+ $this->epub->setCopyright('');
+ $this->assertEquals('', $this->epub->getCopyright());
+
+ // check escaping
+ $this->epub->setCopyright('Foo&nbsp;Bar');
+ $this->assertEquals('Foo&nbsp;Bar', $this->epub->getCopyright());
+ }
+
+ public function testDescription(): void
+ {
+ // get current value
+ $this->assertStringStartsWith('Romeo and Juliet is a tragic play written', $this->epub->getDescription());
+
+ // set new value
+ $this->epub->setDescription('Foo Bar');
+ $this->assertEquals('Foo Bar', $this->epub->getDescription());
+
+ // delete current value
+ $this->epub->setDescription('');
+ $this->assertEquals('', $this->epub->getDescription());
+
+ // check escaping
+ $this->epub->setDescription('Foo&nbsp;Bar');
+ $this->assertEquals('Foo&nbsp;Bar', $this->epub->getDescription());
+ }
+
+ public function testUniqueIdentifier(): void
+ {
+ // get current value
+ $this->assertEquals('urn:uuid:7d38d098-4234-11e1-97b6-001cc0a62c0b', $this->epub->getUniqueIdentifier());
+
+ // set new value
+ $this->epub->setUniqueIdentifier('134htb34tp089h1b');
+ $this->assertEquals('134htb34tp089h1b', $this->epub->getUniqueIdentifier());
+ // this should have affected the same node that is found when looking for UUID/URN scheme
+ $this->assertEquals('134htb34tp089h1b', $this->epub->getUuid());
+ }
+
+ public function testUuid(): void
+ {
+ // get current value
+ $this->assertEquals('urn:uuid:7d38d098-4234-11e1-97b6-001cc0a62c0b', $this->epub->getUuid());
+
+ // set new value
+ $this->epub->setUuid('Foo Bar');
+ $this->assertEquals('Foo Bar', $this->epub->getUuid());
+
+ // delete current value
+ $this->epub->setUuid('');
+ $this->assertEquals('', $this->epub->getUuid());
+
+ // check escaping
+ $this->epub->setUuid('Foo&nbsp;Bar');
+ $this->assertEquals('Foo&nbsp;Bar', $this->epub->getUuid());
+ }
+
+ public function testUri(): void
+ {
+ // get current value
+ $this->assertEquals('http://www.feedbooks.com/book/2936', $this->epub->getUri());
+
+ // set new value
+ $this->epub->setUri('Foo Bar');
+ $this->assertEquals('Foo Bar', $this->epub->getUri());
+
+ // delete current value
+ $this->epub->setUri('');
+ $this->assertEquals('', $this->epub->getUri());
+
+ // check escaping
+ $this->epub->setUri('Foo&nbsp;Bar');
+ $this->assertEquals('Foo&nbsp;Bar', $this->epub->getUri());
+ }
+
+ public function testIsbn(): void
+ {
+ // get current value
+ $this->assertEquals('', $this->epub->getIsbn());
+
+ // set new value
+ $this->epub->setIsbn('Foo Bar');
+ $this->assertEquals('Foo Bar', $this->epub->getIsbn());
+
+ // delete current value
+ $this->epub->setIsbn('');
+ $this->assertEquals('', $this->epub->getIsbn());
+
+ // check escaping
+ $this->epub->setIsbn('Foo&nbsp;Bar');
+ $this->assertEquals('Foo&nbsp;Bar', $this->epub->getIsbn());
+ }
+
+ public function testSubject(): void
+ {
+ // get current values
+ $this->assertEquals(['Fiction', 'Drama', 'Romance'], $this->epub->getSubjects());
+
+ // delete current values with String
+ $this->epub->setSubjects('');
+ $this->assertEquals([], $this->epub->getSubjects());
+
+ // set new values with String
+ $this->epub->setSubjects('Fiction, Drama, Romance');
+ $this->assertEquals(['Fiction', 'Drama', 'Romance'], $this->epub->getSubjects());
+
+ // delete current values with Array
+ $this->epub->setSubjects([]);
+ $this->assertEquals([], $this->epub->getSubjects());
+
+ // set new values with array
+ $this->epub->setSubjects(['Fiction', 'Drama', 'Romance']);
+ $this->assertEquals(['Fiction', 'Drama', 'Romance'], $this->epub->getSubjects());
+
+ // check escaping
+ $this->epub->setSubjects(['Fiction', 'Drama&nbsp;', 'Romance']);
+ $this->assertEquals(['Fiction', 'Drama&nbsp;', 'Romance'], $this->epub->getSubjects());
+ }
+
+ public function testCover(): void
+ {
+ // we work on a copy to test saving
+ $this->assertTrue(copy(static::TEST_EPUB, static::TEST_EPUB_COVER));
+
+ // use the ZipEdit class here
+ //$epub = new EPub(static::TEST_EPUB_COVER, ZipEdit::class);
+ $epub = new EPub(static::TEST_EPUB_COVER);
+
+ // read current cover
+ $cover = $epub->getCover();
+ $this->assertEquals(657911, strlen($cover));
+
+ // change cover and save
+ $epub->setCover(static::TEST_IMAGE, 'image/jpeg');
+ //$epub->save();
+
+ // open epub again
+ //$epub = new EPub(static::TEST_EPUB_COVER);
+
+ // read recently changed cover
+ $cover = $epub->getCover();
+ $this->assertEquals(filesize(static::TEST_IMAGE), strlen($cover));
+
+ // delete cover
+ $epub->clearCover();
+ $cover = $epub->getCover();
+ $this->assertNull($cover);
+
+ $epub->close();
+
+ unlink(static::TEST_EPUB_COVER);
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function testTitlePage()
+ {
+ // we work on a copy to test saving
+ $this->assertTrue(copy(static::TEST_EPUB, static::TEST_EPUB_COVER));
+
+ // use the ZipEdit class here
+ //$epub = new EPub(static::TEST_EPUB_COVER, ZipEdit::class);
+ $epub = new EPub(static::TEST_EPUB_COVER);
+
+ // add title page and save
+ $epub->addCoverImageTitlePage();
+ //$epub->save();
+
+ // open epub again
+ //$epub = new EPub(static::TEST_EPUB_COVER);
+
+ // read recently added title page
+ $spine = $epub->getSpine();
+ $titlePage = $spine->first();
+ $this->assertEquals(EPub::TITLE_PAGE_ID . '.xhtml', $titlePage->getHref());
+ $this->assertEquals(EPub::TITLE_PAGE_ID, $titlePage->getId());
+ $this->assertEquals('application/xhtml+xml', (string) $titlePage->getMediaType());
+
+ // We expect an empty string since there is only an image but no text on that page.
+ $this->assertEmpty(trim($titlePage->getContents()));
+
+ unlink(static::TEST_EPUB_COVER);
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function testCalibreAnnotations()
+ {
+ $epub = new Epub(static::TEST_EPUB);
+ // use metadata from .opf file for tests here - see Alice from mikespub/seblucas-cops
+ $data = file_get_contents(__DIR__ . '/data/metadata.opf');
+ $annotations = $epub->getCalibreAnnotations($data);
+ $this->assertCount(5, $annotations);
+ $expected = [
+ 'format' => 'EPUB',
+ 'user_type' => 'local',
+ 'user' => 'viewer',
+ 'annotation' => [
+ 'title' => 'About #1',
+ 'pos_type' => 'epubcfi',
+ 'pos' => 'epubcfi(/6/2/4/2/6/2:38)',
+ 'timestamp' => '2024-03-11T11:54:35.128396+00:00',
+ 'type' => 'bookmark',
+ ],
+ ];
+ $this->assertEquals($expected, $annotations[0]);
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function testCalibreBookmarks()
+ {
+ $epub = new Epub(static::TEST_EPUB);
+ // use calibre_bookmarks.txt for tests here - see Alice from mikespub/seblucas-cops
+ $data = file_get_contents(__DIR__ . '/data/calibre_bookmarks.txt');
+ $bookmarks = $epub->getCalibreBookmarks($data);
+ $this->assertCount(5, $bookmarks);
+ $expected = [
+ 'title' => 'About #1',
+ 'pos_type' => 'epubcfi',
+ 'pos' => 'epubcfi(/6/2/4/2/6/2:38)',
+ 'timestamp' => '2024-03-11T11:54:35.128396+00:00',
+ 'type' => 'bookmark',
+ ];
+ $this->assertEquals($expected, $bookmarks[0]);
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function testManifest()
+ {
+ $manifest = $this->epub->getManifest();
+ $this->assertCount(41, $manifest);
+
+ $this->assertEquals('cover', $manifest->first()->getId());
+ $this->assertEquals(DataItem::XHTML, $manifest->current()->getMediaType());
+ $manifest->next();
+ $this->assertEquals('title.xml', $manifest->current()->getHref());
+ $this->assertEquals('ncx', $manifest->last()->getId());
+
+ $this->assertSame($manifest['cover'], $manifest->first());
+ $this->assertSame($manifest['ncx'], $manifest->last());
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function testSpine()
+ {
+ $spine = $this->epub->getSpine();
+ $this->assertCount(31, $spine);
+
+ $this->assertEquals('cover', $spine->first()->getId());
+ $this->assertEquals(DataItem::XHTML, $spine->current()->getMediaType());
+ $spine->next();
+ $this->assertEquals('title.xml', $spine->current()->getHref());
+ $this->assertEquals('feedbooks', $spine->last()->getId());
+
+ $this->assertEquals('fb.ncx', $spine->getTocItem()->getHref());
+
+ $this->assertSame($spine[0], $spine->first());
+ $this->assertSame($spine[30], $spine->last());
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function testToc()
+ {
+ $this->assertEquals(2, $this->epub->getEpubVersion());
+
+ $toc = $this->epub->getToc();
+ $this->assertEquals('Romeo and Juliet', $toc->getDocTitle());
+ $this->assertEquals('Shakespeare, William', $toc->getDocAuthor());
+ $navMap = $toc->getNavMap();
+ $this->assertEquals(8, $navMap->count());
+
+ $navPoint = $navMap->first();
+ /** @var TocNavPoint $navPoint */
+ $this->assertEquals('level1-titlepage', $navPoint->getId());
+ $this->assertEquals('titlepage', $navPoint->getClass());
+ $this->assertEquals('1', $navPoint->getPlayOrder());
+ $this->assertEquals('Title', $navPoint->getNavLabel());
+ $this->assertEquals('title.xml', $navPoint->getContentSource());
+ $this->assertCount(0, $navPoint->getChildren());
+
+ $navMap->next();
+ $navMap->next();
+ $navPoint = $navMap->current();
+ /** @var TocNavPoint $navPoint */
+ $this->assertEquals('sec77303', $navPoint->getId());
+ $this->assertEquals('section', $navPoint->getClass());
+ $this->assertEquals('3', $navPoint->getPlayOrder());
+ $this->assertEquals('Act I', $navPoint->getNavLabel());
+ $this->assertEquals('main0.xml', $navPoint->getContentSource());
+ $this->assertCount(6, $navPoint->getChildren());
+ $this->assertEquals('Prologue', $navPoint->getChildren()->first()->getNavLabel());
+ $this->assertEquals('SCENE V. A hall in Capulet\'s house.', $navPoint->getChildren()->last()->getNavLabel());
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function testNav()
+ {
+ $test_epub3 = __DIR__ . '/data/nav-non-text_img_title.epub';
+ $test_epub3_copy = __DIR__ . '/data/nav-non-text_img_title.copy.epub';
+
+ // sometime I might have accidentally broken the test file
+ $this->assertEquals(239564, filesize($test_epub3));
+
+ // we work on a copy to test saving
+ $this->assertTrue(copy($test_epub3, $test_epub3_copy));
+
+ $epub = new EPub($test_epub3_copy);
+ $this->assertEquals(3, $epub->getEpubVersion());
+
+ $toc = $epub->getNav();
+ $this->assertEquals('nav-non-text_img_title', $toc->getDocTitle());
+ $this->assertEquals('Ivan Herman', $toc->getDocAuthor());
+ $navMap = $toc->getNavMap();
+ $this->assertEquals(2, $navMap->count());
+
+ $navPoint = $navMap->first();
+ /** @var TocNavPoint $navPoint */
+ $this->assertEquals('', $navPoint->getId());
+ $this->assertEquals('h1', $navPoint->getClass());
+ $this->assertEquals('1', $navPoint->getPlayOrder());
+ $this->assertEquals('Start page', $navPoint->getNavLabel());
+ $this->assertEquals('content_001.xhtml', $navPoint->getContentSource());
+ $this->assertCount(0, $navPoint->getChildren());
+
+ $navMap->next();
+ $navPoint = $navMap->current();
+ /** @var TocNavPoint $navPoint */
+ $this->assertEquals('', $navPoint->getId());
+ $this->assertEquals('h1', $navPoint->getClass());
+ $this->assertEquals('2', $navPoint->getPlayOrder());
+ $this->assertEquals('Description of the Abbey of Sénanque', $navPoint->getNavLabel());
+ $this->assertEquals('senanque.xhtml', $navPoint->getContentSource());
+ $this->assertCount(0, $navPoint->getChildren());
+ //$this->assertEquals('Prologue', $navPoint->getChildren()->first()->getNavLabel());
+ //$this->assertEquals('SCENE V. A hall in Capulet\'s house.', $navPoint->getChildren()->last()->getNavLabel());
+
+ unlink($test_epub3_copy);
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function testNavTree()
+ {
+ $test_epub3 = __DIR__ . '/data/eng3.epub';
+ $test_epub3_copy = __DIR__ . '/data/eng3.copy.epub';
+
+ // sometime I might have accidentally broken the test file
+ $this->assertEquals(53216, filesize($test_epub3));
+
+ // we work on a copy to test saving
+ $this->assertTrue(copy($test_epub3, $test_epub3_copy));
+
+ $epub = new EPub($test_epub3_copy);
+
+ $toc = $epub->getNav();
+ $this->assertEquals('Calibre Quick Start Guide', $toc->getDocTitle());
+ $this->assertEquals('John Schember', $toc->getDocAuthor());
+ $navMap = $toc->getNavMap();
+ $this->assertEquals(7, $navMap->count());
+ $this->assertCount(1, $navMap->findNavPointsForFile('text/introduction.xhtml'));
+ $this->assertCount(0, $navMap->findNavPointsForFile('oops/are_we_lost?.xhtml'));
+
+ $navPoint = $navMap->first();
+ /** @var TocNavPoint $navPoint */
+ $this->assertEquals('', $navPoint->getId());
+ $this->assertEquals('h1', $navPoint->getClass());
+ $this->assertEquals('1', $navPoint->getPlayOrder());
+ $this->assertEquals('Calibre Quick Start Guide', $navPoint->getNavLabel());
+ $this->assertEquals('text/internal_titlepage.xhtml', $navPoint->getContentSource());
+ $this->assertCount(0, $navPoint->getChildren());
+
+ $navMap->seek(5);
+ $navPoint = $navMap->current();
+ /** @var TocNavPoint $navPoint */
+ $this->assertEquals('', $navPoint->getId());
+ $this->assertEquals('h1', $navPoint->getClass());
+ $this->assertEquals(6, $navPoint->getPlayOrder());
+ $this->assertEquals('Common Tasks', $navPoint->getNavLabel());
+ $this->assertEquals('text/common_tasks.xhtml', $navPoint->getContentSource());
+ $this->assertCount(6, $navPoint->getChildren());
+ $this->assertEquals('Task 1: Organizing', $navPoint->getChildren()->first()->getNavLabel());
+ $navPoint->getChildren()->next();
+ $childPoint = $navPoint->getChildren()->current();
+ $this->assertEquals('Task 2: Conversion', $childPoint->getNavLabel());
+ $this->assertCount(7, $childPoint->getChildren());
+ $this->assertEquals('Task 6: The e-book viewer', $navPoint->getChildren()->last()->getNavLabel());
+
+ unlink($test_epub3_copy);
+ }
+
+ /**
+ * @dataProvider provideContentsTestParameters
+ * @param string $referenceStart The expected start of the extracted contents.
+ * @param string $referenceEnd The expected end of the extracted contents.
+ * @param int $referenceSize The expected size of the extracted contents.
+ * @param bool $keepMarkup Whether to extract contents with or without HTML markup.
+ * @param float $fraction
+ * @throws Exception
+ * @return void
+ */
+ public function testContents(
+ $referenceStart,
+ $referenceEnd,
+ $referenceSize,
+ $keepMarkup,
+ $fraction
+ ) {
+ $contents = trim($this->epub->getContents($keepMarkup, $fraction));
+ $this->assertStringStartsWith($referenceStart, substr($contents, 0, 100));
+ $this->assertStringEndsWith($referenceEnd, substr($contents, -100));
+ $this->assertEquals($referenceSize, strlen($contents));
+ }
+
+ /**
+ * Summary of provideContentsTestParameters
+ * @return array<mixed>
+ */
+ public static function provideContentsTestParameters()
+ {
+ return [
+ ["Romeo and Juliet\n\nWilliam Shakespeare", "www.feedbooks.com\n\n Food for the mind", 152879, false, 1],
+ ["Romeo and Juliet\n\nWilliam Shakespeare", "seek happy nights to happy days.\n\nExeunt", 24936, false, .2],
+ ["Romeo and Juliet\n\nWilliam Shakespeare", "miss, our toil shall strive to mend.", 3810, false, .1],
+ ];
+ }
+
+ /**
+ * @dataProvider provideItemContentsTestParameters
+ * @param string $referenceStart The expected start of the extracted contents.
+ * @param string $referenceEnd The expected end of the extracted contents.
+ * @param string $spineIndex The spine index of the item to extract contents from.
+ * @param string $fragmentBegin The anchor name (ID) where to start extraction.
+ * @param string $fragmentEnd The anchor name (ID) where to end extraction.
+ * @throws Exception
+ * @return void
+ */
+ public function testItemContents(
+ $referenceStart,
+ $referenceEnd,
+ $spineIndex,
+ $fragmentBegin = null,
+ $fragmentEnd = null
+ ) {
+ $spine = $this->epub->getSpine();
+ $contents = trim($spine[$spineIndex]->getContents($fragmentBegin, $fragmentEnd));
+ $this->assertStringStartsWith($referenceStart, $contents);
+ $this->assertStringEndsWith($referenceEnd, $contents);
+ }
+
+ /**
+ * Summary of provideItemContentsTestParameters
+ * @return array<mixed>
+ */
+ public static function provideItemContentsTestParameters()
+ {
+ return [
+ ['Act I', 'our toil shall strive to mend.', 3],
+ ['SCENE I. Verona. A public place.', "I'll pay that doctrine, or else die in debt.\n\nExeunt", 4],
+ ['Act III', 'Act III', 16, 'section_77331', 'section_77332'],
+ ['Act III', 'Act III', 16, null, 'section_77332'],
+ ['SCENE I. A public place.', "pardoning those that kill.\n\nExeunt", 16, 'section_77332'],
+ ];
+ }
+
+ public function testItemContentsStartFragmentException(): void
+ {
+ $this->expectException(Exception::class);
+ $this->expectExceptionMessage('Begin of fragment not found:');
+ $spine = $this->epub->getSpine();
+ $spine[3]->getContents('NonExistingElement');
+ }
+
+ public function testItemContentsEndFragmentException(): void
+ {
+ $this->expectException(Exception::class);
+ $this->expectExceptionMessage('End of fragment not found:');
+ $spine = $this->epub->getSpine();
+ $spine[3]->getContents(null, 'NonExistingElement');
+ }
+
+ /**
+ * @dataProvider provideItemContentsMarkupTestParameters
+ * @param string $referenceFile
+ * @param string $spineIndex
+ * @param string $fragmentBegin
+ * @param string $fragmentEnd
+ * @throws Exception
+ * @return void
+ */
+ public function testItemContentsMarkup($referenceFile, $spineIndex, $fragmentBegin = null, $fragmentEnd = null)
+ {
+ $spine = $this->epub->getSpine();
+ $contents = $spine[$spineIndex]->getContents($fragmentBegin, $fragmentEnd, true);
+ $contents = preg_replace('/\s+/m', ' ', $contents);
+ $extracted = new DOMDocument();
+ $extracted->loadXML($contents);
+ $extstring = $extracted->saveXML($extracted->documentElement);
+ $extstring = preg_replace('/\s*([<>])\s*/m', '$1', $extstring);
+ $reference = new DOMDocument();
+ $contents = file_get_contents($referenceFile);
+ $contents = preg_replace('/\s+/m', ' ', $contents);
+ $reference->loadXML($contents);
+ $refstring = $reference->saveXML($reference->documentElement);
+ $refstring = preg_replace('/\s*([<>])\s*/m', '$1', $refstring);
+ $this->assertEquals($refstring, $extstring);
+ //$this->assertEqualXMLStructure($reference->documentElement, $extracted->documentElement);
+ }
+
+ /**
+ * Summary of provideItemContentsMarkupTestParameters
+ * @return array<mixed>
+ */
+ public static function provideItemContentsMarkupTestParameters()
+ {
+ return [
+ [static::MARKUP_XML_1, 3],
+ [static::MARKUP_XML_2, 4],
+ [static::MARKUP_XML_3, 16, 'section_77331', 'section_77332'],
+ [static::MARKUP_XML_4, 16, null, 'section_77332'],
+ [static::MARKUP_XML_5, 16, 'section_77332'],
+ ];
+ }
+
+ /**
+ * @throws Exception
+ * @return void
+ */
+ public function testItemDataSize()
+ {
+ $item = $this->epub->getSpine()[0];
+ $size = $item->getSize();
+ $data = $item->getData();
+
+ $this->assertEquals(strlen($data), $size);
+ }
+
+ /**
+ * Summary of testZipEdit
+ * @return void
+ */
+ public function testZipEdit()
+ {
+ ZipEdit::copyTest(static::TEST_EPUB_COPY, static::TEST_EPUB_COVER);
+ $epub = new EPub(static::TEST_EPUB_COVER);
+ $oldManifest = $this->epub->getManifest();
+ $newManifest = $epub->getManifest();
+ $this->assertEquals($oldManifest, $newManifest);
+ }
+}
diff --git a/vendor/mikespub/php-epub-meta/test/monocleTest.php b/vendor/mikespub/php-epub-meta/test/monocleTest.php
new file mode 100644
index 000000000..20cc5a6c5
--- /dev/null
+++ b/vendor/mikespub/php-epub-meta/test/monocleTest.php
@@ -0,0 +1,159 @@
+<?php
+
+use PHPUnit\Framework\TestCase;
+use SebLucas\EPubMeta\EPub;
+
+/**
+ * Test for EPUB methods used by Monocle in COPS
+ *
+ * Source: https://github.com/mikespub-org/seblucas
+ */
+class MonocleTest extends TestCase
+{
+ public const TEST_EPUB = __DIR__ . '/data/eng.epub';
+ public const TEST_EPUB_COPY = __DIR__ . '/data/eng.copy.epub';
+ public const TEST_CONTENTS = __DIR__ . '/data/eng.contents.json';
+ public const TEST_COMPONENTS = __DIR__ . '/data/eng.components.json';
+ public const TEST_EPUB3 = __DIR__ . '/data/eng3.epub';
+
+ private static EPub $book;
+
+ public static function setUpBeforeClass(): void
+ {
+ // sometime I might have accidentally broken the test file
+ if (filesize(static::TEST_EPUB) != 22664) {
+ die('test.epub has wrong size, make sure it\'s unmodified');
+ }
+
+ // we work on a copy to test saving
+ if (!copy(static::TEST_EPUB, static::TEST_EPUB_COPY)) {
+ die('failed to create copy of the test book');
+ }
+
+ // @see https://github.com/sebastianbergmann/phpunit/issues/5062#issuecomment-1416362657
+ set_error_handler(
+ static function (int $errno, string $errstr) {
+ throw new \Exception($errstr, $errno);
+ },
+ E_ALL
+ );
+
+ self::$book = new Epub(static::TEST_EPUB_COPY);
+ self::$book->initSpineComponent();
+ }
+
+ public static function tearDownAfterClass(): void
+ {
+ restore_error_handler();
+
+ unlink(static::TEST_EPUB_COPY);
+ }
+
+ public function testComponents(): void
+ {
+ $data = self::$book->components();
+ $contents = file_get_contents(static::TEST_COMPONENTS);
+ $check = json_decode($contents, true);
+ $encoder = $this->provideEncodeReplace();
+ $check = str_replace($encoder[0], $encoder[1], $check);
+ $this->assertEquals($check, $data);
+ }
+
+ public function testContents(): void
+ {
+ $data = self::$book->contents();
+ $contents = file_get_contents(static::TEST_CONTENTS);
+ $check = json_decode($contents, true);
+ $encoder = $this->provideEncodeReplace();
+ foreach (array_keys($check) as $idx) {
+ $check[$idx] = $this->encodeItem($check[$idx], $encoder);
+ }
+ $this->assertEquals($check, $data);
+ }
+
+ /**
+ * Summary of testComponent
+ * @param string $component
+ * @return void
+ */
+ public function testComponent($component = 'text/titlepage.xhtml')
+ {
+ $data = self::$book->component($component);
+ $check = 641;
+ $this->assertEquals($check, strlen($data));
+ }
+
+ /**
+ * Summary of testGetComponentName
+ * @param string $component
+ * @param string $element
+ * @return void
+ */
+ public function testGetComponentName($component = 'text/titlepage.xhtml', $element = '../images/cover.jpg')
+ {
+ $data = self::$book->getComponentName($component, $element);
+ $check = 'images~SLASH~cover.jpg';
+ $this->assertEquals($check, $data);
+ }
+
+ /**
+ * Summary of testComponentContentType
+ * @param string $component
+ * @return void
+ */
+ public function testComponentContentType($component = 'text/titlepage.xhtml')
+ {
+ $data = self::$book->componentContentType($component);
+ $check = 'application/xhtml+xml';
+ $this->assertEquals($check, $data);
+ }
+
+ public function testContentsEpub3(): void
+ {
+ $epub = new EPub(__DIR__ . '/data/eng3.epub');
+ $epub->initSpineComponent();
+ $data = $epub->contents();
+ $contents = file_get_contents(static::TEST_CONTENTS);
+ $check = json_decode($contents, true);
+ $encoder = $this->provideEncodeReplace();
+ foreach (array_keys($check) as $idx) {
+ $check[$idx] = $this->encodeItem($check[$idx], $encoder);
+ }
+ $this->assertEquals($check, $data);
+ }
+
+ /**
+ * Summary of encodeItem
+ * @param array<mixed> $item
+ * @param array<mixed> $encoder
+ * @return array<mixed>
+ */
+ protected function encodeItem($item, $encoder)
+ {
+ $item['src'] = str_replace($encoder[0], $encoder[1], $item['src']);
+ if (!empty($item['children'])) {
+ foreach (array_keys($item['children']) as $idx) {
+ $item['children'][$idx] = $this->encodeItem($item['children'][$idx], $encoder);
+ }
+ }
+ return $item;
+ }
+
+ /**
+ * Summary of provideEncodeReplace
+ * @return array<mixed>
+ */
+ public function provideEncodeReplace()
+ {
+ return EPub::$encodeNameReplace;
+ }
+
+ /**
+ * Summary of provideDecodeReplace
+ * @return array<mixed>
+ */
+ public function provideDecodeReplace()
+ {
+ return EPub::$decodeNameReplace;
+ }
+}