1
0
Fork 0
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:
frankdelange 2015-02-12 20:08:36 +01:00
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

Binary file not shown.

BIN
dist/files_reader-0.6.0.tar.gz vendored Normal file

Binary file not shown.

View file

@ -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>

View file

@ -1,2 +0,0 @@
<?php

View file

@ -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
View 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

View file

@ -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);

View file

@ -35,7 +35,6 @@ class Epub extends Provider {
$cover = $epub->Cover();
if ($cover) {
$image = new \OC_Image();
$image->loadFromData($cover['data']);

View file

@ -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');

View file

@ -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/>

View file

@ -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'],
]];

View 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
View 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
View 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

View file

@ -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

View file

@ -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);
};
}
})();

View file

@ -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";
};
})();

View file

@ -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);

View file

@ -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
View 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

File diff suppressed because one or more lines are too long

View file

@ -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...

View file

@ -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>

View file

@ -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,9 +7418,11 @@ 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

View file

@ -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,9 +7418,11 @@ 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;
}
@ -7528,4 +7562,4 @@ EPUBJS.Unarchiver.prototype.toStorage = function(entries){
// });
// };
//# sourceMappingURL=epub.js.map
//# sourceMappingURL=epub.js.map

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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({

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -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();