mirror of
https://github.com/Yetangitu/owncloud-apps.git
synced 2025-10-02 14:49:17 +02:00
OC8 port, 'should be compatible' with OC7 - please test...
Reader: ported to appframework, new version of epub.js
This commit is contained in:
parent
ba221c1d61
commit
c4d1ace999
50 changed files with 653 additions and 6064 deletions
BIN
dist/files_opds-0.6.2.tar.gz
vendored
Normal file
BIN
dist/files_opds-0.6.2.tar.gz
vendored
Normal file
Binary file not shown.
BIN
dist/files_reader-0.6.0.tar.gz
vendored
Normal file
BIN
dist/files_reader-0.6.0.tar.gz
vendored
Normal file
Binary file not shown.
|
@ -2,9 +2,21 @@
|
|||
<info>
|
||||
<id>files_opds</id>
|
||||
<name>OPDS catalog</name>
|
||||
<description>Personal OPDS catalog</description>
|
||||
<description>
|
||||
The OPDS catalog app enables Owncloud users to publish a sub-tree of their personal filesystem as an OPDS feed. As of v0.3 OPDS catalog can extract all relevant metadata from EPUB documents. v0.5 introduced ISBN-based metadata retrieval, while Calibre-generated metadata.opf files are parsed since v0.6.
|
||||
|
||||
If the directory in which the file is found contains a valid metadata.opf file, this file is parsed and all relevant Dublin Core metadata is applied to all files in the directory. If a cover is specified in this file, and the relevant file is found in the directory, this cover is used as preview and thumbnail for all files in the directory. If the metadata is invalid (ie. one or more of title, author and language are not defined) the files themselves are parsed for metadata in the 'normal' way.
|
||||
|
||||
If an ISBN is found in either existing metadata or in the first 10 pages of the publication, metadata is retrieved from ISBNdb (key required, http://isbndb.com/account/logincreate, max. 500 queries/day) and Google Books (no key required).
|
||||
|
||||
Documents for which no metadata is found will appear with sparse entries for now: only title (as in 'filename'), file size, cover image (where available), modification time and content links are provided. The first visit to a new (or updated) directory will take a bit longer while OPDS catalog scans for metadata, subsequent visits will be faster due to the use of cached metadata.
|
||||
|
||||
The OPDS root feed links to a hierarchical navigation feed mirroring the directory structure as well as a 'personal bookshelf' containing links to all downloaded books (most recent download listed first). This 'personal bookshelf' will be empty (0 books) at first. Use the 'Browse catalog' link to download a book and it'll appear on the 'personal bookshelf'. Download another, and it will appear above the one you previously downloaded. This makes it possible to get at books you are in the process of reading from different devices, or to easily re-visit a book you downloaded earlier.
|
||||
|
||||
The feed is in compliance with the OPDS 1.1 specification according to the online OPDS validator (http://opds-validator.appspot.com/).
|
||||
</description>
|
||||
<licence>AGPL</licence>
|
||||
<version>0.6.1</version>
|
||||
<version>0.6.2</version>
|
||||
<author>Frank de Lange</author>
|
||||
<requiremin>7.0</requiremin>
|
||||
<shipped>true</shipped>
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<?php
|
||||
|
|
@ -10,7 +10,6 @@
|
|||
* later.
|
||||
*/
|
||||
|
||||
|
||||
$this->create('opds_catalog', '/')
|
||||
->actionInclude('files_opds/index.php');
|
||||
$this->create('opds_catalog_admin_settings', 'ajax/admin.php')
|
||||
|
|
55
files_opds/img/app.svg
Normal file
55
files_opds/img/app.svg
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
height="16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="app.svg">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="798"
|
||||
inkscape:window-height="1186"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.7984553"
|
||||
inkscape:cx="2.0136059"
|
||||
inkscape:cy="8.6779652"
|
||||
inkscape:window-x="800"
|
||||
inkscape:window-y="12"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 6.3605388,1.1781792 C 5.3432889,0.71018919 3.3384715,1.6144462 2.7626049,2.4105432 2.50603,2.7667642 2.5241688,3.0234762 2.5241688,3.1691342 l 0,7.7918788 7.5182352,4.088872 1.413809,-0.674729 0,-7.5883898 -7.7192505,-3.87362 c 0.4142344,-0.455662 1.3458772,-1.011314 2.0444073,-0.788162 l 6.8757582,3.214357 0,8.4535718 1.417397,-0.675926 0,-8.4532028 z"
|
||||
id="path2989"
|
||||
sodipodi:nodetypes="cccccccccccccc"
|
||||
style="fill:#ffffff" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
|
@ -58,7 +58,7 @@ $dirInfo = \OC\Files\Filesystem::getFileInfo($dir);
|
|||
/* If requested resource is a file, serve it, otherwise produce opds feed */
|
||||
switch ($dirInfo->getType()) {
|
||||
case 'file':
|
||||
if (isset($type)) {
|
||||
if ($type) {
|
||||
Feed::servePreview($dir,$type);
|
||||
} else {
|
||||
Feed::serveFile($dir,$id);
|
||||
|
|
|
@ -35,7 +35,6 @@ class Epub extends Provider {
|
|||
$cover = $epub->Cover();
|
||||
|
||||
if ($cover) {
|
||||
|
||||
$image = new \OC_Image();
|
||||
|
||||
$image->loadFromData($cover['data']);
|
||||
|
|
|
@ -1,5 +1,17 @@
|
|||
<?php
|
||||
//load the required files
|
||||
|
||||
$l = OC_L10N::get('files_reader');
|
||||
OCP\Util::addscript( 'files_reader', 'loader');
|
||||
/**
|
||||
* ownCloud - Files_Reader App
|
||||
*
|
||||
* @author Frank de Lange
|
||||
* @copyright 2015 Frank de Lange
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
*/
|
||||
|
||||
namespace OCA\Files_Reader\AppInfo;
|
||||
|
||||
use OCP\Util;
|
||||
|
||||
Util::addscript( 'files_reader', 'plugin');
|
||||
|
|
|
@ -2,10 +2,18 @@
|
|||
<info>
|
||||
<id>files_reader</id>
|
||||
<name>Reader (ebook reader)</name>
|
||||
<description>Online ePub file reader</description>
|
||||
<version>0.5.0</version>
|
||||
<description>
|
||||
Reader is an ebook reader based on a pure javascript epub renderer. It only works for books formatted according to the epub standard.
|
||||
|
||||
Using the futurepress epub.js renderer (https://github.com/futurepress/epub.js) it provides near-native looks, especially when used full-screen. Turn pages by pressing the left/right hand side of the screen/window or using the cursor keys (if you have those), use the sidebar to browse through chapters or bookmarks and add annotations.
|
||||
|
||||
Reader has a night mode (toggled by clicking or pressing the book title/author on top of the viewer) to read in the dark without waking up the neighbours. This is obviously most effective when used full-screen. The colours used for night mode are configurable in the Settings dialog.
|
||||
|
||||
Also in Settings you'll find the option to use ignore any internal formatting in the book by forcing a given font style and size.
|
||||
</description>
|
||||
<version>0.6.0</version>
|
||||
<licence>LGPL</licence>
|
||||
<author>Frank de Lange, (taken clues from Thomas Müller/files_pdfviewer, using slightly modified Futurepress/epub.js)</author>
|
||||
<author>Frank de Lange</author>
|
||||
<require>7.0</require>
|
||||
<shipped>false</shipped>
|
||||
<default_enable/>
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
* later.
|
||||
*/
|
||||
|
||||
$this->create('files_reader', '/')
|
||||
->actionInclude('files_reader/viewer.php');
|
||||
namespace OCA\Files_Reader\AppInfo;
|
||||
|
||||
return ['routes' => [
|
||||
['name' => 'display#showReader', 'url' => '/', 'verb' => 'GET'],
|
||||
]];
|
||||
|
||||
|
|
47
files_reader/controller/displaycontroller.php
Normal file
47
files_reader/controller/displaycontroller.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
/**
|
||||
* @author Frank de Lange
|
||||
* @copyright 2015 Frank de Lange
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later.
|
||||
* See the COPYING-README file.
|
||||
*/
|
||||
|
||||
namespace OCA\Files_Reader\Controller;
|
||||
|
||||
use OCP\AppFramework\Controller;
|
||||
use OCP\AppFramework\Http\TemplateResponse;
|
||||
use OCP\IRequest;
|
||||
use OCP\IURLGenerator;
|
||||
|
||||
class DisplayController extends Controller {
|
||||
|
||||
/** @var IURLGenerator */
|
||||
private $urlGenerator;
|
||||
|
||||
/**
|
||||
* @param string $AppName
|
||||
* @param IRequest $request
|
||||
* @param IURLGenerator $urlGenerator
|
||||
*/
|
||||
public function __construct($AppName, IRequest $request, IURLGenerator $urlGenerator) {
|
||||
parent::__construct($AppName, $request);
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @PublicPage
|
||||
* @NoCSRFRequired
|
||||
*
|
||||
* @return TemplateResponse
|
||||
*/
|
||||
public function showReader() {
|
||||
$params = [
|
||||
'urlGenerator' => $this->urlGenerator
|
||||
];
|
||||
|
||||
return new TemplateResponse($this->appName, 'reader', $params, 'blank');
|
||||
}
|
||||
|
||||
}
|
55
files_reader/img/app.svg
Normal file
55
files_reader/img/app.svg
Normal file
|
@ -0,0 +1,55 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
height="16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="app.svg">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="798"
|
||||
inkscape:window-height="1186"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="9.7984553"
|
||||
inkscape:cx="2.0136059"
|
||||
inkscape:cy="8.6779652"
|
||||
inkscape:window-x="800"
|
||||
inkscape:window-y="12"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg2" />
|
||||
<path
|
||||
inkscape:connector-curvature="0"
|
||||
d="M 6.3605388,1.1781792 C 5.3432889,0.71018919 3.3384715,1.6144462 2.7626049,2.4105432 2.50603,2.7667642 2.5241688,3.0234762 2.5241688,3.1691342 l 0,7.7918788 7.5182352,4.088872 1.413809,-0.674729 0,-7.5883898 -7.7192505,-3.87362 c 0.4142344,-0.455662 1.3458772,-1.011314 2.0444073,-0.788162 l 6.8757582,3.214357 0,8.4535718 1.417397,-0.675926 0,-8.4532028 z"
|
||||
id="path2989"
|
||||
sodipodi:nodetypes="cccccccccccccc"
|
||||
style="fill:#ffffff" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
197
files_reader/js/lib/Blob.js
Normal file
197
files_reader/js/lib/Blob.js
Normal file
|
@ -0,0 +1,197 @@
|
|||
/* Blob.js
|
||||
* A Blob implementation.
|
||||
* 2014-07-24
|
||||
*
|
||||
* By Eli Grey, http://eligrey.com
|
||||
* By Devin Samarin, https://github.com/dsamarin
|
||||
* License: X11/MIT
|
||||
* See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
/*global self, unescape */
|
||||
/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true,
|
||||
plusplus: true */
|
||||
|
||||
/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */
|
||||
|
||||
(function (view) {
|
||||
"use strict";
|
||||
|
||||
view.URL = view.URL || view.webkitURL;
|
||||
|
||||
if (view.Blob && view.URL) {
|
||||
try {
|
||||
new Blob;
|
||||
return;
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Internally we use a BlobBuilder implementation to base Blob off of
|
||||
// in order to support older browsers that only have BlobBuilder
|
||||
var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || (function(view) {
|
||||
var
|
||||
get_class = function(object) {
|
||||
return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
|
||||
}
|
||||
, FakeBlobBuilder = function BlobBuilder() {
|
||||
this.data = [];
|
||||
}
|
||||
, FakeBlob = function Blob(data, type, encoding) {
|
||||
this.data = data;
|
||||
this.size = data.length;
|
||||
this.type = type;
|
||||
this.encoding = encoding;
|
||||
}
|
||||
, FBB_proto = FakeBlobBuilder.prototype
|
||||
, FB_proto = FakeBlob.prototype
|
||||
, FileReaderSync = view.FileReaderSync
|
||||
, FileException = function(type) {
|
||||
this.code = this[this.name = type];
|
||||
}
|
||||
, file_ex_codes = (
|
||||
"NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR "
|
||||
+ "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR"
|
||||
).split(" ")
|
||||
, file_ex_code = file_ex_codes.length
|
||||
, real_URL = view.URL || view.webkitURL || view
|
||||
, real_create_object_URL = real_URL.createObjectURL
|
||||
, real_revoke_object_URL = real_URL.revokeObjectURL
|
||||
, URL = real_URL
|
||||
, btoa = view.btoa
|
||||
, atob = view.atob
|
||||
|
||||
, ArrayBuffer = view.ArrayBuffer
|
||||
, Uint8Array = view.Uint8Array
|
||||
|
||||
, origin = /^[\w-]+:\/*\[?[\w\.:-]+\]?(?::[0-9]+)?/
|
||||
;
|
||||
FakeBlob.fake = FB_proto.fake = true;
|
||||
while (file_ex_code--) {
|
||||
FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1;
|
||||
}
|
||||
// Polyfill URL
|
||||
if (!real_URL.createObjectURL) {
|
||||
URL = view.URL = function(uri) {
|
||||
var
|
||||
uri_info = document.createElementNS("http://www.w3.org/1999/xhtml", "a")
|
||||
, uri_origin
|
||||
;
|
||||
uri_info.href = uri;
|
||||
if (!("origin" in uri_info)) {
|
||||
if (uri_info.protocol.toLowerCase() === "data:") {
|
||||
uri_info.origin = null;
|
||||
} else {
|
||||
uri_origin = uri.match(origin);
|
||||
uri_info.origin = uri_origin && uri_origin[1];
|
||||
}
|
||||
}
|
||||
return uri_info;
|
||||
};
|
||||
}
|
||||
URL.createObjectURL = function(blob) {
|
||||
var
|
||||
type = blob.type
|
||||
, data_URI_header
|
||||
;
|
||||
if (type === null) {
|
||||
type = "application/octet-stream";
|
||||
}
|
||||
if (blob instanceof FakeBlob) {
|
||||
data_URI_header = "data:" + type;
|
||||
if (blob.encoding === "base64") {
|
||||
return data_URI_header + ";base64," + blob.data;
|
||||
} else if (blob.encoding === "URI") {
|
||||
return data_URI_header + "," + decodeURIComponent(blob.data);
|
||||
} if (btoa) {
|
||||
return data_URI_header + ";base64," + btoa(blob.data);
|
||||
} else {
|
||||
return data_URI_header + "," + encodeURIComponent(blob.data);
|
||||
}
|
||||
} else if (real_create_object_URL) {
|
||||
return real_create_object_URL.call(real_URL, blob);
|
||||
}
|
||||
};
|
||||
URL.revokeObjectURL = function(object_URL) {
|
||||
if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) {
|
||||
real_revoke_object_URL.call(real_URL, object_URL);
|
||||
}
|
||||
};
|
||||
FBB_proto.append = function(data/*, endings*/) {
|
||||
var bb = this.data;
|
||||
// decode data to a binary string
|
||||
if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) {
|
||||
var
|
||||
str = ""
|
||||
, buf = new Uint8Array(data)
|
||||
, i = 0
|
||||
, buf_len = buf.length
|
||||
;
|
||||
for (; i < buf_len; i++) {
|
||||
str += String.fromCharCode(buf[i]);
|
||||
}
|
||||
bb.push(str);
|
||||
} else if (get_class(data) === "Blob" || get_class(data) === "File") {
|
||||
if (FileReaderSync) {
|
||||
var fr = new FileReaderSync;
|
||||
bb.push(fr.readAsBinaryString(data));
|
||||
} else {
|
||||
// async FileReader won't work as BlobBuilder is sync
|
||||
throw new FileException("NOT_READABLE_ERR");
|
||||
}
|
||||
} else if (data instanceof FakeBlob) {
|
||||
if (data.encoding === "base64" && atob) {
|
||||
bb.push(atob(data.data));
|
||||
} else if (data.encoding === "URI") {
|
||||
bb.push(decodeURIComponent(data.data));
|
||||
} else if (data.encoding === "raw") {
|
||||
bb.push(data.data);
|
||||
}
|
||||
} else {
|
||||
if (typeof data !== "string") {
|
||||
data += ""; // convert unsupported types to strings
|
||||
}
|
||||
// decode UTF-16 to binary string
|
||||
bb.push(unescape(encodeURIComponent(data)));
|
||||
}
|
||||
};
|
||||
FBB_proto.getBlob = function(type) {
|
||||
if (!arguments.length) {
|
||||
type = null;
|
||||
}
|
||||
return new FakeBlob(this.data.join(""), type, "raw");
|
||||
};
|
||||
FBB_proto.toString = function() {
|
||||
return "[object BlobBuilder]";
|
||||
};
|
||||
FB_proto.slice = function(start, end, type) {
|
||||
var args = arguments.length;
|
||||
if (args < 3) {
|
||||
type = null;
|
||||
}
|
||||
return new FakeBlob(
|
||||
this.data.slice(start, args > 1 ? end : this.data.length)
|
||||
, type
|
||||
, this.encoding
|
||||
);
|
||||
};
|
||||
FB_proto.toString = function() {
|
||||
return "[object Blob]";
|
||||
};
|
||||
FB_proto.close = function() {
|
||||
this.size = 0;
|
||||
delete this.data;
|
||||
};
|
||||
return FakeBlobBuilder;
|
||||
}(view));
|
||||
|
||||
view.Blob = function(blobParts, options) {
|
||||
var type = options ? (options.type || "") : "";
|
||||
var builder = new BlobBuilder();
|
||||
if (blobParts) {
|
||||
for (var i = 0, len = blobParts.length; i < len; i++) {
|
||||
builder.append(blobParts[i]);
|
||||
}
|
||||
}
|
||||
return builder.getBlob(type);
|
||||
};
|
||||
}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this));
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +0,0 @@
|
|||
/*! jquery.finger - v0.1.2 - 2014-10-01
|
||||
* https://github.com/ngryman/jquery.finger
|
||||
* Copyright (c) 2014 Nicolas Gryman; Licensed MIT */
|
||||
(function(e,t){function a(t){t.preventDefault(),e.event.remove(T,"click",a)}function n(e,t){return(p?t.originalEvent.touches[0]:t)["page"+e.toUpperCase()]}function r(t,n,r){var o=e.Event(n,b);e.event.trigger(o,{originalEvent:t},t.target),o.isDefaultPrevented()&&(~n.indexOf("tap")&&!p?e.event.add(T,"click",a):t.preventDefault()),r&&(e.event.remove(T,y+"."+D,i),e.event.remove(T,x+"."+D,d))}function o(t){var o=t.timeStamp||+new Date;v!=o&&(v=o,k.x=b.x=n("x",t),k.y=b.y=n("y",t),k.time=o,k.target=t.target,b.orientation=null,b.end=!1,u=!1,l=!1,c=setTimeout(function(){l=!0,r(t,"press")},e.Finger.pressDuration),e.event.add(T,y+"."+D,i),e.event.add(T,x+"."+D,d),w.preventDefault&&(t.preventDefault(),e.event.add(T,"click",a)))}function i(t){if(b.x=n("x",t),b.y=n("y",t),b.dx=b.x-k.x,b.dy=b.y-k.y,b.adx=Math.abs(b.dx),b.ady=Math.abs(b.dy),u=b.adx>w.motionThreshold||b.ady>w.motionThreshold){for(clearTimeout(c),b.orientation||(b.adx>b.ady?(b.orientation="horizontal",b.direction=b.dx>0?1:-1):(b.orientation="vertical",b.direction=b.dy>0?1:-1));t.target&&t.target!==k.target;)t.target=t.target.parentNode;return t.target!==k.target?(t.target=k.target,d.call(this,e.Event(x+"."+D,t)),void 0):(r(t,"drag"),void 0)}}function d(e){var t,a=e.timeStamp||+new Date,n=a-k.time;if(clearTimeout(c),u||l||e.target!==k.target)e.target=k.target,w.flickDuration>n&&r(e,"flick"),b.end=!0,t="drag";else{var o=g===e.target&&w.doubleTapInterval>a-s;t=o?"doubletap":"tap",g=o?null:k.target,s=a}r(e,t,!0)}var u,l,v,c,g,s,m=/chrome/i.exec(t),f=/android/i.exec(t),p="ontouchstart"in window&&!(m&&!f),h=p?"touchstart":"mousedown",x=p?"touchend touchcancel":"mouseup mouseleave",y=p?"touchmove":"mousemove",D="finger",T=e("html")[0],k={},b={},w=e.Finger={pressDuration:300,doubleTapInterval:300,flickDuration:150,motionThreshold:5};e.event.add(T,h+"."+D,o)})(jQuery,navigator.userAgent);
|
File diff suppressed because it is too large
Load diff
|
@ -1,241 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2013 Gildas Lormeau. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
var ERR_HTTP_RANGE = "HTTP Range not supported.";
|
||||
|
||||
var Reader = zip.Reader;
|
||||
var Writer = zip.Writer;
|
||||
|
||||
var ZipDirectoryEntry;
|
||||
|
||||
var appendABViewSupported;
|
||||
try {
|
||||
appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
function HttpReader(url) {
|
||||
var that = this;
|
||||
|
||||
function getData(callback, onerror) {
|
||||
var request;
|
||||
if (!that.data) {
|
||||
request = new XMLHttpRequest();
|
||||
request.addEventListener("load", function() {
|
||||
if (!that.size)
|
||||
that.size = Number(request.getResponseHeader("Content-Length"));
|
||||
that.data = new Uint8Array(request.response);
|
||||
callback();
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.open("GET", url);
|
||||
request.responseType = "arraybuffer";
|
||||
request.send();
|
||||
} else
|
||||
callback();
|
||||
}
|
||||
|
||||
function init(callback, onerror) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("load", function() {
|
||||
that.size = Number(request.getResponseHeader("Content-Length"));
|
||||
callback();
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.open("HEAD", url);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
getData(function() {
|
||||
callback(new Uint8Array(that.data.subarray(index, index + length)));
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
HttpReader.prototype = new Reader();
|
||||
HttpReader.prototype.constructor = HttpReader;
|
||||
|
||||
function HttpRangeReader(url) {
|
||||
var that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.addEventListener("load", function() {
|
||||
that.size = Number(request.getResponseHeader("Content-Length"));
|
||||
if (request.getResponseHeader("Accept-Ranges") == "bytes")
|
||||
callback();
|
||||
else
|
||||
onerror(ERR_HTTP_RANGE);
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.open("HEAD", url);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function readArrayBuffer(index, length, callback, onerror) {
|
||||
var request = new XMLHttpRequest();
|
||||
request.open("GET", url);
|
||||
request.responseType = "arraybuffer";
|
||||
request.setRequestHeader("Range", "bytes=" + index + "-" + (index + length - 1));
|
||||
request.addEventListener("load", function() {
|
||||
callback(request.response);
|
||||
}, false);
|
||||
request.addEventListener("error", onerror, false);
|
||||
request.send();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
readArrayBuffer(index, length, function(arraybuffer) {
|
||||
callback(new Uint8Array(arraybuffer));
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
HttpRangeReader.prototype = new Reader();
|
||||
HttpRangeReader.prototype.constructor = HttpRangeReader;
|
||||
|
||||
function ArrayBufferReader(arrayBuffer) {
|
||||
var that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
that.size = arrayBuffer.byteLength;
|
||||
callback();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
callback(new Uint8Array(arrayBuffer.slice(index, index + length)));
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
ArrayBufferReader.prototype = new Reader();
|
||||
ArrayBufferReader.prototype.constructor = ArrayBufferReader;
|
||||
|
||||
function ArrayBufferWriter() {
|
||||
var array, that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
array = new Uint8Array();
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(arr, callback, onerror) {
|
||||
var tmpArray = new Uint8Array(array.length + arr.length);
|
||||
tmpArray.set(array);
|
||||
tmpArray.set(arr, array.length);
|
||||
array = tmpArray;
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
callback(array.buffer);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
ArrayBufferWriter.prototype = new Writer();
|
||||
ArrayBufferWriter.prototype.constructor = ArrayBufferWriter;
|
||||
|
||||
function FileWriter(fileEntry, contentType) {
|
||||
var writer, that = this;
|
||||
|
||||
function init(callback, onerror) {
|
||||
fileEntry.createWriter(function(fileWriter) {
|
||||
writer = fileWriter;
|
||||
callback();
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback, onerror) {
|
||||
var blob = new Blob([ appendABViewSupported ? array : array.buffer ], {
|
||||
type : contentType
|
||||
});
|
||||
writer.onwrite = function() {
|
||||
writer.onwrite = null;
|
||||
callback();
|
||||
};
|
||||
writer.onerror = onerror;
|
||||
writer.write(blob);
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
fileEntry.file(callback);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
FileWriter.prototype = new Writer();
|
||||
FileWriter.prototype.constructor = FileWriter;
|
||||
|
||||
zip.FileWriter = FileWriter;
|
||||
zip.HttpReader = HttpReader;
|
||||
zip.HttpRangeReader = HttpRangeReader;
|
||||
zip.ArrayBufferReader = ArrayBufferReader;
|
||||
zip.ArrayBufferWriter = ArrayBufferWriter;
|
||||
|
||||
if (zip.fs) {
|
||||
ZipDirectoryEntry = zip.fs.ZipDirectoryEntry;
|
||||
ZipDirectoryEntry.prototype.addHttpContent = function(name, URL, useRangeHeader) {
|
||||
function addChild(parent, name, params, directory) {
|
||||
if (parent.directory)
|
||||
return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new zip.fs.ZipFileEntry(parent.fs, name, params, parent);
|
||||
else
|
||||
throw "Parent entry is not a directory.";
|
||||
}
|
||||
|
||||
return addChild(this, name, {
|
||||
data : URL,
|
||||
Reader : useRangeHeader ? HttpRangeReader : HttpReader
|
||||
});
|
||||
};
|
||||
ZipDirectoryEntry.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) {
|
||||
this.importZip(useRangeHeader ? new HttpRangeReader(URL) : new HttpReader(URL), onend, onerror);
|
||||
};
|
||||
zip.fs.FS.prototype.importHttpContent = function(URL, useRangeHeader, onend, onerror) {
|
||||
this.entries = [];
|
||||
this.root = new ZipDirectoryEntry(this);
|
||||
this.root.importHttpContent(URL, useRangeHeader, onend, onerror);
|
||||
};
|
||||
}
|
||||
|
||||
})();
|
|
@ -1,538 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2013 Gildas Lormeau. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
(function() {
|
||||
|
||||
var CHUNK_SIZE = 512 * 1024;
|
||||
|
||||
var TextWriter = zip.TextWriter, //
|
||||
BlobWriter = zip.BlobWriter, //
|
||||
Data64URIWriter = zip.Data64URIWriter, //
|
||||
Reader = zip.Reader, //
|
||||
TextReader = zip.TextReader, //
|
||||
BlobReader = zip.BlobReader, //
|
||||
Data64URIReader = zip.Data64URIReader, //
|
||||
createReader = zip.createReader, //
|
||||
createWriter = zip.createWriter;
|
||||
|
||||
function ZipBlobReader(entry) {
|
||||
var that = this, blobReader;
|
||||
|
||||
function init(callback) {
|
||||
this.size = entry.uncompressedSize;
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
if (that.data)
|
||||
callback();
|
||||
else
|
||||
entry.getData(new BlobWriter(), function(data) {
|
||||
that.data = data;
|
||||
blobReader = new BlobReader(data);
|
||||
callback();
|
||||
}, null, that.checkCrc32);
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
getData(function() {
|
||||
blobReader.readUint8Array(index, length, callback, onerror);
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
ZipBlobReader.prototype = new Reader();
|
||||
ZipBlobReader.prototype.constructor = ZipBlobReader;
|
||||
ZipBlobReader.prototype.checkCrc32 = false;
|
||||
|
||||
function getTotalSize(entry) {
|
||||
var size = 0;
|
||||
|
||||
function process(entry) {
|
||||
size += entry.uncompressedSize || 0;
|
||||
entry.children.forEach(process);
|
||||
}
|
||||
|
||||
process(entry);
|
||||
return size;
|
||||
}
|
||||
|
||||
function initReaders(entry, onend, onerror) {
|
||||
var index = 0;
|
||||
|
||||
function next() {
|
||||
index++;
|
||||
if (index < entry.children.length)
|
||||
process(entry.children[index]);
|
||||
else
|
||||
onend();
|
||||
}
|
||||
|
||||
function process(child) {
|
||||
if (child.directory)
|
||||
initReaders(child, next, onerror);
|
||||
else {
|
||||
child.reader = new child.Reader(child.data, onerror);
|
||||
child.reader.init(function() {
|
||||
child.uncompressedSize = child.reader.size;
|
||||
next();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.children.length)
|
||||
process(entry.children[index]);
|
||||
else
|
||||
onend();
|
||||
}
|
||||
|
||||
function detach(entry) {
|
||||
var children = entry.parent.children;
|
||||
children.forEach(function(child, index) {
|
||||
if (child.id == entry.id)
|
||||
children.splice(index, 1);
|
||||
});
|
||||
}
|
||||
|
||||
function exportZip(zipWriter, entry, onend, onprogress, totalSize) {
|
||||
var currentIndex = 0;
|
||||
|
||||
function process(zipWriter, entry, onend, onprogress, totalSize) {
|
||||
var childIndex = 0;
|
||||
|
||||
function exportChild() {
|
||||
var child = entry.children[childIndex];
|
||||
if (child)
|
||||
zipWriter.add(child.getFullname(), child.reader, function() {
|
||||
currentIndex += child.uncompressedSize || 0;
|
||||
process(zipWriter, child, function() {
|
||||
childIndex++;
|
||||
exportChild();
|
||||
}, onprogress, totalSize);
|
||||
}, function(index) {
|
||||
if (onprogress)
|
||||
onprogress(currentIndex + index, totalSize);
|
||||
}, {
|
||||
directory : child.directory,
|
||||
version : child.zipVersion
|
||||
});
|
||||
else
|
||||
onend();
|
||||
}
|
||||
|
||||
exportChild();
|
||||
}
|
||||
|
||||
process(zipWriter, entry, onend, onprogress, totalSize);
|
||||
}
|
||||
|
||||
function addFileEntry(zipEntry, fileEntry, onend, onerror) {
|
||||
function getChildren(fileEntry, callback) {
|
||||
if (fileEntry.isDirectory)
|
||||
fileEntry.createReader().readEntries(callback);
|
||||
if (fileEntry.isFile)
|
||||
callback([]);
|
||||
}
|
||||
|
||||
function process(zipEntry, fileEntry, onend) {
|
||||
getChildren(fileEntry, function(children) {
|
||||
var childIndex = 0;
|
||||
|
||||
function addChild(child) {
|
||||
function nextChild(childFileEntry) {
|
||||
process(childFileEntry, child, function() {
|
||||
childIndex++;
|
||||
processChild();
|
||||
});
|
||||
}
|
||||
|
||||
if (child.isDirectory)
|
||||
nextChild(zipEntry.addDirectory(child.name));
|
||||
if (child.isFile)
|
||||
child.file(function(file) {
|
||||
var childZipEntry = zipEntry.addBlob(child.name, file);
|
||||
childZipEntry.uncompressedSize = file.size;
|
||||
nextChild(childZipEntry);
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
function processChild() {
|
||||
var child = children[childIndex];
|
||||
if (child)
|
||||
addChild(child);
|
||||
else
|
||||
onend();
|
||||
}
|
||||
|
||||
processChild();
|
||||
});
|
||||
}
|
||||
|
||||
if (fileEntry.isDirectory)
|
||||
process(zipEntry, fileEntry, onend);
|
||||
else
|
||||
fileEntry.file(function(file) {
|
||||
zipEntry.addBlob(fileEntry.name, file);
|
||||
onend();
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
function getFileEntry(fileEntry, entry, onend, onprogress, onerror, totalSize, checkCrc32) {
|
||||
var currentIndex = 0;
|
||||
|
||||
function process(fileEntry, entry, onend, onprogress, onerror, totalSize) {
|
||||
var childIndex = 0;
|
||||
|
||||
function addChild(child) {
|
||||
function nextChild(childFileEntry) {
|
||||
currentIndex += child.uncompressedSize || 0;
|
||||
process(childFileEntry, child, function() {
|
||||
childIndex++;
|
||||
processChild();
|
||||
}, onprogress, onerror, totalSize);
|
||||
}
|
||||
|
||||
if (child.directory)
|
||||
fileEntry.getDirectory(child.name, {
|
||||
create : true
|
||||
}, nextChild, onerror);
|
||||
else
|
||||
fileEntry.getFile(child.name, {
|
||||
create : true
|
||||
}, function(file) {
|
||||
child.getData(new zip.FileWriter(file, zip.getMimeType(child.name)), nextChild, function(index) {
|
||||
if (onprogress)
|
||||
onprogress(currentIndex + index, totalSize);
|
||||
}, checkCrc32);
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
function processChild() {
|
||||
var child = entry.children[childIndex];
|
||||
if (child)
|
||||
addChild(child);
|
||||
else
|
||||
onend();
|
||||
}
|
||||
|
||||
processChild();
|
||||
}
|
||||
|
||||
if (entry.directory)
|
||||
process(fileEntry, entry, onend, onprogress, onerror, totalSize);
|
||||
else
|
||||
entry.getData(new zip.FileWriter(fileEntry, zip.getMimeType(entry.name)), onend, onprogress, checkCrc32);
|
||||
}
|
||||
|
||||
function resetFS(fs) {
|
||||
fs.entries = [];
|
||||
fs.root = new ZipDirectoryEntry(fs);
|
||||
}
|
||||
|
||||
function bufferedCopy(reader, writer, onend, onprogress, onerror) {
|
||||
var chunkIndex = 0;
|
||||
|
||||
function stepCopy() {
|
||||
var index = chunkIndex * CHUNK_SIZE;
|
||||
if (onprogress)
|
||||
onprogress(index, reader.size);
|
||||
if (index < reader.size)
|
||||
reader.readUint8Array(index, Math.min(CHUNK_SIZE, reader.size - index), function(array) {
|
||||
writer.writeUint8Array(new Uint8Array(array), function() {
|
||||
chunkIndex++;
|
||||
stepCopy();
|
||||
});
|
||||
}, onerror);
|
||||
else
|
||||
writer.getData(onend);
|
||||
}
|
||||
|
||||
stepCopy();
|
||||
}
|
||||
|
||||
function getEntryData(writer, onend, onprogress, onerror) {
|
||||
var that = this;
|
||||
if (!writer || (writer.constructor == that.Writer && that.data))
|
||||
onend(that.data);
|
||||
else {
|
||||
if (!that.reader)
|
||||
that.reader = new that.Reader(that.data, onerror);
|
||||
that.reader.init(function() {
|
||||
writer.init(function() {
|
||||
bufferedCopy(that.reader, writer, onend, onprogress, onerror);
|
||||
}, onerror);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function addChild(parent, name, params, directory) {
|
||||
if (parent.directory)
|
||||
return directory ? new ZipDirectoryEntry(parent.fs, name, params, parent) : new ZipFileEntry(parent.fs, name, params, parent);
|
||||
else
|
||||
throw "Parent entry is not a directory.";
|
||||
}
|
||||
|
||||
function ZipEntry() {
|
||||
}
|
||||
|
||||
ZipEntry.prototype = {
|
||||
init : function(fs, name, params, parent) {
|
||||
var that = this;
|
||||
if (fs.root && parent && parent.getChildByName(name))
|
||||
throw "Entry filename already exists.";
|
||||
if (!params)
|
||||
params = {};
|
||||
that.fs = fs;
|
||||
that.name = name;
|
||||
that.id = fs.entries.length;
|
||||
that.parent = parent;
|
||||
that.children = [];
|
||||
that.zipVersion = params.zipVersion || 0x14;
|
||||
that.uncompressedSize = 0;
|
||||
fs.entries.push(that);
|
||||
if (parent)
|
||||
that.parent.children.push(that);
|
||||
},
|
||||
getFileEntry : function(fileEntry, onend, onprogress, onerror, checkCrc32) {
|
||||
var that = this;
|
||||
initReaders(that, function() {
|
||||
getFileEntry(fileEntry, that, onend, onprogress, onerror, getTotalSize(that), checkCrc32);
|
||||
}, onerror);
|
||||
},
|
||||
moveTo : function(target) {
|
||||
var that = this;
|
||||
if (target.directory) {
|
||||
if (!target.isDescendantOf(that)) {
|
||||
if (that != target) {
|
||||
if (target.getChildByName(that.name))
|
||||
throw "Entry filename already exists.";
|
||||
detach(that);
|
||||
that.parent = target;
|
||||
target.children.push(that);
|
||||
}
|
||||
} else
|
||||
throw "Entry is a ancestor of target entry.";
|
||||
} else
|
||||
throw "Target entry is not a directory.";
|
||||
},
|
||||
getFullname : function() {
|
||||
var that = this, fullname = that.name, entry = that.parent;
|
||||
while (entry) {
|
||||
fullname = (entry.name ? entry.name + "/" : "") + fullname;
|
||||
entry = entry.parent;
|
||||
}
|
||||
return fullname;
|
||||
},
|
||||
isDescendantOf : function(ancestor) {
|
||||
var entry = this.parent;
|
||||
while (entry && entry.id != ancestor.id)
|
||||
entry = entry.parent;
|
||||
return !!entry;
|
||||
}
|
||||
};
|
||||
ZipEntry.prototype.constructor = ZipEntry;
|
||||
|
||||
var ZipFileEntryProto;
|
||||
|
||||
function ZipFileEntry(fs, name, params, parent) {
|
||||
var that = this;
|
||||
ZipEntry.prototype.init.call(that, fs, name, params, parent);
|
||||
that.Reader = params.Reader;
|
||||
that.Writer = params.Writer;
|
||||
that.data = params.data;
|
||||
that.getData = params.getData || getEntryData;
|
||||
}
|
||||
|
||||
ZipFileEntry.prototype = ZipFileEntryProto = new ZipEntry();
|
||||
ZipFileEntryProto.constructor = ZipFileEntry;
|
||||
ZipFileEntryProto.getText = function(onend, onprogress, checkCrc32, encoding) {
|
||||
this.getData(new TextWriter(encoding), onend, onprogress, checkCrc32);
|
||||
};
|
||||
ZipFileEntryProto.getBlob = function(mimeType, onend, onprogress, checkCrc32) {
|
||||
this.getData(new BlobWriter(mimeType), onend, onprogress, checkCrc32);
|
||||
};
|
||||
ZipFileEntryProto.getData64URI = function(mimeType, onend, onprogress, checkCrc32) {
|
||||
this.getData(new Data64URIWriter(mimeType), onend, onprogress, checkCrc32);
|
||||
};
|
||||
|
||||
var ZipDirectoryEntryProto;
|
||||
|
||||
function ZipDirectoryEntry(fs, name, params, parent) {
|
||||
var that = this;
|
||||
ZipEntry.prototype.init.call(that, fs, name, params, parent);
|
||||
that.directory = true;
|
||||
}
|
||||
|
||||
ZipDirectoryEntry.prototype = ZipDirectoryEntryProto = new ZipEntry();
|
||||
ZipDirectoryEntryProto.constructor = ZipDirectoryEntry;
|
||||
ZipDirectoryEntryProto.addDirectory = function(name) {
|
||||
return addChild(this, name, null, true);
|
||||
};
|
||||
ZipDirectoryEntryProto.addText = function(name, text) {
|
||||
return addChild(this, name, {
|
||||
data : text,
|
||||
Reader : TextReader,
|
||||
Writer : TextWriter
|
||||
});
|
||||
};
|
||||
ZipDirectoryEntryProto.addBlob = function(name, blob) {
|
||||
return addChild(this, name, {
|
||||
data : blob,
|
||||
Reader : BlobReader,
|
||||
Writer : BlobWriter
|
||||
});
|
||||
};
|
||||
ZipDirectoryEntryProto.addData64URI = function(name, dataURI) {
|
||||
return addChild(this, name, {
|
||||
data : dataURI,
|
||||
Reader : Data64URIReader,
|
||||
Writer : Data64URIWriter
|
||||
});
|
||||
};
|
||||
ZipDirectoryEntryProto.addFileEntry = function(fileEntry, onend, onerror) {
|
||||
addFileEntry(this, fileEntry, onend, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.addData = function(name, params) {
|
||||
return addChild(this, name, params);
|
||||
};
|
||||
ZipDirectoryEntryProto.importBlob = function(blob, onend, onerror) {
|
||||
this.importZip(new BlobReader(blob), onend, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.importText = function(text, onend, onerror) {
|
||||
this.importZip(new TextReader(text), onend, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.importData64URI = function(dataURI, onend, onerror) {
|
||||
this.importZip(new Data64URIReader(dataURI), onend, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.exportBlob = function(onend, onprogress, onerror) {
|
||||
this.exportZip(new BlobWriter("application/zip"), onend, onprogress, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.exportText = function(onend, onprogress, onerror) {
|
||||
this.exportZip(new TextWriter(), onend, onprogress, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.exportFileEntry = function(fileEntry, onend, onprogress, onerror) {
|
||||
this.exportZip(new zip.FileWriter(fileEntry, "application/zip"), onend, onprogress, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.exportData64URI = function(onend, onprogress, onerror) {
|
||||
this.exportZip(new Data64URIWriter("application/zip"), onend, onprogress, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.importZip = function(reader, onend, onerror) {
|
||||
var that = this;
|
||||
createReader(reader, function(zipReader) {
|
||||
zipReader.getEntries(function(entries) {
|
||||
entries.forEach(function(entry) {
|
||||
var parent = that, path = entry.filename.split("/"), name = path.pop();
|
||||
path.forEach(function(pathPart) {
|
||||
parent = parent.getChildByName(pathPart) || new ZipDirectoryEntry(that.fs, pathPart, null, parent);
|
||||
});
|
||||
if (!entry.directory)
|
||||
addChild(parent, name, {
|
||||
data : entry,
|
||||
Reader : ZipBlobReader
|
||||
});
|
||||
});
|
||||
onend();
|
||||
});
|
||||
}, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.exportZip = function(writer, onend, onprogress, onerror) {
|
||||
var that = this;
|
||||
initReaders(that, function() {
|
||||
createWriter(writer, function(zipWriter) {
|
||||
exportZip(zipWriter, that, function() {
|
||||
zipWriter.close(onend);
|
||||
}, onprogress, getTotalSize(that));
|
||||
}, onerror);
|
||||
}, onerror);
|
||||
};
|
||||
ZipDirectoryEntryProto.getChildByName = function(name) {
|
||||
var childIndex, child, that = this;
|
||||
for (childIndex = 0; childIndex < that.children.length; childIndex++) {
|
||||
child = that.children[childIndex];
|
||||
if (child.name == name)
|
||||
return child;
|
||||
}
|
||||
};
|
||||
|
||||
function FS() {
|
||||
resetFS(this);
|
||||
}
|
||||
FS.prototype = {
|
||||
remove : function(entry) {
|
||||
detach(entry);
|
||||
this.entries[entry.id] = null;
|
||||
},
|
||||
find : function(fullname) {
|
||||
var index, path = fullname.split("/"), node = this.root;
|
||||
for (index = 0; node && index < path.length; index++)
|
||||
node = node.getChildByName(path[index]);
|
||||
return node;
|
||||
},
|
||||
getById : function(id) {
|
||||
return this.entries[id];
|
||||
},
|
||||
importBlob : function(blob, onend, onerror) {
|
||||
resetFS(this);
|
||||
this.root.importBlob(blob, onend, onerror);
|
||||
},
|
||||
importText : function(text, onend, onerror) {
|
||||
resetFS(this);
|
||||
this.root.importText(text, onend, onerror);
|
||||
},
|
||||
importData64URI : function(dataURI, onend, onerror) {
|
||||
resetFS(this);
|
||||
this.root.importData64URI(dataURI, onend, onerror);
|
||||
},
|
||||
exportBlob : function(onend, onprogress, onerror) {
|
||||
this.root.exportBlob(onend, onprogress, onerror);
|
||||
},
|
||||
exportText : function(onend, onprogress, onerror) {
|
||||
this.root.exportText(onend, onprogress, onerror);
|
||||
},
|
||||
exportFileEntry : function(fileEntry, onend, onprogress, onerror) {
|
||||
this.root.exportFileEntry(fileEntry, onend, onprogress, onerror);
|
||||
},
|
||||
exportData64URI : function(onend, onprogress, onerror) {
|
||||
this.root.exportData64URI(onend, onprogress, onerror);
|
||||
}
|
||||
};
|
||||
|
||||
zip.fs = {
|
||||
FS : FS,
|
||||
ZipDirectoryEntry : ZipDirectoryEntry,
|
||||
ZipFileEntry : ZipFileEntry
|
||||
};
|
||||
|
||||
zip.getMimeType = function() {
|
||||
return "application/octet-stream";
|
||||
};
|
||||
|
||||
})();
|
|
@ -1,801 +0,0 @@
|
|||
/*
|
||||
Copyright (c) 2013 Gildas Lormeau. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. The names of the authors may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
|
||||
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
(function(obj) {
|
||||
|
||||
var ERR_BAD_FORMAT = "File format is not recognized.";
|
||||
var ERR_ENCRYPTED = "File contains encrypted entry.";
|
||||
var ERR_ZIP64 = "File is using Zip64 (4gb+ file size).";
|
||||
var ERR_READ = "Error while reading zip file.";
|
||||
var ERR_WRITE = "Error while writing zip file.";
|
||||
var ERR_WRITE_DATA = "Error while writing file data.";
|
||||
var ERR_READ_DATA = "Error while reading file data.";
|
||||
var ERR_DUPLICATED_NAME = "File already exists.";
|
||||
var CHUNK_SIZE = 512 * 1024;
|
||||
|
||||
var INFLATE_JS = "inflate.js";
|
||||
var DEFLATE_JS = "deflate.js";
|
||||
|
||||
var TEXT_PLAIN = "text/plain";
|
||||
|
||||
var MESSAGE_EVENT = "message";
|
||||
|
||||
var appendABViewSupported;
|
||||
try {
|
||||
appendABViewSupported = new Blob([ new DataView(new ArrayBuffer(0)) ]).size === 0;
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
function Crc32() {
|
||||
var crc = -1, that = this;
|
||||
that.append = function(data) {
|
||||
var offset, table = that.table;
|
||||
for (offset = 0; offset < data.length; offset++)
|
||||
crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF];
|
||||
};
|
||||
that.get = function() {
|
||||
return ~crc;
|
||||
};
|
||||
}
|
||||
Crc32.prototype.table = (function() {
|
||||
var i, j, t, table = [];
|
||||
for (i = 0; i < 256; i++) {
|
||||
t = i;
|
||||
for (j = 0; j < 8; j++)
|
||||
if (t & 1)
|
||||
t = (t >>> 1) ^ 0xEDB88320;
|
||||
else
|
||||
t = t >>> 1;
|
||||
table[i] = t;
|
||||
}
|
||||
return table;
|
||||
})();
|
||||
|
||||
function blobSlice(blob, index, length) {
|
||||
if (blob.slice)
|
||||
return blob.slice(index, index + length);
|
||||
else if (blob.webkitSlice)
|
||||
return blob.webkitSlice(index, index + length);
|
||||
else if (blob.mozSlice)
|
||||
return blob.mozSlice(index, index + length);
|
||||
else if (blob.msSlice)
|
||||
return blob.msSlice(index, index + length);
|
||||
}
|
||||
|
||||
function getDataHelper(byteLength, bytes) {
|
||||
var dataBuffer, dataArray;
|
||||
dataBuffer = new ArrayBuffer(byteLength);
|
||||
dataArray = new Uint8Array(dataBuffer);
|
||||
if (bytes)
|
||||
dataArray.set(bytes, 0);
|
||||
return {
|
||||
buffer : dataBuffer,
|
||||
array : dataArray,
|
||||
view : new DataView(dataBuffer)
|
||||
};
|
||||
}
|
||||
|
||||
// Readers
|
||||
function Reader() {
|
||||
}
|
||||
|
||||
function TextReader(text) {
|
||||
var that = this, blobReader;
|
||||
|
||||
function init(callback, onerror) {
|
||||
var blob = new Blob([ text ], {
|
||||
type : TEXT_PLAIN
|
||||
});
|
||||
blobReader = new BlobReader(blob);
|
||||
blobReader.init(function() {
|
||||
that.size = blobReader.size;
|
||||
callback();
|
||||
}, onerror);
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
blobReader.readUint8Array(index, length, callback, onerror);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
TextReader.prototype = new Reader();
|
||||
TextReader.prototype.constructor = TextReader;
|
||||
|
||||
function Data64URIReader(dataURI) {
|
||||
var that = this, dataStart;
|
||||
|
||||
function init(callback) {
|
||||
var dataEnd = dataURI.length;
|
||||
while (dataURI.charAt(dataEnd - 1) == "=")
|
||||
dataEnd--;
|
||||
dataStart = dataURI.indexOf(",") + 1;
|
||||
that.size = Math.floor((dataEnd - dataStart) * 0.75);
|
||||
callback();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback) {
|
||||
var i, data = getDataHelper(length);
|
||||
var start = Math.floor(index / 3) * 4;
|
||||
var end = Math.ceil((index + length) / 3) * 4;
|
||||
var bytes = obj.atob(dataURI.substring(start + dataStart, end + dataStart));
|
||||
var delta = index - Math.floor(start / 4) * 3;
|
||||
for (i = delta; i < delta + length; i++)
|
||||
data.array[i - delta] = bytes.charCodeAt(i);
|
||||
callback(data.array);
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
Data64URIReader.prototype = new Reader();
|
||||
Data64URIReader.prototype.constructor = Data64URIReader;
|
||||
|
||||
function BlobReader(blob) {
|
||||
var that = this;
|
||||
|
||||
function init(callback) {
|
||||
this.size = blob.size;
|
||||
callback();
|
||||
}
|
||||
|
||||
function readUint8Array(index, length, callback, onerror) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
callback(new Uint8Array(e.target.result));
|
||||
};
|
||||
reader.onerror = onerror;
|
||||
reader.readAsArrayBuffer(blobSlice(blob, index, length));
|
||||
}
|
||||
|
||||
that.size = 0;
|
||||
that.init = init;
|
||||
that.readUint8Array = readUint8Array;
|
||||
}
|
||||
BlobReader.prototype = new Reader();
|
||||
BlobReader.prototype.constructor = BlobReader;
|
||||
|
||||
// Writers
|
||||
|
||||
function Writer() {
|
||||
}
|
||||
Writer.prototype.getData = function(callback) {
|
||||
callback(this.data);
|
||||
};
|
||||
|
||||
function TextWriter(encoding) {
|
||||
var that = this, blob;
|
||||
|
||||
function init(callback) {
|
||||
blob = new Blob([], {
|
||||
type : TEXT_PLAIN
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback) {
|
||||
blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
|
||||
type : TEXT_PLAIN
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback, onerror) {
|
||||
var reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
callback(e.target.result);
|
||||
};
|
||||
reader.onerror = onerror;
|
||||
reader.readAsText(blob, encoding);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
TextWriter.prototype = new Writer();
|
||||
TextWriter.prototype.constructor = TextWriter;
|
||||
|
||||
function Data64URIWriter(contentType) {
|
||||
var that = this, data = "", pending = "";
|
||||
|
||||
function init(callback) {
|
||||
data += "data:" + (contentType || "") + ";base64,";
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback) {
|
||||
var i, delta = pending.length, dataString = pending;
|
||||
pending = "";
|
||||
for (i = 0; i < (Math.floor((delta + array.length) / 3) * 3) - delta; i++)
|
||||
dataString += String.fromCharCode(array[i]);
|
||||
for (; i < array.length; i++)
|
||||
pending += String.fromCharCode(array[i]);
|
||||
if (dataString.length > 2)
|
||||
data += obj.btoa(dataString);
|
||||
else
|
||||
pending = dataString;
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
callback(data + obj.btoa(pending));
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
Data64URIWriter.prototype = new Writer();
|
||||
Data64URIWriter.prototype.constructor = Data64URIWriter;
|
||||
|
||||
function BlobWriter(contentType) {
|
||||
var blob, that = this;
|
||||
|
||||
function init(callback) {
|
||||
blob = new Blob([], {
|
||||
type : contentType
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function writeUint8Array(array, callback) {
|
||||
blob = new Blob([ blob, appendABViewSupported ? array : array.buffer ], {
|
||||
type : contentType
|
||||
});
|
||||
callback();
|
||||
}
|
||||
|
||||
function getData(callback) {
|
||||
callback(blob);
|
||||
}
|
||||
|
||||
that.init = init;
|
||||
that.writeUint8Array = writeUint8Array;
|
||||
that.getData = getData;
|
||||
}
|
||||
BlobWriter.prototype = new Writer();
|
||||
BlobWriter.prototype.constructor = BlobWriter;
|
||||
|
||||
// inflate/deflate core functions
|
||||
|
||||
function launchWorkerProcess(worker, reader, writer, offset, size, onappend, onprogress, onend, onreaderror, onwriteerror) {
|
||||
var chunkIndex = 0, index, outputSize;
|
||||
|
||||
function onflush() {
|
||||
worker.removeEventListener(MESSAGE_EVENT, onmessage, false);
|
||||
onend(outputSize);
|
||||
}
|
||||
|
||||
function onmessage(event) {
|
||||
var message = event.data, data = message.data;
|
||||
|
||||
if (message.onappend) {
|
||||
outputSize += data.length;
|
||||
writer.writeUint8Array(data, function() {
|
||||
onappend(false, data);
|
||||
step();
|
||||
}, onwriteerror);
|
||||
}
|
||||
if (message.onflush)
|
||||
if (data) {
|
||||
outputSize += data.length;
|
||||
writer.writeUint8Array(data, function() {
|
||||
onappend(false, data);
|
||||
onflush();
|
||||
}, onwriteerror);
|
||||
} else
|
||||
onflush();
|
||||
if (message.progress && onprogress)
|
||||
onprogress(index + message.current, size);
|
||||
}
|
||||
|
||||
function step() {
|
||||
index = chunkIndex * CHUNK_SIZE;
|
||||
if (index < size)
|
||||
reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(array) {
|
||||
worker.postMessage({
|
||||
append : true,
|
||||
data : array
|
||||
});
|
||||
chunkIndex++;
|
||||
if (onprogress)
|
||||
onprogress(index, size);
|
||||
onappend(true, array);
|
||||
}, onreaderror);
|
||||
else
|
||||
worker.postMessage({
|
||||
flush : true
|
||||
});
|
||||
}
|
||||
|
||||
outputSize = 0;
|
||||
worker.addEventListener(MESSAGE_EVENT, onmessage, false);
|
||||
step();
|
||||
}
|
||||
|
||||
function launchProcess(process, reader, writer, offset, size, onappend, onprogress, onend, onreaderror, onwriteerror) {
|
||||
var chunkIndex = 0, index, outputSize = 0;
|
||||
|
||||
function step() {
|
||||
var outputData;
|
||||
index = chunkIndex * CHUNK_SIZE;
|
||||
if (index < size)
|
||||
reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(inputData) {
|
||||
var outputData = process.append(inputData, function() {
|
||||
if (onprogress)
|
||||
onprogress(offset + index, size);
|
||||
});
|
||||
outputSize += outputData.length;
|
||||
onappend(true, inputData);
|
||||
writer.writeUint8Array(outputData, function() {
|
||||
onappend(false, outputData);
|
||||
chunkIndex++;
|
||||
setTimeout(step, 1);
|
||||
}, onwriteerror);
|
||||
if (onprogress)
|
||||
onprogress(index, size);
|
||||
}, onreaderror);
|
||||
else {
|
||||
outputData = process.flush();
|
||||
if (outputData) {
|
||||
outputSize += outputData.length;
|
||||
writer.writeUint8Array(outputData, function() {
|
||||
onappend(false, outputData);
|
||||
onend(outputSize);
|
||||
}, onwriteerror);
|
||||
} else
|
||||
onend(outputSize);
|
||||
}
|
||||
}
|
||||
|
||||
step();
|
||||
}
|
||||
|
||||
function inflate(reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
|
||||
var worker, crc32 = new Crc32();
|
||||
|
||||
function oninflateappend(sending, array) {
|
||||
if (computeCrc32 && !sending)
|
||||
crc32.append(array);
|
||||
}
|
||||
|
||||
function oninflateend(outputSize) {
|
||||
onend(outputSize, crc32.get());
|
||||
}
|
||||
|
||||
if (obj.zip.useWebWorkers) {
|
||||
worker = new Worker(obj.zip.workerScriptsPath + INFLATE_JS);
|
||||
launchWorkerProcess(worker, reader, writer, offset, size, oninflateappend, onprogress, oninflateend, onreaderror, onwriteerror);
|
||||
} else
|
||||
launchProcess(new obj.zip.Inflater(), reader, writer, offset, size, oninflateappend, onprogress, oninflateend, onreaderror, onwriteerror);
|
||||
return worker;
|
||||
}
|
||||
|
||||
function deflate(reader, writer, level, onend, onprogress, onreaderror, onwriteerror) {
|
||||
var worker, crc32 = new Crc32();
|
||||
|
||||
function ondeflateappend(sending, array) {
|
||||
if (sending)
|
||||
crc32.append(array);
|
||||
}
|
||||
|
||||
function ondeflateend(outputSize) {
|
||||
onend(outputSize, crc32.get());
|
||||
}
|
||||
|
||||
function onmessage() {
|
||||
worker.removeEventListener(MESSAGE_EVENT, onmessage, false);
|
||||
launchWorkerProcess(worker, reader, writer, 0, reader.size, ondeflateappend, onprogress, ondeflateend, onreaderror, onwriteerror);
|
||||
}
|
||||
|
||||
if (obj.zip.useWebWorkers) {
|
||||
worker = new Worker(obj.zip.workerScriptsPath + DEFLATE_JS);
|
||||
worker.addEventListener(MESSAGE_EVENT, onmessage, false);
|
||||
worker.postMessage({
|
||||
init : true,
|
||||
level : level
|
||||
});
|
||||
} else
|
||||
launchProcess(new obj.zip.Deflater(), reader, writer, 0, reader.size, ondeflateappend, onprogress, ondeflateend, onreaderror, onwriteerror);
|
||||
return worker;
|
||||
}
|
||||
|
||||
function copy(reader, writer, offset, size, computeCrc32, onend, onprogress, onreaderror, onwriteerror) {
|
||||
var chunkIndex = 0, crc32 = new Crc32();
|
||||
|
||||
function step() {
|
||||
var index = chunkIndex * CHUNK_SIZE;
|
||||
if (index < size)
|
||||
reader.readUint8Array(offset + index, Math.min(CHUNK_SIZE, size - index), function(array) {
|
||||
if (computeCrc32)
|
||||
crc32.append(array);
|
||||
if (onprogress)
|
||||
onprogress(index, size, array);
|
||||
writer.writeUint8Array(array, function() {
|
||||
chunkIndex++;
|
||||
step();
|
||||
}, onwriteerror);
|
||||
}, onreaderror);
|
||||
else
|
||||
onend(size, crc32.get());
|
||||
}
|
||||
|
||||
step();
|
||||
}
|
||||
|
||||
// ZipReader
|
||||
|
||||
function decodeASCII(str) {
|
||||
var i, out = "", charCode, extendedASCII = [ '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB',
|
||||
'\u00E8', '\u00EF', '\u00EE', '\u00EC', '\u00C4', '\u00C5', '\u00C9', '\u00E6', '\u00C6', '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9',
|
||||
'\u00FF', '\u00D6', '\u00DC', '\u00F8', '\u00A3', '\u00D8', '\u00D7', '\u0192', '\u00E1', '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1',
|
||||
'\u00AA', '\u00BA', '\u00BF', '\u00AE', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', '\u00BB', '_', '_', '_', '\u00A6', '\u00A6',
|
||||
'\u00C1', '\u00C2', '\u00C0', '\u00A9', '\u00A6', '\u00A6', '+', '+', '\u00A2', '\u00A5', '+', '+', '-', '-', '+', '-', '+', '\u00E3',
|
||||
'\u00C3', '+', '+', '-', '-', '\u00A6', '-', '+', '\u00A4', '\u00F0', '\u00D0', '\u00CA', '\u00CB', '\u00C8', 'i', '\u00CD', '\u00CE',
|
||||
'\u00CF', '+', '+', '_', '_', '\u00A6', '\u00CC', '_', '\u00D3', '\u00DF', '\u00D4', '\u00D2', '\u00F5', '\u00D5', '\u00B5', '\u00FE',
|
||||
'\u00DE', '\u00DA', '\u00DB', '\u00D9', '\u00FD', '\u00DD', '\u00AF', '\u00B4', '\u00AD', '\u00B1', '_', '\u00BE', '\u00B6', '\u00A7',
|
||||
'\u00F7', '\u00B8', '\u00B0', '\u00A8', '\u00B7', '\u00B9', '\u00B3', '\u00B2', '_', ' ' ];
|
||||
for (i = 0; i < str.length; i++) {
|
||||
charCode = str.charCodeAt(i) & 0xFF;
|
||||
if (charCode > 127)
|
||||
out += extendedASCII[charCode - 128];
|
||||
else
|
||||
out += String.fromCharCode(charCode);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
function decodeUTF8(string) {
|
||||
return decodeURIComponent(escape(string));
|
||||
}
|
||||
|
||||
function getString(bytes) {
|
||||
var i, str = "";
|
||||
for (i = 0; i < bytes.length; i++)
|
||||
str += String.fromCharCode(bytes[i]);
|
||||
return str;
|
||||
}
|
||||
|
||||
function getDate(timeRaw) {
|
||||
var date = (timeRaw & 0xffff0000) >> 16, time = timeRaw & 0x0000ffff;
|
||||
try {
|
||||
return new Date(1980 + ((date & 0xFE00) >> 9), ((date & 0x01E0) >> 5) - 1, date & 0x001F, (time & 0xF800) >> 11, (time & 0x07E0) >> 5,
|
||||
(time & 0x001F) * 2, 0);
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
|
||||
function readCommonHeader(entry, data, index, centralDirectory, onerror) {
|
||||
entry.version = data.view.getUint16(index, true);
|
||||
entry.bitFlag = data.view.getUint16(index + 2, true);
|
||||
entry.compressionMethod = data.view.getUint16(index + 4, true);
|
||||
entry.lastModDateRaw = data.view.getUint32(index + 6, true);
|
||||
entry.lastModDate = getDate(entry.lastModDateRaw);
|
||||
if ((entry.bitFlag & 0x01) === 0x01) {
|
||||
onerror(ERR_ENCRYPTED);
|
||||
return;
|
||||
}
|
||||
if (centralDirectory || (entry.bitFlag & 0x0008) != 0x0008) {
|
||||
entry.crc32 = data.view.getUint32(index + 10, true);
|
||||
entry.compressedSize = data.view.getUint32(index + 14, true);
|
||||
entry.uncompressedSize = data.view.getUint32(index + 18, true);
|
||||
}
|
||||
if (entry.compressedSize === 0xFFFFFFFF || entry.uncompressedSize === 0xFFFFFFFF) {
|
||||
onerror(ERR_ZIP64);
|
||||
return;
|
||||
}
|
||||
entry.filenameLength = data.view.getUint16(index + 22, true);
|
||||
entry.extraFieldLength = data.view.getUint16(index + 24, true);
|
||||
}
|
||||
|
||||
function createZipReader(reader, onerror) {
|
||||
function Entry() {
|
||||
}
|
||||
|
||||
Entry.prototype.getData = function(writer, onend, onprogress, checkCrc32) {
|
||||
var that = this, worker;
|
||||
|
||||
function terminate(callback, param) {
|
||||
if (worker)
|
||||
worker.terminate();
|
||||
worker = null;
|
||||
if (callback)
|
||||
callback(param);
|
||||
}
|
||||
|
||||
function testCrc32(crc32) {
|
||||
var dataCrc32 = getDataHelper(4);
|
||||
dataCrc32.view.setUint32(0, crc32);
|
||||
return that.crc32 == dataCrc32.view.getUint32(0);
|
||||
}
|
||||
|
||||
function getWriterData(uncompressedSize, crc32) {
|
||||
if (checkCrc32 && !testCrc32(crc32))
|
||||
onreaderror();
|
||||
else
|
||||
writer.getData(function(data) {
|
||||
terminate(onend, data);
|
||||
});
|
||||
}
|
||||
|
||||
function onreaderror() {
|
||||
terminate(onerror, ERR_READ_DATA);
|
||||
}
|
||||
|
||||
function onwriteerror() {
|
||||
terminate(onerror, ERR_WRITE_DATA);
|
||||
}
|
||||
|
||||
reader.readUint8Array(that.offset, 30, function(bytes) {
|
||||
var data = getDataHelper(bytes.length, bytes), dataOffset;
|
||||
if (data.view.getUint32(0) != 0x504b0304) {
|
||||
onerror(ERR_BAD_FORMAT);
|
||||
return;
|
||||
}
|
||||
readCommonHeader(that, data, 4, false, onerror);
|
||||
dataOffset = that.offset + 30 + that.filenameLength + that.extraFieldLength;
|
||||
writer.init(function() {
|
||||
if (that.compressionMethod === 0)
|
||||
copy(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
|
||||
else
|
||||
worker = inflate(reader, writer, dataOffset, that.compressedSize, checkCrc32, getWriterData, onprogress, onreaderror, onwriteerror);
|
||||
}, onwriteerror);
|
||||
}, onreaderror);
|
||||
};
|
||||
|
||||
function seekEOCDR(offset, entriesCallback) {
|
||||
reader.readUint8Array(reader.size - offset, offset, function(bytes) {
|
||||
var dataView = getDataHelper(bytes.length, bytes).view;
|
||||
if (dataView.getUint32(0) != 0x504b0506) {
|
||||
seekEOCDR(offset + 1, entriesCallback);
|
||||
} else {
|
||||
entriesCallback(dataView);
|
||||
}
|
||||
}, function() {
|
||||
onerror(ERR_READ);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
getEntries : function(callback) {
|
||||
if (reader.size < 22) {
|
||||
onerror(ERR_BAD_FORMAT);
|
||||
return;
|
||||
}
|
||||
// look for End of central directory record
|
||||
seekEOCDR(22, function(dataView) {
|
||||
var datalength, fileslength;
|
||||
datalength = dataView.getUint32(16, true);
|
||||
fileslength = dataView.getUint16(8, true);
|
||||
reader.readUint8Array(datalength, reader.size - datalength, function(bytes) {
|
||||
var i, index = 0, entries = [], entry, filename, comment, data = getDataHelper(bytes.length, bytes);
|
||||
for (i = 0; i < fileslength; i++) {
|
||||
entry = new Entry();
|
||||
if (data.view.getUint32(index) != 0x504b0102) {
|
||||
onerror(ERR_BAD_FORMAT);
|
||||
return;
|
||||
}
|
||||
readCommonHeader(entry, data, index + 6, true, onerror);
|
||||
entry.commentLength = data.view.getUint16(index + 32, true);
|
||||
entry.directory = ((data.view.getUint8(index + 38) & 0x10) == 0x10);
|
||||
entry.offset = data.view.getUint32(index + 42, true);
|
||||
filename = getString(data.array.subarray(index + 46, index + 46 + entry.filenameLength));
|
||||
entry.filename = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(filename) : decodeASCII(filename);
|
||||
if (!entry.directory && entry.filename.charAt(entry.filename.length - 1) == "/")
|
||||
entry.directory = true;
|
||||
comment = getString(data.array.subarray(index + 46 + entry.filenameLength + entry.extraFieldLength, index + 46
|
||||
+ entry.filenameLength + entry.extraFieldLength + entry.commentLength));
|
||||
entry.comment = ((entry.bitFlag & 0x0800) === 0x0800) ? decodeUTF8(comment) : decodeASCII(comment);
|
||||
entries.push(entry);
|
||||
index += 46 + entry.filenameLength + entry.extraFieldLength + entry.commentLength;
|
||||
}
|
||||
callback(entries);
|
||||
}, function() {
|
||||
onerror(ERR_READ);
|
||||
});
|
||||
});
|
||||
},
|
||||
close : function(callback) {
|
||||
if (callback)
|
||||
callback();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// ZipWriter
|
||||
|
||||
function encodeUTF8(string) {
|
||||
return unescape(encodeURIComponent(string));
|
||||
}
|
||||
|
||||
function getBytes(str) {
|
||||
var i, array = [];
|
||||
for (i = 0; i < str.length; i++)
|
||||
array.push(str.charCodeAt(i));
|
||||
return array;
|
||||
}
|
||||
|
||||
function createZipWriter(writer, onerror, dontDeflate) {
|
||||
var worker, files = {}, filenames = [], datalength = 0;
|
||||
|
||||
function terminate(callback, message) {
|
||||
if (worker)
|
||||
worker.terminate();
|
||||
worker = null;
|
||||
if (callback)
|
||||
callback(message);
|
||||
}
|
||||
|
||||
function onwriteerror() {
|
||||
terminate(onerror, ERR_WRITE);
|
||||
}
|
||||
|
||||
function onreaderror() {
|
||||
terminate(onerror, ERR_READ_DATA);
|
||||
}
|
||||
|
||||
return {
|
||||
add : function(name, reader, onend, onprogress, options) {
|
||||
var header, filename, date;
|
||||
|
||||
function writeHeader(callback) {
|
||||
var data;
|
||||
date = options.lastModDate || new Date();
|
||||
header = getDataHelper(26);
|
||||
files[name] = {
|
||||
headerArray : header.array,
|
||||
directory : options.directory,
|
||||
filename : filename,
|
||||
offset : datalength,
|
||||
comment : getBytes(encodeUTF8(options.comment || ""))
|
||||
};
|
||||
header.view.setUint32(0, 0x14000808);
|
||||
if (options.version)
|
||||
header.view.setUint8(0, options.version);
|
||||
if (!dontDeflate && options.level !== 0 && !options.directory)
|
||||
header.view.setUint16(4, 0x0800);
|
||||
header.view.setUint16(6, (((date.getHours() << 6) | date.getMinutes()) << 5) | date.getSeconds() / 2, true);
|
||||
header.view.setUint16(8, ((((date.getFullYear() - 1980) << 4) | (date.getMonth() + 1)) << 5) | date.getDate(), true);
|
||||
header.view.setUint16(22, filename.length, true);
|
||||
data = getDataHelper(30 + filename.length);
|
||||
data.view.setUint32(0, 0x504b0304);
|
||||
data.array.set(header.array, 4);
|
||||
data.array.set(filename, 30);
|
||||
datalength += data.array.length;
|
||||
writer.writeUint8Array(data.array, callback, onwriteerror);
|
||||
}
|
||||
|
||||
function writeFooter(compressedLength, crc32) {
|
||||
var footer = getDataHelper(16);
|
||||
datalength += compressedLength || 0;
|
||||
footer.view.setUint32(0, 0x504b0708);
|
||||
if (typeof crc32 != "undefined") {
|
||||
header.view.setUint32(10, crc32, true);
|
||||
footer.view.setUint32(4, crc32, true);
|
||||
}
|
||||
if (reader) {
|
||||
footer.view.setUint32(8, compressedLength, true);
|
||||
header.view.setUint32(14, compressedLength, true);
|
||||
footer.view.setUint32(12, reader.size, true);
|
||||
header.view.setUint32(18, reader.size, true);
|
||||
}
|
||||
writer.writeUint8Array(footer.array, function() {
|
||||
datalength += 16;
|
||||
terminate(onend);
|
||||
}, onwriteerror);
|
||||
}
|
||||
|
||||
function writeFile() {
|
||||
options = options || {};
|
||||
name = name.trim();
|
||||
if (options.directory && name.charAt(name.length - 1) != "/")
|
||||
name += "/";
|
||||
if (files.hasOwnProperty(name)) {
|
||||
onerror(ERR_DUPLICATED_NAME);
|
||||
return;
|
||||
}
|
||||
filename = getBytes(encodeUTF8(name));
|
||||
filenames.push(name);
|
||||
writeHeader(function() {
|
||||
if (reader)
|
||||
if (dontDeflate || options.level === 0)
|
||||
copy(reader, writer, 0, reader.size, true, writeFooter, onprogress, onreaderror, onwriteerror);
|
||||
else
|
||||
worker = deflate(reader, writer, options.level, writeFooter, onprogress, onreaderror, onwriteerror);
|
||||
else
|
||||
writeFooter();
|
||||
}, onwriteerror);
|
||||
}
|
||||
|
||||
if (reader)
|
||||
reader.init(writeFile, onreaderror);
|
||||
else
|
||||
writeFile();
|
||||
},
|
||||
close : function(callback) {
|
||||
var data, length = 0, index = 0, indexFilename, file;
|
||||
for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
|
||||
file = files[filenames[indexFilename]];
|
||||
length += 46 + file.filename.length + file.comment.length;
|
||||
}
|
||||
data = getDataHelper(length + 22);
|
||||
for (indexFilename = 0; indexFilename < filenames.length; indexFilename++) {
|
||||
file = files[filenames[indexFilename]];
|
||||
data.view.setUint32(index, 0x504b0102);
|
||||
data.view.setUint16(index + 4, 0x1400);
|
||||
data.array.set(file.headerArray, index + 6);
|
||||
data.view.setUint16(index + 32, file.comment.length, true);
|
||||
if (file.directory)
|
||||
data.view.setUint8(index + 38, 0x10);
|
||||
data.view.setUint32(index + 42, file.offset, true);
|
||||
data.array.set(file.filename, index + 46);
|
||||
data.array.set(file.comment, index + 46 + file.filename.length);
|
||||
index += 46 + file.filename.length + file.comment.length;
|
||||
}
|
||||
data.view.setUint32(index, 0x504b0506);
|
||||
data.view.setUint16(index + 8, filenames.length, true);
|
||||
data.view.setUint16(index + 10, filenames.length, true);
|
||||
data.view.setUint32(index + 12, length, true);
|
||||
data.view.setUint32(index + 16, datalength, true);
|
||||
writer.writeUint8Array(data.array, function() {
|
||||
terminate(function() {
|
||||
writer.getData(callback);
|
||||
});
|
||||
}, onwriteerror);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
obj.zip = {
|
||||
Reader : Reader,
|
||||
Writer : Writer,
|
||||
BlobReader : BlobReader,
|
||||
Data64URIReader : Data64URIReader,
|
||||
TextReader : TextReader,
|
||||
BlobWriter : BlobWriter,
|
||||
Data64URIWriter : Data64URIWriter,
|
||||
TextWriter : TextWriter,
|
||||
createReader : function(reader, callback, onerror) {
|
||||
reader.init(function() {
|
||||
callback(createZipReader(reader, onerror));
|
||||
}, onerror);
|
||||
},
|
||||
createWriter : function(writer, callback, onerror, dontDeflate) {
|
||||
writer.init(function() {
|
||||
callback(createZipWriter(writer, onerror, dontDeflate));
|
||||
}, onerror);
|
||||
},
|
||||
workerScriptsPath : "",
|
||||
useWebWorkers : true
|
||||
};
|
||||
|
||||
})(this);
|
|
@ -1,85 +0,0 @@
|
|||
var READER = function() {
|
||||
|
||||
var isMobile = navigator.userAgent.match(/Mobi/i);
|
||||
var hasTouch = 'ontouchstart' in document.documentElement;
|
||||
|
||||
var sharingToken = null;
|
||||
|
||||
function hideReader() {
|
||||
FileList.setViewerMode(false);
|
||||
$("#controls").show();
|
||||
$('#app-content #controls').removeClass('hidden');
|
||||
$('iframe').remove();
|
||||
}
|
||||
|
||||
function hideControls() {
|
||||
$('#app-content #controls').hide();
|
||||
}
|
||||
|
||||
function showReader(dir, filename, share) {
|
||||
if (!showReader.shown) {
|
||||
if (share === 'undefined')
|
||||
share = '';
|
||||
var viewer = OC.linkTo('files_reader', 'viewer.php') + '?dir=' + encodeURIComponent(dir).replace(/%2F/g, '/') + '&file=' + encodeURIComponent(filename.replace('&', '%26')) + '&share=' + encodeURIComponent(share);
|
||||
if (isMobile || hasTouch)
|
||||
window.open(viewer, dir + '/' + filename);
|
||||
else {
|
||||
$iframe = '<iframe style="width:100%;height:100%;display:block;position:absolute;top:0;" src="' + viewer + '" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" sandbox="allow-scripts allow-same-origin"/>';
|
||||
if ($('#isPublic').val()) {
|
||||
// force the preview to adjust its height
|
||||
$('#preview').append($iframe).css({
|
||||
height: '100%'
|
||||
});
|
||||
$('body').css({
|
||||
height: '100%'
|
||||
});
|
||||
$('footer').addClass('hidden');
|
||||
$('#imgframe').addClass('hidden');
|
||||
$('.directLink').addClass('hidden');
|
||||
$('.directDownload').addClass('hidden');
|
||||
$('#controls').addClass('hidden');
|
||||
} else {
|
||||
FileList.setViewerMode(true);
|
||||
$('#app-content').append($iframe);
|
||||
}
|
||||
|
||||
// replace the controls with our own
|
||||
hideControls();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openReader(filename) {
|
||||
if ($('#isPublic').val()) {
|
||||
showReader(FileList.getCurrentDirectory(), filename, sharingToken);
|
||||
} else {
|
||||
showReader(FileList.getCurrentDirectory(), filename, '');
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
if (!$.browser.msie) { //doesn't work on IE
|
||||
sharingToken = $('#sharingToken').val();
|
||||
|
||||
// Logged view
|
||||
if ($('#filesApp').val() && typeof FileActions !== 'undefined') {
|
||||
OCA.Files.fileActions.register('application/epub+zip', 'Edit', OC.PERMISSION_READ, '', openReader);
|
||||
FileActions.setDefault('application/epub+zip', 'Edit');
|
||||
}
|
||||
|
||||
// Publicly shared view
|
||||
if ($('#isPublic').val()) {
|
||||
if ($('#mimetype').val() === 'application/epub+zip') {
|
||||
showReader('', '', sharingToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
hideReader: hideReader,
|
||||
hideControls: hideControls,
|
||||
showReader: showReader
|
||||
}
|
||||
|
||||
}();
|
124
files_reader/js/plugin.js
Normal file
124
files_reader/js/plugin.js
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Frank de Lange
|
||||
* Copyright (c) 2013-2014 Lukas Reschke <lukas@owncloud.com>
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3
|
||||
* or later.
|
||||
*
|
||||
* See the COPYING-README file.
|
||||
*
|
||||
*/
|
||||
|
||||
(function(OCA) {
|
||||
|
||||
OCA.FilesReader = OCA.FilesReader || {};
|
||||
|
||||
var isMobile = navigator.userAgent.match(/Mobi/i);
|
||||
var hasTouch = 'ontouchstart' in document.documentElement;
|
||||
|
||||
/**
|
||||
* @namespace OCA.FilesReader.Plugin
|
||||
*/
|
||||
OCA.FilesReader.Plugin = {
|
||||
|
||||
/**
|
||||
* @param fileList
|
||||
*/
|
||||
attach: function(fileList) {
|
||||
this._extendFileActions(fileList.fileActions);
|
||||
},
|
||||
|
||||
hideControls: function() {
|
||||
$('#app-content #controls').hide();
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if ($('#fileList').length) {
|
||||
FileList.setViewerMode(false);
|
||||
}
|
||||
$("#controls").show();
|
||||
$('#app-content #controls').removeClass('hidden');
|
||||
if ($('#isPublic').val()) {
|
||||
$('#imgframe').show();
|
||||
$('footer').show();
|
||||
$('.directLink').show();
|
||||
$('.directDownload').show();
|
||||
}
|
||||
$('iframe').remove();
|
||||
},
|
||||
|
||||
/**
|
||||
* @param downloadUrl
|
||||
* @param isFileList
|
||||
*/
|
||||
show: function(downloadUrl, isFileList) {
|
||||
var self = this;
|
||||
var $iframe;
|
||||
var viewer = OC.generateUrl('/apps/files_reader/?file={file}', {file: encodeURIComponent(downloadUrl)});
|
||||
// launch in new window on mobile and touch devices...
|
||||
if (isMobile || hasTouch) {
|
||||
window.open(viewer, downloadUrl);
|
||||
} else {
|
||||
$iframe = '<iframe style="width:100%;height:100%;display:block;position:absolute;top:0;" src="' + viewer + '" allowfullscreen="true" webkitallowfullscreen="true" mozallowfullscreen="true" sandbox="allow-scripts allow-same-origin"/>';
|
||||
if (isFileList === true) {
|
||||
FileList.setViewerMode(true);
|
||||
}
|
||||
if ($('#isPublic').val()) {
|
||||
// force the preview to adjust its height
|
||||
$('#preview').append($iframe).css({ height: '100%' });
|
||||
$('body').css({ height: '100%' });
|
||||
$('footer').addClass('hidden');
|
||||
$('#imgframe').addClass('hidden');
|
||||
$('.directLink').addClass('hidden');
|
||||
$('.directDownload').addClass('hidden');
|
||||
$('#controls').addClass('hidden');
|
||||
} else {
|
||||
$('#app-content').append($iframe);
|
||||
self.hideControls();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @param fileActions
|
||||
* @private
|
||||
*/
|
||||
_extendFileActions: function(fileActions) {
|
||||
var self = this;
|
||||
fileActions.registerAction({
|
||||
name: 'view',
|
||||
displayName: 'Favorite',
|
||||
mime: 'application/epub+zip',
|
||||
permissions: OC.PERMISSION_READ,
|
||||
actionHandler: function(fileName, context) {
|
||||
var downloadUrl = '';
|
||||
if($('#isPublic').val()) {
|
||||
var sharingToken = $('#sharingToken').val();
|
||||
downloadUrl = OC.generateUrl('/s/{token}/download?files={files}&path={path}', {
|
||||
token: encodeURIComponent(sharingToken),
|
||||
files: encodeURIComponent(fileName),
|
||||
path: encodeURIComponent(context.dir)
|
||||
});
|
||||
} else {
|
||||
downloadUrl = Files.getDownloadUrl(fileName, context.dir);
|
||||
}
|
||||
self.show(downloadUrl, true);
|
||||
}
|
||||
});
|
||||
fileActions.setDefault('application/epub+zip', 'view');
|
||||
}
|
||||
};
|
||||
|
||||
})(OCA);
|
||||
|
||||
OC.Plugins.register('OCA.Files.FileList', OCA.FilesReader.Plugin);
|
||||
|
||||
// FIXME: Hack for single public file view since it is not attached to the fileslist
|
||||
$(document).ready(function(){
|
||||
if ($('#isPublic').val() && $('#mimetype').val() === 'application/epub+zip') {
|
||||
var sharingToken = $('#sharingToken').val();
|
||||
var downloadUrl = OC.generateUrl('/s/{token}/download', {token: encodeURIComponent(sharingToken)});
|
||||
var viewer = OCA.FilesReader.Plugin;
|
||||
viewer.show(downloadUrl, false);
|
||||
}
|
||||
});
|
File diff suppressed because it is too large
Load diff
2
files_reader/js/reader.min.js
vendored
2
files_reader/js/reader.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -42,12 +42,10 @@ function delCSSRule(sheet, selector) {
|
|||
|
||||
document.onreadystatechange = function () {
|
||||
if (document.readyState == "complete") {
|
||||
// enable (large-screen) or hide (mobile/small-screen) close button
|
||||
if (parent.READER == undefined) {
|
||||
$('#close').hide();
|
||||
} else {
|
||||
$('#close').on('click', function() { reader.book.destroy(); parent.READER.hideReader(); });
|
||||
parent.READER.hideControls();
|
||||
// only enable close button when launched in an iframe
|
||||
if (parent !== window) {
|
||||
$('#close').show();
|
||||
$('#close').on('click', function() { reader.book.destroy(); parent.OCA.FilesReader.Plugin.hide(); });
|
||||
}
|
||||
|
||||
// some parameters...
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
<?php
|
||||
/** @var array $_ */
|
||||
/** @var OCP\IURLGenerator $urlGenerator */
|
||||
$urlGenerator = $_['urlGenerator'];
|
||||
$version = \OCP\App::getAppVersion('files_reader');
|
||||
$dllink = isset($_GET['file']) ? $_GET['file'] : '';
|
||||
?>
|
||||
|
||||
<html dir="ltr">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<base href="<?php print_unescaped($_['base']);?>">
|
||||
<base href="<?php p($urlGenerator->linkTo('files_reader',''));?>">
|
||||
<title>
|
||||
<?php p($_['title']);?>
|
||||
</title>
|
||||
|
@ -12,20 +20,33 @@
|
|||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="css/popup.css">
|
||||
<link rel="stylesheet" href="css/tooltip.css">
|
||||
<!--
|
||||
<script type="text/javascript" src="js/libs/jquery-2.1.0.min.js"> </script>
|
||||
<script type="text/javascript" src="js/libs/jquery.highlight.js"> </script>
|
||||
<script type="text/javascript" src="js/libs/screenfull.min.js"> </script>
|
||||
<script type="text/javascript" src="js/libs/typedarray.min.js"> </script>
|
||||
<script type="text/javascript" src="js/libs/blob.js"> </script>
|
||||
<script type="text/javascript" src="js/libs/zip.min.js"> </script>
|
||||
<script type="text/javascript" src="js/ready.js"> </script>
|
||||
<script type="text/javascript" src="js/epub.min.js"> </script>
|
||||
<script type="text/javascript" src="js/hooks.min.js"> </script>
|
||||
<script type="text/javascript" src="js/hooks/extensions/highlight.js"> </script>
|
||||
<script type="text/javascript" src="js/reader.min.js"> </script>
|
||||
-->
|
||||
<script type="text/javascript" src="js/lib/typedarray.min.js"> </script>
|
||||
<script type="text/javascript" src="js/lib/Blob.js"> </script>
|
||||
<script type="text/javascript" src="vendor/epubjs/libs/jquery-2.1.0.min.js"> </script>
|
||||
<script type="text/javascript" src="vendor/epubjs/libs/jquery.highlight.js"> </script>
|
||||
<script type="text/javascript" src="vendor/epubjs/libs/screenfull.min.js"> </script>
|
||||
<script type="text/javascript" src="vendor/epubjs/libs/zip.min.js"> </script>
|
||||
<script type="text/javascript" src="vendor/epubjs/epub.min.js"> </script>
|
||||
<script type="text/javascript" src="vendor/epubjs/hooks.min.js"> </script>
|
||||
<script type="text/javascript" src="vendor/epubjs/hooks/extensions/highlight.js"> </script>
|
||||
<script type="text/javascript" src="vendor/epubjs/reader.min.js"> </script>
|
||||
|
||||
<script type="text/javascript" src="js/ready.js"> </script>
|
||||
</head>
|
||||
<body>
|
||||
<input type="hidden" id="dllink" value="<?php print_unescaped($_['dllink']);?>">
|
||||
<input type="hidden" id="dllink" value="<?php print_unescaped($dllink);?>">
|
||||
<div id="outerContainer">
|
||||
<div id="sidebar">
|
||||
<div id="panels">
|
||||
|
@ -91,7 +112,7 @@
|
|||
<a id="fullscreen" class="icon-resize-full">
|
||||
<?php p($l->t("Fullscreen")); ?>
|
||||
</a>
|
||||
<a id="close" class="icon-cancel-circled2">
|
||||
<a id="close" class="icon-cancel-circled2" style="display:none">
|
||||
<?php p($l->t("Close")); ?>
|
||||
</a>
|
||||
</div>
|
||||
|
|
|
@ -2185,7 +2185,7 @@ global.RSVP = requireModule('rsvp');
|
|||
'use strict';
|
||||
|
||||
var EPUBJS = EPUBJS || {};
|
||||
EPUBJS.VERSION = "0.2.4";
|
||||
EPUBJS.VERSION = "0.2.5";
|
||||
|
||||
EPUBJS.plugins = EPUBJS.plugins || {};
|
||||
|
||||
|
@ -4372,8 +4372,14 @@ EPUBJS.EpubCFI.prototype.generateCfiFromElement = function(element, chapter) {
|
|||
// Start of Chapter
|
||||
return "epubcfi(" + chapter + "!/4/)";
|
||||
} else {
|
||||
var offset = "";
|
||||
var embeddedElements = ["audio", "canvas", "embed", "iframe", "img", "math", "object", "svg", "video"];
|
||||
if (embeddedElements.indexOf(element.tagName.toLowerCase()) === -1) {
|
||||
// if the element could contain text, set the character offset;
|
||||
offset += "/1:0";
|
||||
}
|
||||
// First Text Node
|
||||
return "epubcfi(" + chapter + "!" + path + "/1:0)";
|
||||
return "epubcfi(" + chapter + "!" + path + offset + ")";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5115,7 +5121,7 @@ EPUBJS.Layout.Fixed = function(){
|
|||
|
||||
EPUBJS.Layout.Fixed.prototype.format = function(documentElement, _width, _height, _gap){
|
||||
var columnWidth = EPUBJS.core.prefixed('columnWidth');
|
||||
var viewport = documentElement.querySelector("[name=viewport");
|
||||
var viewport = documentElement.querySelector("[name=viewport]");
|
||||
var content;
|
||||
var contents;
|
||||
var width, height;
|
||||
|
@ -5880,7 +5886,13 @@ EPUBJS.Render.Iframe.prototype.setLeft = function(leftPos){
|
|||
// this.bodyEl.style.marginLeft = -leftPos + "px";
|
||||
// this.docEl.style.marginLeft = -leftPos + "px";
|
||||
// this.docEl.style[EPUBJS.Render.Iframe.transform] = 'translate('+ (-leftPos) + 'px, 0)';
|
||||
this.document.defaultView.scrollTo(leftPos, 0);
|
||||
|
||||
if (navigator.userAgent.match(/(iPad|iPhone|iPod|Mobile|Android)/g)) {
|
||||
this.docEl.style["-webkit-transform"] = 'translate('+ (-leftPos) + 'px, 0)';
|
||||
} else {
|
||||
this.document.defaultView.scrollTo(leftPos, 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
EPUBJS.Render.Iframe.prototype.setStyle = function(style, val, prefixed){
|
||||
|
@ -6473,6 +6485,15 @@ EPUBJS.Renderer.prototype.firstElementisTextNode = function(node) {
|
|||
return false;
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.isGoodNode = function(node) {
|
||||
var embeddedElements = ["audio", "canvas", "embed", "iframe", "img", "math", "object", "svg", "video"];
|
||||
if (embeddedElements.indexOf(node.tagName.toLowerCase()) !== -1) {
|
||||
// Embedded elements usually do not have a text node as first element, but are also good nodes
|
||||
return true;
|
||||
}
|
||||
return this.firstElementisTextNode(node);
|
||||
};
|
||||
|
||||
// Walk the node tree from a start element to next visible element
|
||||
EPUBJS.Renderer.prototype.walk = function(node, x, y) {
|
||||
var r, children, leng,
|
||||
|
@ -6484,7 +6505,7 @@ EPUBJS.Renderer.prototype.walk = function(node, x, y) {
|
|||
|
||||
while(!r && stack.length) {
|
||||
node = stack.shift();
|
||||
if( this.containsPoint(node, x, y) && this.firstElementisTextNode(node)) {
|
||||
if( this.containsPoint(node, x, y) && this.isGoodNode(node)) {
|
||||
r = node;
|
||||
}
|
||||
|
||||
|
@ -7343,9 +7364,15 @@ EPUBJS.replace.links = function(_store, full, done, link){
|
|||
setTimeout(function(){
|
||||
done(url, full);
|
||||
}, 5); //-- Allow for css to apply before displaying chapter
|
||||
}, function(reason) {
|
||||
// we were unable to replace the style sheets
|
||||
done(null);
|
||||
});
|
||||
}else{
|
||||
_store.getUrl(full).then(done);
|
||||
_store.getUrl(full).then(done, function(reason) {
|
||||
// we were unable to get the url, signal to upper layer
|
||||
done(null);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7365,10 +7392,12 @@ EPUBJS.replace.stylesheets = function(_store, full) {
|
|||
|
||||
deferred.resolve(url);
|
||||
|
||||
}, function(e) {
|
||||
console.error(e);
|
||||
}, function(reason) {
|
||||
deferred.reject(reason);
|
||||
});
|
||||
|
||||
}, function(reason) {
|
||||
deferred.reject(reason);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
|
@ -7389,8 +7418,10 @@ EPUBJS.replace.cssUrls = function(_store, base, text){
|
|||
matches.forEach(function(str){
|
||||
var full = EPUBJS.core.resolveUrl(base, str.replace(/url\(|[|\)|\'|\"]/g, ''));
|
||||
var replaced = _store.getUrl(full).then(function(url){
|
||||
text = text.replace(str, 'url("'+url+'")');
|
||||
});
|
||||
text = text.replace(str, 'url("'+url+'")');
|
||||
}, function(reason) {
|
||||
deferred.reject(reason);
|
||||
});
|
||||
|
||||
promises.push(replaced);
|
||||
});
|
||||
|
@ -7472,7 +7503,10 @@ EPUBJS.Unarchiver.prototype.getText = function(url, encoding){
|
|||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
|
||||
if(!entry) {
|
||||
console.warn("File not found in the contained epub:", url);
|
||||
deferred.reject({
|
||||
message : "File not found in the epub: " + url,
|
||||
stack : new Error().stack
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
1
files_reader/vendor/epubjs/epub.js.map
vendored
Normal file
1
files_reader/vendor/epubjs/epub.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -2185,7 +2185,7 @@ global.RSVP = requireModule('rsvp');
|
|||
'use strict';
|
||||
|
||||
var EPUBJS = EPUBJS || {};
|
||||
EPUBJS.VERSION = "0.2.4";
|
||||
EPUBJS.VERSION = "0.2.5";
|
||||
|
||||
EPUBJS.plugins = EPUBJS.plugins || {};
|
||||
|
||||
|
@ -4372,8 +4372,14 @@ EPUBJS.EpubCFI.prototype.generateCfiFromElement = function(element, chapter) {
|
|||
// Start of Chapter
|
||||
return "epubcfi(" + chapter + "!/4/)";
|
||||
} else {
|
||||
var offset = "";
|
||||
var embeddedElements = ["audio", "canvas", "embed", "iframe", "img", "math", "object", "svg", "video"];
|
||||
if (embeddedElements.indexOf(element.tagName.toLowerCase()) === -1) {
|
||||
// if the element could contain text, set the character offset;
|
||||
offset += "/1:0";
|
||||
}
|
||||
// First Text Node
|
||||
return "epubcfi(" + chapter + "!" + path + "/1:0)";
|
||||
return "epubcfi(" + chapter + "!" + path + offset + ")";
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5115,7 +5121,7 @@ EPUBJS.Layout.Fixed = function(){
|
|||
|
||||
EPUBJS.Layout.Fixed.prototype.format = function(documentElement, _width, _height, _gap){
|
||||
var columnWidth = EPUBJS.core.prefixed('columnWidth');
|
||||
var viewport = documentElement.querySelector("[name=viewport");
|
||||
var viewport = documentElement.querySelector("[name=viewport]");
|
||||
var content;
|
||||
var contents;
|
||||
var width, height;
|
||||
|
@ -5880,7 +5886,13 @@ EPUBJS.Render.Iframe.prototype.setLeft = function(leftPos){
|
|||
// this.bodyEl.style.marginLeft = -leftPos + "px";
|
||||
// this.docEl.style.marginLeft = -leftPos + "px";
|
||||
// this.docEl.style[EPUBJS.Render.Iframe.transform] = 'translate('+ (-leftPos) + 'px, 0)';
|
||||
this.document.defaultView.scrollTo(leftPos, 0);
|
||||
|
||||
if (navigator.userAgent.match(/(iPad|iPhone|iPod|Mobile|Android)/g)) {
|
||||
this.docEl.style["-webkit-transform"] = 'translate('+ (-leftPos) + 'px, 0)';
|
||||
} else {
|
||||
this.document.defaultView.scrollTo(leftPos, 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
EPUBJS.Render.Iframe.prototype.setStyle = function(style, val, prefixed){
|
||||
|
@ -6473,6 +6485,15 @@ EPUBJS.Renderer.prototype.firstElementisTextNode = function(node) {
|
|||
return false;
|
||||
};
|
||||
|
||||
EPUBJS.Renderer.prototype.isGoodNode = function(node) {
|
||||
var embeddedElements = ["audio", "canvas", "embed", "iframe", "img", "math", "object", "svg", "video"];
|
||||
if (embeddedElements.indexOf(node.tagName.toLowerCase()) !== -1) {
|
||||
// Embedded elements usually do not have a text node as first element, but are also good nodes
|
||||
return true;
|
||||
}
|
||||
return this.firstElementisTextNode(node);
|
||||
};
|
||||
|
||||
// Walk the node tree from a start element to next visible element
|
||||
EPUBJS.Renderer.prototype.walk = function(node, x, y) {
|
||||
var r, children, leng,
|
||||
|
@ -6484,7 +6505,7 @@ EPUBJS.Renderer.prototype.walk = function(node, x, y) {
|
|||
|
||||
while(!r && stack.length) {
|
||||
node = stack.shift();
|
||||
if( this.containsPoint(node, x, y) && this.firstElementisTextNode(node)) {
|
||||
if( this.containsPoint(node, x, y) && this.isGoodNode(node)) {
|
||||
r = node;
|
||||
}
|
||||
|
||||
|
@ -7343,9 +7364,15 @@ EPUBJS.replace.links = function(_store, full, done, link){
|
|||
setTimeout(function(){
|
||||
done(url, full);
|
||||
}, 5); //-- Allow for css to apply before displaying chapter
|
||||
}, function(reason) {
|
||||
// we were unable to replace the style sheets
|
||||
done(null);
|
||||
});
|
||||
}else{
|
||||
_store.getUrl(full).then(done);
|
||||
_store.getUrl(full).then(done, function(reason) {
|
||||
// we were unable to get the url, signal to upper layer
|
||||
done(null);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7365,10 +7392,12 @@ EPUBJS.replace.stylesheets = function(_store, full) {
|
|||
|
||||
deferred.resolve(url);
|
||||
|
||||
}, function(e) {
|
||||
console.error(e);
|
||||
}, function(reason) {
|
||||
deferred.reject(reason);
|
||||
});
|
||||
|
||||
}, function(reason) {
|
||||
deferred.reject(reason);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
|
@ -7389,8 +7418,10 @@ EPUBJS.replace.cssUrls = function(_store, base, text){
|
|||
matches.forEach(function(str){
|
||||
var full = EPUBJS.core.resolveUrl(base, str.replace(/url\(|[|\)|\'|\"]/g, ''));
|
||||
var replaced = _store.getUrl(full).then(function(url){
|
||||
text = text.replace(str, 'url("'+url+'")');
|
||||
});
|
||||
text = text.replace(str, 'url("'+url+'")');
|
||||
}, function(reason) {
|
||||
deferred.reject(reason);
|
||||
});
|
||||
|
||||
promises.push(replaced);
|
||||
});
|
||||
|
@ -7472,7 +7503,10 @@ EPUBJS.Unarchiver.prototype.getText = function(url, encoding){
|
|||
var _URL = window.URL || window.webkitURL || window.mozURL;
|
||||
|
||||
if(!entry) {
|
||||
console.warn("File not found in the contained epub:", url);
|
||||
deferred.reject({
|
||||
message : "File not found in the epub: " + url,
|
||||
stack : new Error().stack
|
||||
});
|
||||
return deferred.promise;
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
1
files_reader/vendor/epubjs/hooks.min.map
vendored
Normal file
1
files_reader/vendor/epubjs/hooks.min.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,7 +1,7 @@
|
|||
EPUBJS.reader.search = {};
|
||||
|
||||
// Search Server -- https://github.com/futurepress/epubjs-search
|
||||
EPUBJS.reader.search.SERVER = "https://example.com";
|
||||
EPUBJS.reader.search.SERVER = "https://pacific-cliffs-3579.herokuapp.com";
|
||||
|
||||
EPUBJS.reader.search.request = function(q, callback) {
|
||||
var fetch = $.ajax({
|
2
files_reader/vendor/epubjs/reader.min.js
vendored
Normal file
2
files_reader/vendor/epubjs/reader.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
files_reader/vendor/epubjs/reader.min.map
vendored
Normal file
1
files_reader/vendor/epubjs/reader.min.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,27 +0,0 @@
|
|||
<?php
|
||||
|
||||
OCP\App::checkAppEnabled('files_reader');
|
||||
|
||||
$dir = isset($_GET['dir']) ? $_GET['dir'] : '';
|
||||
$file = isset($_GET['file']) ? $_GET['file'] : '';
|
||||
$share = isset($_GET['share']) ? $_GET['share'] : '';
|
||||
|
||||
// TODO: add mime type detection and load the template
|
||||
$mime = "application/zip+epub";
|
||||
|
||||
// download link varies by sharing status, compose it here
|
||||
$dllink = $share === ''
|
||||
// ? OC_Helper::linkTo('files', 'ajax/download.php', array('dir' => urldecode($dir), 'files' => urldecode($file), 'share' => $share ))
|
||||
? OC_Helper::linkTo('files', 'ajax/download.php', array('dir' => $dir, 'files' => $file, 'share' => $share ))
|
||||
: OC_Helper::linkToPublic('files') . '&t=' . rawurlencode($share) . '&download';
|
||||
|
||||
// needed for css/script inclusion
|
||||
$base = OC_Helper::linkTo('files_reader', '');
|
||||
|
||||
$title = htmlentities($file);
|
||||
|
||||
$page = new OCP\Template( 'files_reader', 'reader');
|
||||
$page->assign('title', $title);
|
||||
$page->assign('dllink', $dllink);
|
||||
$page->assign('base', $base);
|
||||
$page->printPage();
|
Loading…
Add table
Add a link
Reference in a new issue