mirror of
https://github.com/Yetangitu/owncloud-apps.git
synced 2025-10-03 14:59:19 +02:00
Initial commit
This commit is contained in:
parent
26dd81b2df
commit
993289d86b
51 changed files with 16863 additions and 0 deletions
21
files_opds/ajax/clear_bookshelf.php
Normal file
21
files_opds/ajax/clear_bookshelf.php
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds App
|
||||||
|
*
|
||||||
|
* @author Frank de Lange
|
||||||
|
* @copyright 2014 Frank de Lange
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Opds;
|
||||||
|
|
||||||
|
$l = new \OC_L10N('files_opds');
|
||||||
|
|
||||||
|
\OCP\JSON::checkLoggedIn();
|
||||||
|
\OCP\JSON::callCheck();
|
||||||
|
|
||||||
|
Bookshelf::clear();
|
||||||
|
\OCP\JSON::success(array( "data" => array( "message" => $l->t("Bookshelf cleared"))));
|
46
files_opds/ajax/personal.php
Normal file
46
files_opds/ajax/personal.php
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds App
|
||||||
|
*
|
||||||
|
* @author Frank de Lange
|
||||||
|
* @copyright 2014 Frank de Lange
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Opds;
|
||||||
|
|
||||||
|
\OCP\JSON::callCheck();
|
||||||
|
\OCP\JSON::checkLoggedIn();
|
||||||
|
|
||||||
|
$l = new \OC_L10N('files_opds');
|
||||||
|
|
||||||
|
$opdsEnable = isset($_POST['opdsEnable']) ? $_POST['opdsEnable'] : 'false';
|
||||||
|
$rootPath = isset($_POST['rootPath']) ? $_POST['rootPath'] : null;
|
||||||
|
$fileTypes = isset($_POST['fileTypes']) ? $_POST['fileTypes'] : '';
|
||||||
|
|
||||||
|
if (!is_null($rootPath)){
|
||||||
|
if (\OC\Files\Filesystem::file_exists($rootPath) === false ){
|
||||||
|
\OCP\JSON::error(
|
||||||
|
array(
|
||||||
|
'data' => array('message'=> $l->t('Directory does not exist!'))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
Config::set('root_path', $rootPath);
|
||||||
|
\OCP\JSON::success(
|
||||||
|
array(
|
||||||
|
'data' => array('message'=> $l->t('Settings updated successfully.'))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Config::set('enable', $opdsEnable);
|
||||||
|
Config::set('file_types', $fileTypes);
|
||||||
|
Config::set('id', Util::genUuid());
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
exit();
|
||||||
|
|
7
files_opds/appinfo/app.php
Normal file
7
files_opds/appinfo/app.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
$l = OC_L10N::get('files');
|
||||||
|
|
||||||
|
\OCP\App::registerPersonal('files_opds', 'personal');
|
||||||
|
|
||||||
|
|
13
files_opds/appinfo/info.xml
Normal file
13
files_opds/appinfo/info.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<info>
|
||||||
|
<id>files_opds</id>
|
||||||
|
<name>OPDS catalog</name>
|
||||||
|
<description>Personal OPDS catalog</description>
|
||||||
|
<licence>AGPL</licence>
|
||||||
|
<version>0.1</version>
|
||||||
|
<author>Frank de Lange</author>
|
||||||
|
<requiremin>7.0</requiremin>
|
||||||
|
<shipped>true</shipped>
|
||||||
|
<default_enable/>
|
||||||
|
</info>
|
||||||
|
|
57
files_opds/index.php
Normal file
57
files_opds/index.php
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds App
|
||||||
|
*
|
||||||
|
* @author Frank de Lange
|
||||||
|
* @copyright 2014 Frank de Lange
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Opds;
|
||||||
|
|
||||||
|
\OCP\App::checkAppEnabled('files_opds');
|
||||||
|
|
||||||
|
/* Enable login through basic auth, using normal OC username/password
|
||||||
|
* This is required because opds clients do not support the normal
|
||||||
|
* OC login process
|
||||||
|
*/
|
||||||
|
if (Util::authenticateUser() === false) {
|
||||||
|
Util::changeHttpStatus(401);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
\OCP\User::checkLoggedIn();
|
||||||
|
|
||||||
|
/* Refuse access if user disabled opds support */
|
||||||
|
if (Config::get('enable', 'false') === 'false') {
|
||||||
|
Util::changeHttpStatus(403);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* id defaults to 'root' (meaning 'serve root feed') */
|
||||||
|
$id = isset($_GET['id']) ? $_GET['id'] : 'root';
|
||||||
|
$dir = \OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getPath($id));
|
||||||
|
$root = Config::get('root_path', '/Library');
|
||||||
|
|
||||||
|
/* Only feed files descending from designated root directory */
|
||||||
|
if (!(Files::isChild($root,$dir))) {
|
||||||
|
$dir = $root;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dirInfo = \OC\Files\Filesystem::getFileInfo($dir);
|
||||||
|
|
||||||
|
/* If requested resource is a file, serve it, otherwise produce opds feed */
|
||||||
|
switch ($dirInfo->getType()) {
|
||||||
|
case 'file':
|
||||||
|
Util::serveFile($dir,$id);
|
||||||
|
break;
|
||||||
|
case 'dir':
|
||||||
|
Util::serveFeed($dir, $id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Util::logWarn("I don't know how to handle files of type " . $dirInfo->getType());
|
||||||
|
break;
|
||||||
|
}
|
45
files_opds/js/personal.js
Normal file
45
files_opds/js/personal.js
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
$(document).ready(function(){
|
||||||
|
// clear bookshelf
|
||||||
|
$('#opds-clear-bookshelf').on("click", function() {
|
||||||
|
$('#opds-really-clear-bookshelf,#opds-dont-clear-bookshelf').show();
|
||||||
|
});
|
||||||
|
$('#opds-dont-clear-bookshelf').on("click", function() {
|
||||||
|
$('#opds-really-clear-bookshelf,#opds-dont-clear-bookshelf').hide();
|
||||||
|
});
|
||||||
|
$('#opds-really-clear-bookshelf').on("click", function() {
|
||||||
|
$.post(OC.filePath('files_opds','ajax','clear_bookshelf.php'), {},
|
||||||
|
function(result){
|
||||||
|
if(result) {
|
||||||
|
OC.msg.finishedSaving('#opds-personal .clr', result);
|
||||||
|
$('#opds-book-count').hide();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#opds-really-clear-bookshelf,#opds-dont-clear-bookshelf').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
// save settings
|
||||||
|
var opdsSettings = {
|
||||||
|
save : function() {
|
||||||
|
var opdsEnable = document.getElementById('opds-enable').checked ? 'true' : 'false';
|
||||||
|
var data = {
|
||||||
|
opdsEnable : opdsEnable,
|
||||||
|
rootPath : $('#opds-root-path').val(),
|
||||||
|
fileTypes : $('#opds-file-types').val()
|
||||||
|
};
|
||||||
|
OC.msg.startSaving('#opds-personal .msg');
|
||||||
|
$.post(OC.filePath('files_opds', 'ajax', 'personal.php'), data, opdsSettings.afterSave);
|
||||||
|
},
|
||||||
|
afterSave : function(data){
|
||||||
|
OC.msg.finishedSaving('#opds-personal .msg', data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$('#opds-root-path,#opds-file-types').blur(opdsSettings.save);
|
||||||
|
$('#opds-root-path,#opds-file-types').keypress(function( event ) {
|
||||||
|
if (event.which == 13) {
|
||||||
|
event.preventDefault();
|
||||||
|
opdsSettings.save();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#opds-enable').on("change", opdsSettings.save);
|
||||||
|
});
|
||||||
|
|
65
files_opds/lib/bookshelf.php
Normal file
65
files_opds/lib/bookshelf.php
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds App
|
||||||
|
*
|
||||||
|
* @author Frank de Lange
|
||||||
|
* @copyright 2014 Frank de Lange
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Opds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bookshelf class for publishing as OPDS
|
||||||
|
*
|
||||||
|
* This implements a 'personal bookshelf', listing books
|
||||||
|
* which have been downloaded from the OPDS feed.
|
||||||
|
*/
|
||||||
|
class Bookshelf
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief add book to personal bookshelf
|
||||||
|
*
|
||||||
|
* @param int $id book to add to bookshelf
|
||||||
|
*/
|
||||||
|
public static function add($id) {
|
||||||
|
$bookshelf = json_decode(Config::get('bookshelf', ''), true);
|
||||||
|
if(!isset($bookshelf[$id])) {
|
||||||
|
$bookshelf[$id]=time();
|
||||||
|
}
|
||||||
|
Config::set('bookshelf', json_encode($bookshelf));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief clear personal bookshelf
|
||||||
|
*/
|
||||||
|
public static function clear() {
|
||||||
|
Config::set('bookshelf', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief return number of books on personal bookshelf
|
||||||
|
* @return int number of books
|
||||||
|
*/
|
||||||
|
public static function count() {
|
||||||
|
return substr_count(Config::get('bookshelf', ''), ':');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief list bookshelf contents
|
||||||
|
*
|
||||||
|
* @return array of FileInfo[], sorted by time added
|
||||||
|
*/
|
||||||
|
public static function get() {
|
||||||
|
$files = array();
|
||||||
|
$bookshelf = json_decode(Config::get('bookshelf', ''), true);
|
||||||
|
arsort($bookshelf);
|
||||||
|
while (list($id, $time) = each($bookshelf)) {
|
||||||
|
array_push($files, \OC\Files\Filesystem::getFileInfo(\OC\Files\Filesystem::normalizePath(\OC\Files\Filesystem::getPath($id))));
|
||||||
|
}
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
}
|
41
files_opds/lib/config.php
Normal file
41
files_opds/lib/config.php
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds App
|
||||||
|
*
|
||||||
|
* @author Frank de Lange
|
||||||
|
* @copyright 2014 Frank de Lange
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Opds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Config class for publishing as OPDS
|
||||||
|
*/
|
||||||
|
class Config
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief get user config value
|
||||||
|
*
|
||||||
|
* @param string $key value to retrieve
|
||||||
|
* @param string $default default value to use
|
||||||
|
* @return string retrieved value or default
|
||||||
|
*/
|
||||||
|
public static function get($key, $default) {
|
||||||
|
return \OCP\Config::getUserValue(\OCP\User::getUser(), 'files_opds', $key, $default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief set user config value
|
||||||
|
*
|
||||||
|
* @param string $key key for value to change
|
||||||
|
* @param string $value value to use
|
||||||
|
* @return bool success
|
||||||
|
*/
|
||||||
|
public static function set($key, $value) {
|
||||||
|
return \OCP\Config::setUserValue(\OCP\User::getUser(), 'files_opds', $key, $value);
|
||||||
|
}
|
||||||
|
}
|
67
files_opds/lib/files.php
Normal file
67
files_opds/lib/files.php
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds App
|
||||||
|
*
|
||||||
|
* @author Frank de Lange
|
||||||
|
* @copyright 2014 Frank de Lange
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Opds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Files class, extendes \OCA\Files, tailored for OPDS
|
||||||
|
*/
|
||||||
|
class Files extends \OCA\Files\Helper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Formats the file info to be returned as OPDS to the client.
|
||||||
|
*
|
||||||
|
* @param \OCP\Files\FileInfo $i
|
||||||
|
* @return array formatted file info
|
||||||
|
*/
|
||||||
|
public static function formatFileInfo($i) {
|
||||||
|
$entry = array();
|
||||||
|
|
||||||
|
$entry['id'] = $i['fileid'];
|
||||||
|
$entry['mtime'] = $i['mtime'] * 1000;
|
||||||
|
$entry['icon'] = self::determineIcon($i);
|
||||||
|
$entry['name'] = $i->getName();
|
||||||
|
$entry['mimetype'] = $i['mimetype'];
|
||||||
|
$entry['size'] = $i['size'];
|
||||||
|
$entry['type'] = $i['type'];
|
||||||
|
return $entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Format file info for OPDS feed
|
||||||
|
* @param \OCP\Files\FileInfo[] $fileInfos file infos
|
||||||
|
*/
|
||||||
|
public static function formatFileInfos($fileInfos) {
|
||||||
|
$files = array();
|
||||||
|
/* if set, add only files with given extensions */
|
||||||
|
$fileTypes = array_filter(explode(',', strtolower(Config::get('file_types', ''))));
|
||||||
|
foreach ($fileInfos as $i) {
|
||||||
|
if((!empty($fileTypes)) && (!in_array(strtolower(substr(strrchr($i->getName(), "."), 1)), $fileTypes))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$files[] = self::formatFileInfo($i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $files;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @brief check if $child is a subdirectory of $parent
|
||||||
|
*
|
||||||
|
* @param string $parent a directory
|
||||||
|
* @param string $child a directory
|
||||||
|
* @return bool true if $child is a subdirectory of $parent
|
||||||
|
*/
|
||||||
|
public static function isChild($parent, $child) {
|
||||||
|
return strpos($child, $parent . '/') === 0;
|
||||||
|
}
|
||||||
|
}
|
151
files_opds/lib/util.php
Normal file
151
files_opds/lib/util.php
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds App
|
||||||
|
*
|
||||||
|
* @author Frank de Lange
|
||||||
|
* @copyright 2014 Frank de Lange
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OCA\Files_Opds;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for OPDS
|
||||||
|
*/
|
||||||
|
class Util
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief Authenticate user by HTTP Basic Authentication
|
||||||
|
* with user name and password
|
||||||
|
*/
|
||||||
|
public static function authenticateUser() {
|
||||||
|
if (!isset($_SERVER['PHP_AUTH_USER'])) {
|
||||||
|
$defaults = new \OC_Defaults();
|
||||||
|
$realm = $defaults->getName();
|
||||||
|
header ("HTTP/1.0 401 Unauthorized");
|
||||||
|
header ('WWW-Authenticate: Basic realm="' . $realm. '"');
|
||||||
|
exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
$userName = $_SERVER['PHP_AUTH_USER'];
|
||||||
|
|
||||||
|
// Check the password in the ownCloud database
|
||||||
|
return self::checkPassword($userName, $_SERVER['PHP_AUTH_PW']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks the password of a user.
|
||||||
|
* @param string $userName ownCloud user name whose password will be checked.
|
||||||
|
* @param string $password ownCloud password.
|
||||||
|
* @return bool True if the password is correct, false otherwise.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static function checkPassword($userName, $password) {
|
||||||
|
|
||||||
|
// Check password normally
|
||||||
|
if (\OCP\User::checkPassword($userName, $password) != false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Change HTTP response code.
|
||||||
|
*
|
||||||
|
* @param integer $statusCode The new HTTP status code.
|
||||||
|
*/
|
||||||
|
public static function changeHttpStatus($statusCode) {
|
||||||
|
|
||||||
|
$message = '';
|
||||||
|
switch ($statusCode) {
|
||||||
|
case 400: $message = 'Bad Request'; break;
|
||||||
|
case 401: $message = 'Unauthorized'; break;
|
||||||
|
case 403: $message = 'Forbidden'; break;
|
||||||
|
case 404: $message = 'Not Found'; break;
|
||||||
|
case 500: $message = 'Internal Server Error'; break;
|
||||||
|
case 503: $message = 'Service Unavailable'; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set status code and status message in HTTP header
|
||||||
|
header('HTTP/1.0 ' . $statusCode . ' ' . $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief offer single file for download
|
||||||
|
*
|
||||||
|
* @param string $path full path to file
|
||||||
|
* @param int $id file id
|
||||||
|
*/
|
||||||
|
public static function serveFile($path, $id) {
|
||||||
|
\OCP\User::checkLoggedIn();
|
||||||
|
\OC::$session->close();
|
||||||
|
Bookshelf::add($id);
|
||||||
|
$dirName = dirname($path);
|
||||||
|
$fileName = basename($path);
|
||||||
|
\OC_Files::get($dirName, array($fileName), $_SERVER['REQUEST_METHOD'] == 'HEAD');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief serve opds feed for given directory
|
||||||
|
*
|
||||||
|
* @param string $dir full path to directory
|
||||||
|
* @param int $id requested id
|
||||||
|
*/
|
||||||
|
public static function serveFeed($dir, $id) {
|
||||||
|
if (isset($_SERVER['HTTP_ACCEPT']) && stristr($_SERVER['HTTP_ACCEPT'], 'application/atom+xml')) {
|
||||||
|
header('Content-Type: application/atom+xml');
|
||||||
|
} else {
|
||||||
|
header('Content-Type: text/xml; charset=UTF-8');
|
||||||
|
}
|
||||||
|
$sortAttribute = 'name';
|
||||||
|
$sortDirection = false;
|
||||||
|
$defaults = new \OC_Defaults();
|
||||||
|
$tmpl = new \OCP\Template('files_opds', 'feed');
|
||||||
|
$tmpl->assign('files', Files::formatFileInfos(Files::getFiles($dir, $sortAttribute, $sortDirection)));
|
||||||
|
$tmpl->assign('bookshelf', Files::formatFileInfos(Bookshelf::get()));
|
||||||
|
$tmpl->assign('bookshelf-count', Bookshelf::count());
|
||||||
|
$tmpl->assign('feed_id', self::getFeedId());
|
||||||
|
$tmpl->assign('id', $id);
|
||||||
|
$tmpl->assign('dir', $dir);
|
||||||
|
$tmpl->assign('user', \OCP\User::getDisplayName());
|
||||||
|
$tmpl->assign('ocname', $defaults->getName());
|
||||||
|
$tmpl->printPage();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief generate v3 UUID based on display name and site url
|
||||||
|
*
|
||||||
|
* @return string uuid
|
||||||
|
*/
|
||||||
|
public static function genUuid() {
|
||||||
|
$defaults = new \OC_Defaults();
|
||||||
|
$hash = md5(\OCP\User::getDisplayName() . $defaults->getBaseUrl());
|
||||||
|
$hash = substr($hash, 0, 8 ) .'-'.
|
||||||
|
substr($hash, 8, 4) .'-3'.
|
||||||
|
substr($hash, 13, 3) .'-9'.
|
||||||
|
substr($hash, 17, 3) .'-'.
|
||||||
|
substr($hash, 20);
|
||||||
|
return $hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief get feed id
|
||||||
|
*
|
||||||
|
* @return string feed id
|
||||||
|
*/
|
||||||
|
public static function getFeedId() {
|
||||||
|
return Config::get('id', '');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief log warning
|
||||||
|
* @param string message to write to log
|
||||||
|
*/
|
||||||
|
public static function logWarn($msg) {
|
||||||
|
\OCP\Util::writeLog('files_opds', $msg, \OCP\Util::WARN);
|
||||||
|
}
|
||||||
|
}
|
24
files_opds/personal.php
Normal file
24
files_opds/personal.php
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds app
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014 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_Opds;
|
||||||
|
|
||||||
|
\OCP\Util::addScript('files_opds', 'personal');
|
||||||
|
|
||||||
|
$tmpl = new \OCP\Template('files_opds', 'personal');
|
||||||
|
$opdsEnable = Config::get('enable', false);
|
||||||
|
$tmpl->assign('opdsEnable-checked', ($opdsEnable === 'true') ? 'checked="checked"' : '');
|
||||||
|
$tmpl->assign('opdsEnable-value', ($opdsEnable === 'true') ? '1' : '0');
|
||||||
|
$tmpl->assign('rootPath', Config::get('root_path', '/Library'));
|
||||||
|
$tmpl->assign('fileTypes', Config::get('file_types', ''));
|
||||||
|
$tmpl->assign('bookshelf-count', Bookshelf::count());
|
||||||
|
|
||||||
|
return $tmpl->fetchPage();
|
||||||
|
|
124
files_opds/templates/feed.php
Normal file
124
files_opds/templates/feed.php
Normal file
|
@ -0,0 +1,124 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds App
|
||||||
|
*
|
||||||
|
* @author Frank de Lange
|
||||||
|
* @copyright 2014 Frank de Lange
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
echo '<?xml version="1.0" encoding="UTF-8"?>';
|
||||||
|
?>
|
||||||
|
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom"
|
||||||
|
xmlns:dc="http://purl.org/dc/terms/"
|
||||||
|
xmlns:opds="http://opds-spec.org/2010/catalog">
|
||||||
|
<id>id:<?php p($_['feed_id']); ?></id>
|
||||||
|
<title><?php p($l->t("%s's library", array($_['user']))); ?></title>
|
||||||
|
<subtitle><?php p($l->t("%s OPDS Catalog", array($_['ocname']))); ?></subtitle>
|
||||||
|
<updated><?php p(date("Y-m-d\TH:i:sP", $_['feed_updated'])); ?></updated>
|
||||||
|
<author>
|
||||||
|
<name><?php p($_['user']); ?></name>
|
||||||
|
</author>
|
||||||
|
|
||||||
|
<link rel="start"
|
||||||
|
href="?id=root"
|
||||||
|
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||||
|
<link rel="self"
|
||||||
|
href="?id=<?php p($_['id']); ?>"
|
||||||
|
type="application/atom+xml;profile=opds-catalog;kind=navigation"/>
|
||||||
|
<?php if ($_['id'] == 'root'): ?>
|
||||||
|
<entry>
|
||||||
|
<title><?php p($l->t("Browse catalog")); ?></title>
|
||||||
|
<content type="text"><?php p($l->t("Browse the catalog in alphabetical order")); ?></content>
|
||||||
|
<link type="application/atom+xml;profile=opds-catalog;kind=navigation"
|
||||||
|
href="?id=directory"/>
|
||||||
|
<id>id:by_directory</id>
|
||||||
|
</entry>
|
||||||
|
<entry>
|
||||||
|
<title><?php p($l->t("%s's bookshelf", array($_['user']))); ?></title>
|
||||||
|
<content type="text"><?php p($l->t("This bookshelf contains %s books", array($_['bookshelf-count']))); ?></content>
|
||||||
|
<link type="application/atom+xml;profile=opds-catalog;kind=navigation"
|
||||||
|
href="?id=bookshelf"/>
|
||||||
|
<id>id:by_bookshelf</id>
|
||||||
|
</entry>
|
||||||
|
<?php elseif ($_['id'] == 'bookshelf'): ?>
|
||||||
|
<link rel="http://opds-spec.org/facet"
|
||||||
|
href="?id=bookshelf"
|
||||||
|
title="Bookshelf"
|
||||||
|
opds:activeFacet="true" />
|
||||||
|
|
||||||
|
<?php foreach ($_['bookshelf'] as $file): ?>
|
||||||
|
<entry>
|
||||||
|
<title><?php p($file['name']); ?></title>
|
||||||
|
<updated><?php p(date("Y-m-d\TH:i:sP", $file['mtime'])); ?></updated>
|
||||||
|
<id>id:<?php p($file['id']); ?></id>
|
||||||
|
<link type="<?php p($file['mimetype']); ?>"
|
||||||
|
rel="alternate"
|
||||||
|
href="?id=<?php p($file['id']); ?>"/>
|
||||||
|
<link type="<?php p($file['mimetype']); ?>"
|
||||||
|
rel="http://opds-spec.org/acquisition/open-access"
|
||||||
|
href="?id=<?php p($file['id']); ?>"/>
|
||||||
|
<link href="<?php p($file['icon']); ?>"
|
||||||
|
rel="http://opds-spec.org/image"
|
||||||
|
type="image/jpeg" />
|
||||||
|
<link href="<?php p($file['icon']); ?>"
|
||||||
|
rel="x-stanza-cover-image"
|
||||||
|
type="image/jpeg" />
|
||||||
|
<link href="<?php p($file['icon']); ?>"
|
||||||
|
rel="http://opds-spec.org/thumbnail"
|
||||||
|
type="image/jpeg" />
|
||||||
|
<link href="<?php p($file['icon']); ?>"
|
||||||
|
rel="x-stanza-cover-image-thumbnail"
|
||||||
|
type="image/jpeg" />
|
||||||
|
<content type="text"></content>
|
||||||
|
</entry>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<?php foreach ($_['files'] as $file): ?>
|
||||||
|
<?php if ($file['type'] == 'dir'): ?>
|
||||||
|
<entry>
|
||||||
|
<title><?php p($file['name']); ?></title>
|
||||||
|
<updated><?php p(date("Y-m-d\TH:i:sP", $file['mtime'])); ?></updated>
|
||||||
|
<id>id:<?php p($file['id']); ?></id>
|
||||||
|
<link type="application/atom+xml"
|
||||||
|
rel="alternate"
|
||||||
|
href="?id=<?php p($file['id']); ?>"/>
|
||||||
|
<link type="application/atom+xml;profile=opds-catalog;kind=navigation"
|
||||||
|
rel="subsection"
|
||||||
|
href="?id=<?php p($file['id']); ?>"/>
|
||||||
|
<content type="text"></content>
|
||||||
|
</entry>
|
||||||
|
<?php else: ?>
|
||||||
|
<entry>
|
||||||
|
<title><?php p($file['name']); ?></title>
|
||||||
|
<updated><?php p(date("Y-m-d\TH:i:sP", $file['mtime'])); ?></updated>
|
||||||
|
<id>id:<?php p($file['id']); ?></id>
|
||||||
|
<link type="<?php p($file['mimetype']); ?>"
|
||||||
|
rel="alternate"
|
||||||
|
href="?id=<?php p($file['id']); ?>"/>
|
||||||
|
<link type="<?php p($file['mimetype']); ?>"
|
||||||
|
rel="http://opds-spec.org/acquisition/open-access"
|
||||||
|
href="?id=<?php p($file['id']); ?>"/>
|
||||||
|
<link href="<?php p($file['icon']); ?>"
|
||||||
|
rel="http://opds-spec.org/image"
|
||||||
|
type="image/jpeg" />
|
||||||
|
<link href="<?php p($file['icon']); ?>"
|
||||||
|
rel="x-stanza-cover-image"
|
||||||
|
type="image/jpeg" />
|
||||||
|
<link href="<?php p($file['icon']); ?>"
|
||||||
|
rel="http://opds-spec.org/thumbnail"
|
||||||
|
type="image/jpeg" />
|
||||||
|
<link href="<?php p($file['icon']); ?>"
|
||||||
|
rel="x-stanza-cover-image-thumbnail"
|
||||||
|
type="image/jpeg" />
|
||||||
|
<content type="text/html"></content>
|
||||||
|
</entry>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php endif; ?>
|
||||||
|
</feed>
|
||||||
|
|
39
files_opds/templates/personal.php
Normal file
39
files_opds/templates/personal.php
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ownCloud - Files_Opds App
|
||||||
|
*
|
||||||
|
* @author Frank de Lange
|
||||||
|
* @copyright 2014 Frank de Lange
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3 or
|
||||||
|
* later.
|
||||||
|
*/
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div class="section" id="opds-personal">
|
||||||
|
<h2><?php p($l->t('OPDS')); ?></h2>
|
||||||
|
<div>
|
||||||
|
<input id="opds-enable" name="opds-enable" value="<?php p($_['opdsEnable-value']) ?>" <?php p($_['opdsEnable-checked']) ?> type="checkbox">
|
||||||
|
<label for="opds-enable"><?php p($l->t('enable OPDS catalog')) ?></label>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="opds-root-path"><?php p($l->t('Root directory:')) ?></label>
|
||||||
|
<input type="text" id="opds-root-path" title="<?php p($l->t("Enter root directory for OPDS catalog.")); ?>" value="<?php p($_['rootPath']) ?>" /><span class="msg"></span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label for="opds-file-types"><?php p($l->t('Supported extensions:')) ?></label>
|
||||||
|
<input type="text" id="opds-file-types" title="<?php p($l->t("Enter list of comma-separated extensions (eg. pdf,epub,doc,txt). Leave blank to publish all file types.")); ?>" value="<?php p($_['fileTypes']) ?>" />
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<input type="button" id="opds-clear-bookshelf" value="<?php p($l -> t('Clear Bookshelf')); ?>" />
|
||||||
|
<input type="button" id="opds-really-clear-bookshelf" title="<?php p($l->t("Clear list of downloaded books from bookshelf. This only clears the list, it does not delete any books.")); ?>" value="<?php p($l -> t('Yes, I really want to clear my personal bookshelf')); ?>" hidden />
|
||||||
|
<input type="button" id="opds-dont-clear-bookshelf" value="<?php p($l -> t('No, I do not want to clear my bookshelf')); ?>" hidden />
|
||||||
|
<span class="clr"></span>
|
||||||
|
<div>
|
||||||
|
<span id="opds-book-count"><?php p($l->t('There are %s books on your personal bookshelf', array($_['bookshelf-count']))) ?></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
3
files_reader/appinfo/app.php
Normal file
3
files_reader/appinfo/app.php
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<?php
|
||||||
|
//load the required files
|
||||||
|
OCP\Util::addscript( 'files_reader', 'loader');
|
13
files_reader/appinfo/info.xml
Normal file
13
files_reader/appinfo/info.xml
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<info>
|
||||||
|
<id>files_reader</id>
|
||||||
|
<name>Reader (ebook reader)</name>
|
||||||
|
<description>Online ePub file reader</description>
|
||||||
|
<version>0.4.4</version>
|
||||||
|
<licence>LGPL</licence>
|
||||||
|
<author>Frank de Lange, (taken clues from Thomas Müller/files_pdfviewer, using slightly modified Futurepress/epub.js)</author>
|
||||||
|
<require>7.0</require>
|
||||||
|
<shipped>false</shipped>
|
||||||
|
<default_enable/>
|
||||||
|
<standalone/>
|
||||||
|
</info>
|
1
files_reader/appinfo/version
Normal file
1
files_reader/appinfo/version
Normal file
|
@ -0,0 +1 @@
|
||||||
|
0.4.4
|
BIN
files_reader/css/font/fontello.eot
Normal file
BIN
files_reader/css/font/fontello.eot
Normal file
Binary file not shown.
BIN
files_reader/css/font/fontello.svg
Normal file
BIN
files_reader/css/font/fontello.svg
Normal file
Binary file not shown.
BIN
files_reader/css/font/fontello.ttf
Normal file
BIN
files_reader/css/font/fontello.ttf
Normal file
Binary file not shown.
BIN
files_reader/css/font/fontello.woff
Normal file
BIN
files_reader/css/font/fontello.woff
Normal file
Binary file not shown.
33
files_reader/css/idevice.css
Normal file
33
files_reader/css/idevice.css
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
/* For iPad portrait layouts only */
|
||||||
|
@media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation: portrait) {
|
||||||
|
#viewer iframe {
|
||||||
|
width: 460px;
|
||||||
|
height: 740px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*For iPad landscape layouts only */
|
||||||
|
@media only screen and (min-device-width: 481px) and (max-device-width: 1024px) and (orientation: landscape) {
|
||||||
|
#viewer iframe {
|
||||||
|
width: 460px;
|
||||||
|
height: 415px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* For iPhone portrait layouts only */
|
||||||
|
@media only screen and (max-device-width: 480px) and (orientation: portrait) {
|
||||||
|
#viewer {
|
||||||
|
width: 256px;
|
||||||
|
height: 432px;
|
||||||
|
}
|
||||||
|
#viewer iframe {
|
||||||
|
width: 256px;
|
||||||
|
height: 432px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* For iPhone landscape layouts only */
|
||||||
|
@media only screen and (max-device-width: 480px) and (orientation: landscape) {
|
||||||
|
#viewer iframe {
|
||||||
|
width: 256px;
|
||||||
|
height: 124px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
782
files_reader/css/main.css
Normal file
782
files_reader/css/main.css
Normal file
|
@ -0,0 +1,782 @@
|
||||||
|
@font-face {
|
||||||
|
font-family: 'fontello';
|
||||||
|
src: url('font/fontello.eot?60518104');
|
||||||
|
src: url('font/fontello.eot?60518104#iefix') format('embedded-opentype'),
|
||||||
|
url('font/fontello.woff?60518104') format('woff'),
|
||||||
|
url('font/fontello.ttf?60518104') format('truetype'),
|
||||||
|
url('font/fontello.svg?60518104#fontello') format('svg');
|
||||||
|
font-weight: normal;
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background: #4e4e4e;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
/* height: 500px; */
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
right: 0;
|
||||||
|
/* left: 40px; */
|
||||||
|
/* -webkit-transform: translate(40px, 0);
|
||||||
|
-moz-transform: translate(40px, 0); */
|
||||||
|
|
||||||
|
/* border-radius: 5px 0px 0px 5px; */
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #fff;
|
||||||
|
overflow: hidden;
|
||||||
|
-webkit-transition: -webkit-transform .4s, width .2s;
|
||||||
|
-moz-transition: -webkit-transform .4s, width .2s;
|
||||||
|
|
||||||
|
-moz-box-shadow: inset 0 0 50px rgba(0,0,0,.1);
|
||||||
|
-webkit-box-shadow: inset 0 0 50px rgba(0,0,0,.1);
|
||||||
|
box-shadow: inset 0 0 50px rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#titlebar {
|
||||||
|
height: 8%;
|
||||||
|
min-height: 20px;
|
||||||
|
padding: 10px;
|
||||||
|
/* margin: 0 50px 0 50px; */
|
||||||
|
position: relative;
|
||||||
|
color: #4f4f4f;
|
||||||
|
font-weight: 100;
|
||||||
|
font-family: Georgia, "Times New Roman", Times, serif;
|
||||||
|
opacity: .5;
|
||||||
|
text-align: center;
|
||||||
|
-webkit-transition: opacity .5s;
|
||||||
|
-moz-transition: opacity .5s;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
#titlebar:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#titlebar a {
|
||||||
|
width: 18px;
|
||||||
|
height: 19px;
|
||||||
|
line-height: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: inline-block;
|
||||||
|
opacity: .5;
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#titlebar a::before {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
#titlebar a:hover {
|
||||||
|
opacity: .8;
|
||||||
|
border: 1px rgba(0,0,0,.2) solid;
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#titlebar a:active {
|
||||||
|
opacity: 1;
|
||||||
|
color: rgba(0,0,0,.6);
|
||||||
|
/* margin: 1px -1px -1px 1px; */
|
||||||
|
-moz-box-shadow: inset 0 0 6px rgba(155,155,155,.8);
|
||||||
|
-webkit-box-shadow: inset 0 0 6px rgba(155,155,155,.8);
|
||||||
|
box-shadow: inset 0 0 6px rgba(155,155,155,.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#book-title {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title-seperator {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#viewer {
|
||||||
|
width: 80%;
|
||||||
|
height: 80%;
|
||||||
|
/* margin-left: 10%; */
|
||||||
|
margin: 0 auto;
|
||||||
|
max-width: 1250px;
|
||||||
|
z-index: 2;
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#viewer iframe {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#prev, #next {
|
||||||
|
position: absolute;
|
||||||
|
top: 10%;
|
||||||
|
height: 85%;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.touch_nav {
|
||||||
|
width: 35%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow div {
|
||||||
|
display: table-cell;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#prev {
|
||||||
|
left: 0;
|
||||||
|
padding-left: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#next {
|
||||||
|
right: 0;
|
||||||
|
padding-right: 40px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
/* position: relative;
|
||||||
|
top: 50%;
|
||||||
|
margin-top: -32px; */
|
||||||
|
font-size: 64px;
|
||||||
|
color: #E2E2E2;
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
display: table;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow:hover {
|
||||||
|
color: #777;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow:active,
|
||||||
|
.arrow.active {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar {
|
||||||
|
background: #6b6b6b;
|
||||||
|
position: absolute;
|
||||||
|
/* left: -260px; */
|
||||||
|
/* -webkit-transform: translate(-260px, 0);
|
||||||
|
-moz-transform: translate(-260px, 0); */
|
||||||
|
top: 0;
|
||||||
|
min-width: 300px;
|
||||||
|
width: 25%;
|
||||||
|
height: 100%;
|
||||||
|
-webkit-transition: -webkit-transform .5s;
|
||||||
|
-moz-transition: -moz-transform .5s;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar.open {
|
||||||
|
/* left: 0; */
|
||||||
|
/* -webkit-transform: translate(0, 0);
|
||||||
|
-moz-transform: translate(0, 0); */
|
||||||
|
}
|
||||||
|
|
||||||
|
#main.closed {
|
||||||
|
/* left: 300px; */
|
||||||
|
-webkit-transform: translate(300px, 0);
|
||||||
|
-moz-transform: translate(300px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#main.single {
|
||||||
|
width: 75%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main.single #viewer {
|
||||||
|
/* width: 60%;
|
||||||
|
margin-left: 20%; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#panels {
|
||||||
|
background: #4e4e4e;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
padding: 13px 0;
|
||||||
|
height: 14px;
|
||||||
|
-moz-box-shadow: 0px 1px 3px rgba(0,0,0,.6);
|
||||||
|
-webkit-box-shadow: 0px 1px 3px rgba(0,0,0,.6);
|
||||||
|
box-shadow: 0px 1px 3px rgba(0,0,0,.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#opener {
|
||||||
|
/* padding: 10px 10px; */
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #opener #slider {
|
||||||
|
width: 25px;
|
||||||
|
} */
|
||||||
|
|
||||||
|
#metainfo {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#title-controls {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#panels a {
|
||||||
|
visibility: hidden;
|
||||||
|
width: 18px;
|
||||||
|
height: 20px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: inline-block;
|
||||||
|
color: #ccc;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#panels a::before {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
#panels a:hover {
|
||||||
|
color: #AAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
#panels a:active {
|
||||||
|
color: #AAA;
|
||||||
|
margin: 1px 0 -1px 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#panels a.active,
|
||||||
|
#panels a.active:hover {
|
||||||
|
color: #AAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchBox {
|
||||||
|
width: 165px;
|
||||||
|
float: left;
|
||||||
|
margin-left: 10px;
|
||||||
|
margin-top: -1px;
|
||||||
|
/*
|
||||||
|
border-radius: 5px;
|
||||||
|
background: #9b9b9b;
|
||||||
|
float: left;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: -5px;
|
||||||
|
padding: 3px 10px;
|
||||||
|
color: #000;
|
||||||
|
border: none;
|
||||||
|
outline: none; */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-webkit-input-placeholder {
|
||||||
|
color: #454545;
|
||||||
|
}
|
||||||
|
input:-moz-placeholder {
|
||||||
|
color: #454545;
|
||||||
|
}
|
||||||
|
|
||||||
|
#divider {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px;
|
||||||
|
border-right: 1px #000 solid;
|
||||||
|
height: 80%;
|
||||||
|
z-index: 1;
|
||||||
|
left: 50%;
|
||||||
|
margin-left: -1px;
|
||||||
|
top: 10%;
|
||||||
|
opacity: .15;
|
||||||
|
box-shadow: -2px 0 15px rgba(0, 0, 0, 1);
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#divider.show {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loader {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 10;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
margin: -33px 0 0 -33px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tocView,
|
||||||
|
#bookmarksView {
|
||||||
|
overflow-x: hidden;
|
||||||
|
overflow-y: hidden;
|
||||||
|
min-width: 300px;
|
||||||
|
width: 25%;
|
||||||
|
height: 100%;
|
||||||
|
visibility: hidden;
|
||||||
|
-webkit-transition: visibility 0 ease .5s;
|
||||||
|
-moz-transition: visibility 0 ease .5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#sidebar.open #tocView,
|
||||||
|
#sidebar.open #bookmarksView {
|
||||||
|
overflow-y: auto;
|
||||||
|
visibility: visible;
|
||||||
|
-webkit-transition: visibility 0 ease 0;
|
||||||
|
-moz-transition: visibility 0 ease 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar.open #tocView {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tocView > ul,
|
||||||
|
#bookmarksView > ul {
|
||||||
|
margin-top: 15px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
padding-left: 20px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tocView li,
|
||||||
|
#bookmarksView li {
|
||||||
|
margin-bottom:10px;
|
||||||
|
width: 225px;
|
||||||
|
font-family: Georgia, "Times New Roman", Times, serif;
|
||||||
|
list-style: none;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tocView li:active,
|
||||||
|
#tocView li.currentChapter
|
||||||
|
{
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list_item a {
|
||||||
|
color: #AAA;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list_item a.chapter {
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list_item a.section {
|
||||||
|
font-size: .8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list_item.currentChapter > a,
|
||||||
|
.list_item a:hover {
|
||||||
|
color: #f1f1f1
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #tocView li.openChapter > a, */
|
||||||
|
.list_item a:hover {
|
||||||
|
color: #E2E2E2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list_item ul {
|
||||||
|
padding-left:10px;
|
||||||
|
margin-top: 8px;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list_item.currentChapter > ul,
|
||||||
|
.list_item.openChapter > ul {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tocView.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc_toggle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 14px;
|
||||||
|
cursor: pointer;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.toc_toggle:before {
|
||||||
|
content: '▸';
|
||||||
|
color: #fff;
|
||||||
|
margin-right: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.currentChapter > .toc_toggle:before,
|
||||||
|
.openChapter > .toc_toggle:before {
|
||||||
|
content: '▾';
|
||||||
|
}
|
||||||
|
|
||||||
|
.view {
|
||||||
|
width: 300px;
|
||||||
|
height: 100%;
|
||||||
|
display: none;
|
||||||
|
padding-top: 50px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchResults {
|
||||||
|
margin-bottom: 50px;
|
||||||
|
padding-left: 20px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchResults li {
|
||||||
|
margin-bottom:10px;
|
||||||
|
width: 225px;
|
||||||
|
font-family: Georgia, "Times New Roman", Times, serif;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchResults a {
|
||||||
|
color: #AAA;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchResults p {
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchResults p .match {
|
||||||
|
background: #ccc;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchResults li > p {
|
||||||
|
color: #AAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchResults li a:hover {
|
||||||
|
color: #E2E2E2;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchView.shown {
|
||||||
|
display: block;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notes {
|
||||||
|
padding: 0 0 0 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notes li {
|
||||||
|
color: #eee;
|
||||||
|
font-size: 12px;
|
||||||
|
width: 240px;
|
||||||
|
border-top: 1px #fff solid;
|
||||||
|
padding-top: 6px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notes li a {
|
||||||
|
color: #fff;
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notes li a:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#notes li img {
|
||||||
|
max-width: 240px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#note-text {
|
||||||
|
display: block;
|
||||||
|
width: 260px;
|
||||||
|
height: 80px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#note-text[disabled], #note-text[disabled="disabled"]{
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
|
||||||
|
#note-anchor {
|
||||||
|
margin-left: 218px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settingsPanel {
|
||||||
|
display:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settingsPanel h3 {
|
||||||
|
color:#f1f1f1;
|
||||||
|
font-family:Georgia, "Times New Roman", Times, serif;
|
||||||
|
margin-bottom:10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settingsPanel ul {
|
||||||
|
margin-top:60px;
|
||||||
|
list-style-type:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settingsPanel li {
|
||||||
|
font-size:1em;
|
||||||
|
color:#f1f1f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#settingsPanel .xsmall { font-size:x-small; }
|
||||||
|
#settingsPanel .small { font-size:small; }
|
||||||
|
#settingsPanel .medium { font-size:medium; }
|
||||||
|
#settingsPanel .large { font-size:large; }
|
||||||
|
#settingsPanel .xlarge { font-size:x-large; }
|
||||||
|
|
||||||
|
.highlight { background-color: yellow }
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 50%;
|
||||||
|
width: 630px;
|
||||||
|
|
||||||
|
height: auto;
|
||||||
|
z-index: 2000;
|
||||||
|
visibility: hidden;
|
||||||
|
margin-left: -320px;
|
||||||
|
margin-top: -160px;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.overlay {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
visibility: hidden;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1000;
|
||||||
|
opacity: 0;
|
||||||
|
background: rgba(255,255,255,0.8);
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
-moz-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-show {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-show ~ .overlay {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Content styles */
|
||||||
|
.md-content {
|
||||||
|
color: #fff;
|
||||||
|
background: #6b6b6b;
|
||||||
|
position: relative;
|
||||||
|
border-radius: 3px;
|
||||||
|
margin: 0 auto;
|
||||||
|
height: 320px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-content h3 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 6px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 22px;
|
||||||
|
font-weight: 300;
|
||||||
|
opacity: 0.8;
|
||||||
|
background: rgba(0,0,0,0.1);
|
||||||
|
border-radius: 3px 3px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-content > div {
|
||||||
|
padding: 15px 40px 30px;
|
||||||
|
margin: 0;
|
||||||
|
font-weight: 300;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-content > div p {
|
||||||
|
margin: 0;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-content > div ul {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 0 30px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-content > div ul li {
|
||||||
|
padding: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-content button {
|
||||||
|
display: block;
|
||||||
|
margin: 0 auto;
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Effect 1: Fade in and scale up */
|
||||||
|
.md-effect-1 .md-content {
|
||||||
|
-webkit-transform: scale(0.7);
|
||||||
|
-moz-transform: scale(0.7);
|
||||||
|
-ms-transform: scale(0.7);
|
||||||
|
transform: scale(0.7);
|
||||||
|
opacity: 0;
|
||||||
|
-webkit-transition: all 0.3s;
|
||||||
|
-moz-transition: all 0.3s;
|
||||||
|
transition: all 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-show.md-effect-1 .md-content {
|
||||||
|
-webkit-transform: scale(1);
|
||||||
|
-moz-transform: scale(1);
|
||||||
|
-ms-transform: scale(1);
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.md-content > .closer {
|
||||||
|
font-size: 18px;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 1040px) {
|
||||||
|
#viewer{
|
||||||
|
width: 50%;
|
||||||
|
margin-left: 25%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#divider,
|
||||||
|
#divider.show {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 900px) {
|
||||||
|
#viewer{
|
||||||
|
width: 60%;
|
||||||
|
margin-left: 20%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#prev {
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#next {
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (max-width: 550px) {
|
||||||
|
#viewer{
|
||||||
|
width: 80%;
|
||||||
|
margin-left: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#prev {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#next {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow div {
|
||||||
|
text-indent: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main {
|
||||||
|
-webkit-transform: translate(0, 0);
|
||||||
|
-moz-transform: translate(0, 0);
|
||||||
|
-webkit-transition: -webkit-transform .3s;
|
||||||
|
-moz-transition: -moz-transform .3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
#main.closed {
|
||||||
|
-webkit-transform: translate(260px, 0);
|
||||||
|
-moz-transform: translate(260px, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#titlebar {
|
||||||
|
/* font-size: 16px; */
|
||||||
|
/* margin: 0 50px 0 50px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
#metainfo {
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tocView {
|
||||||
|
width: 260px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tocView li {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tocView > ul{
|
||||||
|
padding-left: 10px;
|
||||||
|
webkit-padding-start:;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[class^="icon-"]:before, [class*=" icon-"]:before {
|
||||||
|
font-family: "fontello";
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
speak: none;
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
text-decoration: inherit;
|
||||||
|
width: 1em;
|
||||||
|
margin-right: .2em;
|
||||||
|
text-align: center;
|
||||||
|
/* opacity: .8; */
|
||||||
|
|
||||||
|
/* For safety - reset parent styles, that can break glyph codes*/
|
||||||
|
font-variant: normal;
|
||||||
|
text-transform: none;
|
||||||
|
|
||||||
|
/* you can be more comfortable with increased icons size */
|
||||||
|
font-size: 112%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.icon-search:before { content: '\e807'; } /* '' */
|
||||||
|
.icon-resize-full-1:before { content: '\e804'; } /* '' */
|
||||||
|
.icon-cancel-circled2:before { content: '\e80f'; } /* '' */
|
||||||
|
.icon-link:before { content: '\e80d'; } /* '' */
|
||||||
|
.icon-bookmark:before { content: '\e805'; } /* '' */
|
||||||
|
.icon-bookmark-empty:before { content: '\e806'; } /* '' */
|
||||||
|
.icon-download-cloud:before { content: '\e811'; } /* '' */
|
||||||
|
.icon-edit:before { content: '\e814'; } /* '' */
|
||||||
|
.icon-menu:before { content: '\e802'; } /* '' */
|
||||||
|
.icon-cog:before { content: '\e813'; } /* '' */
|
||||||
|
.icon-resize-full:before { content: '\e812'; } /* '' */
|
||||||
|
.icon-cancel-circled:before { content: '\e80e'; } /* '' */
|
||||||
|
.icon-up-dir:before { content: '\e80c'; } /* '' */
|
||||||
|
.icon-right-dir:before { content: '\e80b'; } /* '' */
|
||||||
|
.icon-angle-right:before { content: '\e809'; } /* '' */
|
||||||
|
.icon-angle-down:before { content: '\e80a'; } /* '' */
|
||||||
|
.icon-right:before { content: '\e815'; } /* '' */
|
||||||
|
.icon-list-1:before { content: '\e803'; } /* '' */
|
||||||
|
.icon-list-numbered:before { content: '\e801'; } /* '' */
|
||||||
|
.icon-columns:before { content: '\e810'; } /* '' */
|
||||||
|
.icon-list:before { content: '\e800'; } /* '' */
|
||||||
|
.icon-resize-small:before { content: '\e808'; } /* '' */
|
505
files_reader/css/normalize.css
vendored
Normal file
505
files_reader/css/normalize.css
vendored
Normal file
|
@ -0,0 +1,505 @@
|
||||||
|
/*! normalize.css v1.0.1 | MIT License | git.io/normalize */
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
HTML5 display definitions
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Corrects `block` display not defined in IE 6/7/8/9 and Firefox 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
article,
|
||||||
|
aside,
|
||||||
|
details,
|
||||||
|
figcaption,
|
||||||
|
figure,
|
||||||
|
footer,
|
||||||
|
header,
|
||||||
|
hgroup,
|
||||||
|
nav,
|
||||||
|
section,
|
||||||
|
summary {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Corrects `inline-block` display not defined in IE 6/7/8/9 and Firefox 3.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio,
|
||||||
|
canvas,
|
||||||
|
video {
|
||||||
|
display: inline-block;
|
||||||
|
*display: inline;
|
||||||
|
*zoom: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prevents modern browsers from displaying `audio` without controls.
|
||||||
|
* Remove excess height in iOS 5 devices.
|
||||||
|
*/
|
||||||
|
|
||||||
|
audio:not([controls]) {
|
||||||
|
display: none;
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses styling for `hidden` attribute not present in IE 7/8/9, Firefox 3,
|
||||||
|
* and Safari 4.
|
||||||
|
* Known issue: no IE 6 support.
|
||||||
|
*/
|
||||||
|
|
||||||
|
[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Base
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Corrects text resizing oddly in IE 6/7 when body `font-size` is set using
|
||||||
|
* `em` units.
|
||||||
|
* 2. Prevents iOS text size adjust after orientation change, without disabling
|
||||||
|
* user zoom.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
-webkit-text-size-adjust: 100%; /* 2 */
|
||||||
|
-ms-text-size-adjust: 100%; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses `font-family` inconsistency between `textarea` and other form
|
||||||
|
* elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
html,
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses margins handled incorrectly in IE 6/7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Links
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses `outline` inconsistency between Chrome and other browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a:focus {
|
||||||
|
outline: thin dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Improves readability when focused and also mouse hovered in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
a:active,
|
||||||
|
a:hover {
|
||||||
|
outline: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Typography
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses font sizes and margins set differently in IE 6/7.
|
||||||
|
* Addresses font sizes within `section` and `article` in Firefox 4+, Safari 5,
|
||||||
|
* and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2em;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.5em;
|
||||||
|
margin: 0.83em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-size: 1.17em;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 1em;
|
||||||
|
margin: 1.33em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h5 {
|
||||||
|
font-size: 0.83em;
|
||||||
|
margin: 1.67em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h6 {
|
||||||
|
font-size: 0.75em;
|
||||||
|
margin: 2.33em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses styling not present in IE 7/8/9, Safari 5, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
abbr[title] {
|
||||||
|
border-bottom: 1px dotted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses style set to `bolder` in Firefox 3+, Safari 4/5, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
b,
|
||||||
|
strong {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
margin: 1em 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses styling not present in Safari 5 and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
dfn {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses styling not present in IE 6/7/8/9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mark {
|
||||||
|
background: #ff0;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses margins set differently in IE 6/7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
p,
|
||||||
|
pre {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Corrects font family set oddly in IE 6, Safari 4/5, and Chrome.
|
||||||
|
*/
|
||||||
|
|
||||||
|
code,
|
||||||
|
kbd,
|
||||||
|
pre,
|
||||||
|
samp {
|
||||||
|
font-family: monospace, serif;
|
||||||
|
_font-family: 'courier new', monospace;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Improves readability of pre-formatted text in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pre {
|
||||||
|
white-space: pre;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses CSS quotes not supported in IE 6/7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
q {
|
||||||
|
quotes: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses `quotes` property not supported in Safari 4.
|
||||||
|
*/
|
||||||
|
|
||||||
|
q:before,
|
||||||
|
q:after {
|
||||||
|
content: '';
|
||||||
|
content: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses inconsistent and variable font size in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
small {
|
||||||
|
font-size: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prevents `sub` and `sup` affecting `line-height` in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sub,
|
||||||
|
sup {
|
||||||
|
font-size: 75%;
|
||||||
|
line-height: 0;
|
||||||
|
position: relative;
|
||||||
|
vertical-align: baseline;
|
||||||
|
}
|
||||||
|
|
||||||
|
sup {
|
||||||
|
top: -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
sub {
|
||||||
|
bottom: -0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Lists
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses margins set differently in IE 6/7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
dl,
|
||||||
|
menu,
|
||||||
|
ol,
|
||||||
|
ul {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dd {
|
||||||
|
margin: 0 0 0 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses paddings set differently in IE 6/7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
menu,
|
||||||
|
ol,
|
||||||
|
ul {
|
||||||
|
padding: 0 0 0 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Corrects list images handled incorrectly in IE 7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
nav ul,
|
||||||
|
nav ol {
|
||||||
|
list-style: none;
|
||||||
|
list-style-image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Embedded content
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Removes border when inside `a` element in IE 6/7/8/9 and Firefox 3.
|
||||||
|
* 2. Improves image quality when scaled in IE 7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
img {
|
||||||
|
border: 0; /* 1 */
|
||||||
|
-ms-interpolation-mode: bicubic; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Corrects overflow displayed oddly in IE 9.
|
||||||
|
*/
|
||||||
|
|
||||||
|
svg:not(:root) {
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Figures
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses margin not present in IE 6/7/8/9, Safari 5, and Opera 11.
|
||||||
|
*/
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Forms
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Corrects margin displayed oddly in IE 6/7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
form {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define consistent border, margin, and padding.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
border: 1px solid #c0c0c0;
|
||||||
|
margin: 0 2px;
|
||||||
|
padding: 0.35em 0.625em 0.75em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Corrects color not being inherited in IE 6/7/8/9.
|
||||||
|
* 2. Corrects text not wrapping in Firefox 3.
|
||||||
|
* 3. Corrects alignment displayed oddly in IE 6/7.
|
||||||
|
*/
|
||||||
|
|
||||||
|
legend {
|
||||||
|
border: 0; /* 1 */
|
||||||
|
padding: 0;
|
||||||
|
white-space: normal; /* 2 */
|
||||||
|
*margin-left: -7px; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Corrects font size not being inherited in all browsers.
|
||||||
|
* 2. Addresses margins set differently in IE 6/7, Firefox 3+, Safari 5,
|
||||||
|
* and Chrome.
|
||||||
|
* 3. Improves appearance and consistency in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input,
|
||||||
|
select,
|
||||||
|
textarea {
|
||||||
|
font-size: 100%; /* 1 */
|
||||||
|
margin: 0; /* 2 */
|
||||||
|
vertical-align: baseline; /* 3 */
|
||||||
|
*vertical-align: middle; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Addresses Firefox 3+ setting `line-height` on `input` using `!important` in
|
||||||
|
* the UA stylesheet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
input {
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
|
||||||
|
* and `video` controls.
|
||||||
|
* 2. Corrects inability to style clickable `input` types in iOS.
|
||||||
|
* 3. Improves usability and consistency of cursor style between image-type
|
||||||
|
* `input` and others.
|
||||||
|
* 4. Removes inner spacing in IE 7 without affecting normal text inputs.
|
||||||
|
* Known issue: inner spacing remains in IE 6.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button,
|
||||||
|
html input[type="button"], /* 1 */
|
||||||
|
input[type="reset"],
|
||||||
|
input[type="submit"] {
|
||||||
|
-webkit-appearance: button; /* 2 */
|
||||||
|
cursor: pointer; /* 3 */
|
||||||
|
*overflow: visible; /* 4 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Re-set default cursor for disabled elements.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button[disabled],
|
||||||
|
input[disabled] {
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Addresses box sizing set to content-box in IE 8/9.
|
||||||
|
* 2. Removes excess padding in IE 8/9.
|
||||||
|
* 3. Removes excess padding in IE 7.
|
||||||
|
* Known issue: excess padding remains in IE 6.
|
||||||
|
*/
|
||||||
|
|
||||||
|
input[type="checkbox"],
|
||||||
|
input[type="radio"] {
|
||||||
|
box-sizing: border-box; /* 1 */
|
||||||
|
padding: 0; /* 2 */
|
||||||
|
*height: 13px; /* 3 */
|
||||||
|
*width: 13px; /* 3 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Addresses `appearance` set to `searchfield` in Safari 5 and Chrome.
|
||||||
|
* 2. Addresses `box-sizing` set to `border-box` in Safari 5 and Chrome
|
||||||
|
* (include `-moz` to future-proof).
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
input[type="search"] {
|
||||||
|
-webkit-appearance: textfield;
|
||||||
|
-moz-box-sizing: content-box;
|
||||||
|
-webkit-box-sizing: content-box;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Removes inner padding and search cancel button in Safari 5 and Chrome
|
||||||
|
* on OS X.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* input[type="search"]::-webkit-search-cancel-button,
|
||||||
|
input[type="search"]::-webkit-search-decoration {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
} */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Removes inner padding and border in Firefox 3+.
|
||||||
|
*/
|
||||||
|
|
||||||
|
button::-moz-focus-inner,
|
||||||
|
input::-moz-focus-inner {
|
||||||
|
border: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 1. Removes default vertical scrollbar in IE 6/7/8/9.
|
||||||
|
* 2. Improves readability and alignment in all browsers.
|
||||||
|
*/
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
overflow: auto; /* 1 */
|
||||||
|
vertical-align: top; /* 2 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==========================================================================
|
||||||
|
Tables
|
||||||
|
========================================================================== */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove most spacing between table cells.
|
||||||
|
*/
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
border-spacing: 0;
|
||||||
|
}
|
96
files_reader/css/popup.css
Normal file
96
files_reader/css/popup.css
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/* http://davidwalsh.name/css-tooltips */
|
||||||
|
/* base CSS element */
|
||||||
|
.popup {
|
||||||
|
background: #eee;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||||
|
position: fixed;
|
||||||
|
max-width: 300px;
|
||||||
|
font-size: 12px;
|
||||||
|
|
||||||
|
display: none;
|
||||||
|
margin-left: 2px;
|
||||||
|
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup.above {
|
||||||
|
margin-top: -10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup.left {
|
||||||
|
margin-left: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup.right {
|
||||||
|
margin-left: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pop_content {
|
||||||
|
max-height: 225px;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pop_content > p {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* below */
|
||||||
|
.popup:before {
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom: 10px solid #eee;
|
||||||
|
border-right: 10px solid transparent;
|
||||||
|
border-left: 10px solid transparent;
|
||||||
|
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||||
|
left: 50%;
|
||||||
|
top: -10px;
|
||||||
|
margin-left: -6px;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup:after {
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom: 9px solid #eee;
|
||||||
|
border-right: 9px solid transparent;
|
||||||
|
border-left: 9px solid transparent;
|
||||||
|
left: 50%;
|
||||||
|
top: -9px;
|
||||||
|
margin-left: -5px;
|
||||||
|
content: '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* above */
|
||||||
|
.popup.above:before {
|
||||||
|
border-bottom: none;
|
||||||
|
border-top: 10px solid #eee;
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.2);
|
||||||
|
top: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup.above:after {
|
||||||
|
border-bottom: none;
|
||||||
|
border-top: 9px solid #eee;
|
||||||
|
top: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup.left:before,
|
||||||
|
.popup.left:after
|
||||||
|
{
|
||||||
|
left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup.right:before,
|
||||||
|
.popup.right:after
|
||||||
|
{
|
||||||
|
left: auto;
|
||||||
|
right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.popup.show, .popup.on {
|
||||||
|
display: block;
|
||||||
|
}
|
31
files_reader/css/tooltip.css
Normal file
31
files_reader/css/tooltip.css
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
.tooltip {
|
||||||
|
position: relative;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
*.tooltip:hover span {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
*.tooltip span {
|
||||||
|
z-index: 10;
|
||||||
|
padding: 1em;
|
||||||
|
bottom: 2em;
|
||||||
|
right: -10em;
|
||||||
|
width: 50%;
|
||||||
|
background-color: #222222;
|
||||||
|
color: #FFFFFF;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
opacity: 0;
|
||||||
|
position:absolute;
|
||||||
|
visibility: hidden;
|
||||||
|
word-wrap: break-word;
|
||||||
|
-webkit-transition: all 0.5s;
|
||||||
|
-moz-transition: all 0.5s;
|
||||||
|
-ms-transition: all 0.5s;
|
||||||
|
-o-transition: all 0.5s;
|
||||||
|
transition: all 0.5s;
|
||||||
|
}
|
BIN
files_reader/img/book.png
Normal file
BIN
files_reader/img/book.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
files_reader/img/loading.gif
Normal file
BIN
files_reader/img/loading.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
7406
files_reader/js/epub.js
Normal file
7406
files_reader/js/epub.js
Normal file
File diff suppressed because one or more lines are too long
4
files_reader/js/epub.min.js
vendored
Normal file
4
files_reader/js/epub.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
2
files_reader/js/hooks.min.js
vendored
Normal file
2
files_reader/js/hooks.min.js
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
EPUBJS.Hooks.register("beforeChapterDisplay").endnotes=function(a,b){var c=b.contents.querySelectorAll("a[href]"),d=Array.prototype.slice.call(c),e="epub:type",f="noteref",g=EPUBJS.core.folder(location.pathname),h=g+EPUBJS.cssPath||g,i={};EPUBJS.core.addCss(h+"popup.css",!1,b.render.document.head),d.forEach(function(a){function c(){var c,e,f=b.height,j=b.width,p=225;o||(c=l.cloneNode(!0),o=c.querySelector("p")),i[k]||(i[k]=document.createElement("div"),i[k].setAttribute("class","popup"),pop_content=document.createElement("div"),i[k].appendChild(pop_content),pop_content.appendChild(o),pop_content.setAttribute("class","pop_content"),b.render.document.body.appendChild(i[k]),i[k].addEventListener("mouseover",d,!1),i[k].addEventListener("mouseout",g,!1),b.on("renderer:pageChanged",h,this),b.on("renderer:pageChanged",g,this)),c=i[k],e=a.getBoundingClientRect(),m=e.left,n=e.top,c.classList.add("show"),popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width/2+"px",c.style.top=n+"px",p>f/2.5&&(p=f/2.5,pop_content.style.maxHeight=p+"px"),popRect.height+n>=f-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),m-popRect.width<=0?(c.style.left=m+"px",c.classList.add("left")):c.classList.remove("left"),m+popRect.width/2>=j?(c.style.left=m-300+"px",popRect=c.getBoundingClientRect(),c.style.left=m-popRect.width+"px",popRect.height+n>=f-25?(c.style.top=n-popRect.height+"px",c.classList.add("above")):c.classList.remove("above"),c.classList.add("right")):c.classList.remove("right")}function d(){i[k].classList.add("on")}function g(){i[k].classList.remove("on")}function h(){setTimeout(function(){i[k].classList.remove("show")},100)}var j,k,l,m,n,o,p=a.getAttribute(e);p==f&&(j=a.getAttribute("href"),k=j.replace("#",""),l=b.render.document.getElementById(k),a.addEventListener("mouseover",c,!1),a.addEventListener("mouseout",h,!1))}),a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").mathml=function(a,b){if(-1!==b.currentChapter.manifestProperties.indexOf("mathml")){b.iframe.contentWindow.mathmlCallback=a;var c=document.createElement("script");c.type="text/x-mathjax-config",c.innerHTML=' MathJax.Hub.Register.StartupHook("End",function () { window.mathmlCallback(); }); MathJax.Hub.Config({jax: ["input/TeX","input/MathML","output/SVG"],extensions: ["tex2jax.js","mml2jax.js","MathEvents.js"],TeX: {extensions: ["noErrors.js","noUndefined.js","autoload-all.js"]},MathMenu: {showRenderer: false},menuSettings: {zoom: "Click"},messageStyle: "none"}); ',b.doc.body.appendChild(c),EPUBJS.core.addScript("http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML",null,b.doc.head)}else a&&a()},EPUBJS.Hooks.register("beforeChapterDisplay").smartimages=function(a,b){var c=b.contents.querySelectorAll("img"),d=Array.prototype.slice.call(c),e=b.height;return"reflowable"!=b.layoutSettings.layout?void a():(d.forEach(function(a){function c(){var c,d=a.getBoundingClientRect(),f=d.height,g=d.top,h=a.getAttribute("data-height"),i=h||f,j=Number(getComputedStyle(a,"").fontSize.match(/(\d*(\.\d*)?)px/)[1]),k=j?j/2:0;e=b.contents.clientHeight,0>g&&(g=0),i+g>=e?(e/2>g?(c=e-g-k,a.style.maxHeight=c+"px",a.style.width="auto"):(i>e&&(a.style.maxHeight=e+"px",a.style.width="auto",d=a.getBoundingClientRect(),i=d.height),a.style.display="block",a.style.WebkitColumnBreakBefore="always",a.style.breakBefore="column"),a.setAttribute("data-height",c)):(a.style.removeProperty("max-height"),a.style.removeProperty("margin-top"))}a.addEventListener("load",c,!1),b.on("renderer:resized",c),b.on("renderer:chapterUnloaded",function(){a.removeEventListener("load",c),b.off("renderer:resized",c)}),c()}),void(a&&a()))},EPUBJS.Hooks.register("beforeChapterDisplay").transculsions=function(a,b){var c=b.contents.querySelectorAll("[transclusion]"),d=Array.prototype.slice.call(c);d.forEach(function(a){function c(){j=g,k=h,j>chapter.colWidth&&(d=chapter.colWidth/j,j=chapter.colWidth,k*=d),f.width=j,f.height=k}var d,e=a.getAttribute("ref"),f=document.createElement("iframe"),g=a.getAttribute("width"),h=a.getAttribute("height"),i=a.parentNode,j=g,k=h;c(),b.listenUntil("renderer:resized","renderer:chapterUnloaded",c),f.src=e,i.replaceChild(f,a)}),a&&a()};
|
||||||
|
//# sourceMappingURL=hooks.min.map
|
14
files_reader/js/hooks/extensions/highlight.js
Normal file
14
files_reader/js/hooks/extensions/highlight.js
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
EPUBJS.Hooks.register("beforeChapterDisplay").highlight = function(callback, renderer){
|
||||||
|
|
||||||
|
// EPUBJS.core.addScript("js/libs/jquery.highlight.js", null, renderer.doc.head);
|
||||||
|
|
||||||
|
var s = document.createElement("style");
|
||||||
|
s.innerHTML =".highlight { background: yellow; font-weight: normal; }";
|
||||||
|
|
||||||
|
renderer.render.document.head.appendChild(s);
|
||||||
|
|
||||||
|
if(callback) callback();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
31
files_reader/js/libs/blob.js
Normal file
31
files_reader/js/libs/blob.js
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
Blob = (function() {
|
||||||
|
var nativeBlob = Blob;
|
||||||
|
|
||||||
|
// Add unprefixed slice() method.
|
||||||
|
if (Blob.prototype.webkitSlice) {
|
||||||
|
Blob.prototype.slice = Blob.prototype.webkitSlice;
|
||||||
|
}
|
||||||
|
else if (Blob.prototype.mozSlice) {
|
||||||
|
Blob.prototype.slice = Blob.prototype.mozSlice;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Temporarily replace Blob() constructor with one that checks support.
|
||||||
|
return function(parts, properties) {
|
||||||
|
try {
|
||||||
|
// Restore native Blob() constructor, so this check is only evaluated once.
|
||||||
|
Blob = nativeBlob;
|
||||||
|
return new Blob(parts || [], properties || {});
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// If construction fails provide one that uses BlobBuilder.
|
||||||
|
Blob = function (parts, properties) {
|
||||||
|
var bb = new (WebKitBlobBuilder || MozBlobBuilder), i;
|
||||||
|
for (i in parts) {
|
||||||
|
bb.append(parts[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bb.getBlob(properties && properties.type ? properties.type : undefined);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}());
|
2163
files_reader/js/libs/inflate.js
Normal file
2163
files_reader/js/libs/inflate.js
Normal file
File diff suppressed because it is too large
Load diff
4
files_reader/js/libs/jquery-2.1.0.min.js
vendored
Normal file
4
files_reader/js/libs/jquery-2.1.0.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
files_reader/js/libs/jquery.finger.0.1.2.js
Normal file
4
files_reader/js/libs/jquery.finger.0.1.2.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
/*! 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);
|
108
files_reader/js/libs/jquery.highlight.js
Normal file
108
files_reader/js/libs/jquery.highlight.js
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* jQuery Highlight plugin
|
||||||
|
*
|
||||||
|
* Based on highlight v3 by Johann Burkard
|
||||||
|
* http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
|
||||||
|
*
|
||||||
|
* Code a little bit refactored and cleaned (in my humble opinion).
|
||||||
|
* Most important changes:
|
||||||
|
* - has an option to highlight only entire words (wordsOnly - false by default),
|
||||||
|
* - has an option to be case sensitive (caseSensitive - false by default)
|
||||||
|
* - highlight element tag and class names can be specified in options
|
||||||
|
*
|
||||||
|
* Usage:
|
||||||
|
* // wrap every occurrance of text 'lorem' in content
|
||||||
|
* // with <span class='highlight'> (default options)
|
||||||
|
* $('#content').highlight('lorem');
|
||||||
|
*
|
||||||
|
* // search for and highlight more terms at once
|
||||||
|
* // so you can save some time on traversing DOM
|
||||||
|
* $('#content').highlight(['lorem', 'ipsum']);
|
||||||
|
* $('#content').highlight('lorem ipsum');
|
||||||
|
*
|
||||||
|
* // search only for entire word 'lorem'
|
||||||
|
* $('#content').highlight('lorem', { wordsOnly: true });
|
||||||
|
*
|
||||||
|
* // don't ignore case during search of term 'lorem'
|
||||||
|
* $('#content').highlight('lorem', { caseSensitive: true });
|
||||||
|
*
|
||||||
|
* // wrap every occurrance of term 'ipsum' in content
|
||||||
|
* // with <em class='important'>
|
||||||
|
* $('#content').highlight('ipsum', { element: 'em', className: 'important' });
|
||||||
|
*
|
||||||
|
* // remove default highlight
|
||||||
|
* $('#content').unhighlight();
|
||||||
|
*
|
||||||
|
* // remove custom highlight
|
||||||
|
* $('#content').unhighlight({ element: 'em', className: 'important' });
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Copyright (c) 2009 Bartek Szopka
|
||||||
|
*
|
||||||
|
* Licensed under MIT license.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
jQuery.extend({
|
||||||
|
highlight: function (node, re, nodeName, className) {
|
||||||
|
if (node.nodeType === 3) {
|
||||||
|
var match = node.data.match(re);
|
||||||
|
if (match) {
|
||||||
|
var highlight = document.createElement(nodeName || 'span');
|
||||||
|
highlight.className = className || 'highlight';
|
||||||
|
var wordNode = node.splitText(match.index);
|
||||||
|
wordNode.splitText(match[0].length);
|
||||||
|
var wordClone = wordNode.cloneNode(true);
|
||||||
|
highlight.appendChild(wordClone);
|
||||||
|
wordNode.parentNode.replaceChild(highlight, wordNode);
|
||||||
|
return 1; //skip added node in parent
|
||||||
|
}
|
||||||
|
} else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
|
||||||
|
!/(script|style)/i.test(node.tagName) && // ignore script and style nodes
|
||||||
|
!(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
|
||||||
|
for (var i = 0; i < node.childNodes.length; i++) {
|
||||||
|
i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
jQuery.fn.unhighlight = function (options) {
|
||||||
|
var settings = { className: 'highlight', element: 'span' };
|
||||||
|
jQuery.extend(settings, options);
|
||||||
|
|
||||||
|
return this.find(settings.element + "." + settings.className).each(function () {
|
||||||
|
var parent = this.parentNode;
|
||||||
|
parent.replaceChild(this.firstChild, this);
|
||||||
|
parent.normalize();
|
||||||
|
}).end();
|
||||||
|
};
|
||||||
|
|
||||||
|
jQuery.fn.highlight = function (words, options) {
|
||||||
|
var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
|
||||||
|
jQuery.extend(settings, options);
|
||||||
|
|
||||||
|
if (words.constructor === String) {
|
||||||
|
words = [words];
|
||||||
|
}
|
||||||
|
words = jQuery.grep(words, function(word, i){
|
||||||
|
return word != '';
|
||||||
|
});
|
||||||
|
words = jQuery.map(words, function(word, i) {
|
||||||
|
return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||||
|
});
|
||||||
|
if (words.length == 0) { return this; };
|
||||||
|
|
||||||
|
var flag = settings.caseSensitive ? "" : "i";
|
||||||
|
var pattern = "(" + words.join("|") + ")";
|
||||||
|
if (settings.wordsOnly) {
|
||||||
|
pattern = "\\b" + pattern + "\\b";
|
||||||
|
}
|
||||||
|
var re = new RegExp(pattern, flag);
|
||||||
|
|
||||||
|
return this.each(function () {
|
||||||
|
jQuery.highlight(this, re, settings.element, settings.className);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
1001
files_reader/js/libs/mime-types.js
Normal file
1001
files_reader/js/libs/mime-types.js
Normal file
File diff suppressed because it is too large
Load diff
7
files_reader/js/libs/screenfull.min.js
vendored
Normal file
7
files_reader/js/libs/screenfull.min.js
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
/*!
|
||||||
|
* screenfull
|
||||||
|
* v1.1.0 - 2013-09-06
|
||||||
|
* https://github.com/sindresorhus/screenfull.js
|
||||||
|
* (c) Sindre Sorhus; MIT License
|
||||||
|
*/
|
||||||
|
!function(a,b){"use strict";var c="undefined"!=typeof Element&&"ALLOW_KEYBOARD_INPUT"in Element,d=function(){for(var a,c,d=[["requestFullscreen","exitFullscreen","fullscreenElement","fullscreenEnabled","fullscreenchange","fullscreenerror"],["webkitRequestFullscreen","webkitExitFullscreen","webkitFullscreenElement","webkitFullscreenEnabled","webkitfullscreenchange","webkitfullscreenerror"],["webkitRequestFullScreen","webkitCancelFullScreen","webkitCurrentFullScreenElement","webkitCancelFullScreen","webkitfullscreenchange","webkitfullscreenerror"],["mozRequestFullScreen","mozCancelFullScreen","mozFullScreenElement","mozFullScreenEnabled","mozfullscreenchange","mozfullscreenerror"],["msRequestFullscreen","msExitFullscreen","msFullscreenElement","msFullscreenEnabled","MSFullscreenchange","MSFullscreenerror"]],e=0,f=d.length,g={};f>e;e++)if(a=d[e],a&&a[1]in b){for(e=0,c=a.length;c>e;e++)g[d[0][e]]=a[e];return g}return!1}(),e={request:function(a){var e=d.requestFullscreen;a=a||b.documentElement,/5\.1[\.\d]* Safari/.test(navigator.userAgent)?a[e]():a[e](c&&Element.ALLOW_KEYBOARD_INPUT)},exit:function(){b[d.exitFullscreen]()},toggle:function(a){this.isFullscreen?this.exit():this.request(a)},onchange:function(){},onerror:function(){},raw:d};return d?(Object.defineProperties(e,{isFullscreen:{get:function(){return!!b[d.fullscreenElement]}},element:{enumerable:!0,get:function(){return b[d.fullscreenElement]}},enabled:{enumerable:!0,get:function(){return!!b[d.fullscreenEnabled]}}}),b.addEventListener(d.fullscreenchange,function(a){e.onchange.call(e,a)}),b.addEventListener(d.fullscreenerror,function(a){e.onerror.call(e,a)}),a.screenfull=e,void 0):(a.screenfull=!1,void 0)}(window,document);
|
629
files_reader/js/libs/typedarray.js
Normal file
629
files_reader/js/libs/typedarray.js
Normal file
|
@ -0,0 +1,629 @@
|
||||||
|
/*
|
||||||
|
$LicenseInfo:firstyear=2010&license=mit$
|
||||||
|
|
||||||
|
Copyright (c) 2010, Linden Research, Inc.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
THE SOFTWARE.
|
||||||
|
$/LicenseInfo$
|
||||||
|
*/
|
||||||
|
/*global document*/
|
||||||
|
|
||||||
|
//
|
||||||
|
// ES3/ES5 implementation of the Krhonos TypedArray Working Draft (work in progress):
|
||||||
|
// Ref: https://cvs.khronos.org/svn/repos/registry/trunk/public/webgl/doc/spec/TypedArray-spec.html
|
||||||
|
// Date: 2011-02-01
|
||||||
|
//
|
||||||
|
// Variations:
|
||||||
|
// * Float/Double -> Float32/Float64, per WebGL-Public mailing list conversations (post 5/17)
|
||||||
|
// * Allows typed_array.get/set() as alias for subscripts (typed_array[])
|
||||||
|
|
||||||
|
var ArrayBuffer, ArrayBufferView,
|
||||||
|
Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array,
|
||||||
|
DataView;
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
/*jslint bitwise: false, nomen: false */
|
||||||
|
|
||||||
|
// Approximations of internal ECMAScript conversion functions
|
||||||
|
var ECMAScript = {
|
||||||
|
ToInt32: function (v) { return v >> 0; },
|
||||||
|
ToUint32: function (v) { return v >>> 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Raise an INDEX_SIZE_ERR event - intentionally induces a DOM error
|
||||||
|
function raise_INDEX_SIZE_ERR() {
|
||||||
|
if (document) {
|
||||||
|
// raises DOMException(INDEX_SIZE_ERR)
|
||||||
|
document.createTextNode("").splitText(1);
|
||||||
|
}
|
||||||
|
throw new RangeError("INDEX_SIZE_ERR");
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES5: lock down object properties
|
||||||
|
function configureProperties(obj) {
|
||||||
|
if (Object.getOwnPropertyNames && Object.defineProperty) {
|
||||||
|
var props = Object.getOwnPropertyNames(obj), i;
|
||||||
|
for (i = 0; i < props.length; i += 1) {
|
||||||
|
Object.defineProperty(obj, props[i], {
|
||||||
|
value: obj[props[i]],
|
||||||
|
writable: false,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// emulate ES5 getter/setter API using legacy APIs
|
||||||
|
// http://blogs.msdn.com/b/ie/archive/2010/09/07/transitioning-existing-code-to-the-es5-getter-setter-apis.aspx
|
||||||
|
if (Object.prototype.__defineGetter__ && !Object.defineProperty) {
|
||||||
|
Object.defineProperty = function (obj, prop, desc) {
|
||||||
|
if (desc.hasOwnProperty('get')) { obj.__defineGetter__(prop, desc.get); }
|
||||||
|
if (desc.hasOwnProperty('set')) { obj.__defineSetter__(prop, desc.set); }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES5: Make obj[index] an alias for obj._getter(index)/obj._setter(index, value)
|
||||||
|
// for index in 0 ... obj.length
|
||||||
|
function makeArrayAccessors(obj) {
|
||||||
|
if (!Object.defineProperty) { return; }
|
||||||
|
|
||||||
|
function makeArrayAccessor(index) {
|
||||||
|
Object.defineProperty(obj, index, {
|
||||||
|
'get': function () { return obj._getter(index); },
|
||||||
|
'set': function (v) { obj._setter(index, v); },
|
||||||
|
enumerable: true,
|
||||||
|
configurable: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < obj.length; i += 1) {
|
||||||
|
makeArrayAccessor(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal conversion functions:
|
||||||
|
// pack<Type>() - take a number (interpreted as Type), output a byte array
|
||||||
|
// unpack<Type>() - take a byte array, output a Type-like number
|
||||||
|
|
||||||
|
function as_signed(value, bits) { var s = 32 - bits; return (value << s) >> s; }
|
||||||
|
function as_unsigned(value, bits) { var s = 32 - bits; return (value << s) >>> s; }
|
||||||
|
|
||||||
|
function packInt8(n) { return [n & 0xff]; }
|
||||||
|
function unpackInt8(bytes) { return as_signed(bytes[0], 8); }
|
||||||
|
|
||||||
|
function packUint8(n) { return [n & 0xff]; }
|
||||||
|
function unpackUint8(bytes) { return as_unsigned(bytes[0], 8); }
|
||||||
|
|
||||||
|
function packInt16(n) { return [(n >> 8) & 0xff, n & 0xff]; }
|
||||||
|
function unpackInt16(bytes) { return as_signed(bytes[0] << 8 | bytes[1], 16); }
|
||||||
|
|
||||||
|
function packUint16(n) { return [(n >> 8) & 0xff, n & 0xff]; }
|
||||||
|
function unpackUint16(bytes) { return as_unsigned(bytes[0] << 8 | bytes[1], 16); }
|
||||||
|
|
||||||
|
function packInt32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; }
|
||||||
|
function unpackInt32(bytes) { return as_signed(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); }
|
||||||
|
|
||||||
|
function packUint32(n) { return [(n >> 24) & 0xff, (n >> 16) & 0xff, (n >> 8) & 0xff, n & 0xff]; }
|
||||||
|
function unpackUint32(bytes) { return as_unsigned(bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3], 32); }
|
||||||
|
|
||||||
|
function packIEEE754(v, ebits, fbits) {
|
||||||
|
|
||||||
|
var bias = (1 << (ebits - 1)) - 1,
|
||||||
|
s, e, f, ln,
|
||||||
|
i, bits, str, bytes;
|
||||||
|
|
||||||
|
// Compute sign, exponent, fraction
|
||||||
|
if (isNaN(v)) {
|
||||||
|
// http://dev.w3.org/2006/webapi/WebIDL/#es-type-mapping
|
||||||
|
e = (1 << bias) - 1; f = Math.pow(2, fbits - 1); s = 0;
|
||||||
|
}
|
||||||
|
else if (v === Infinity || v === -Infinity) {
|
||||||
|
e = (1 << bias) - 1; f = 0; s = (v < 0) ? 1 : 0;
|
||||||
|
}
|
||||||
|
else if (v === 0) {
|
||||||
|
e = 0; f = 0; s = (1 / v === -Infinity) ? 1 : 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
s = v < 0;
|
||||||
|
v = Math.abs(v);
|
||||||
|
|
||||||
|
if (v >= Math.pow(2, 1 - bias)) {
|
||||||
|
// Normalized
|
||||||
|
ln = Math.min(Math.floor(Math.log(v) / Math.LN2), bias);
|
||||||
|
e = ln + bias;
|
||||||
|
f = Math.round(v * Math.pow(2, fbits - ln) - Math.pow(2, fbits));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Denormalized
|
||||||
|
e = 0;
|
||||||
|
f = Math.round(v / Math.pow(2, 1 - bias - fbits));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pack sign, exponent, fraction
|
||||||
|
bits = [];
|
||||||
|
for (i = fbits; i; i -= 1) { bits.push(f % 2 ? 1 : 0); f = Math.floor(f / 2); }
|
||||||
|
for (i = ebits; i; i -= 1) { bits.push(e % 2 ? 1 : 0); e = Math.floor(e / 2); }
|
||||||
|
bits.push(s ? 1 : 0);
|
||||||
|
bits.reverse();
|
||||||
|
str = bits.join('');
|
||||||
|
|
||||||
|
// Bits to bytes
|
||||||
|
bytes = [];
|
||||||
|
while (str.length) {
|
||||||
|
bytes.push(parseInt(str.substring(0, 8), 2));
|
||||||
|
str = str.substring(8);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpackIEEE754(bytes, ebits, fbits) {
|
||||||
|
|
||||||
|
// Bytes to bits
|
||||||
|
var bits = [], i, j, b, str,
|
||||||
|
bias, s, e, f;
|
||||||
|
|
||||||
|
for (i = bytes.length; i; i -= 1) {
|
||||||
|
b = bytes[i - 1];
|
||||||
|
for (j = 8; j; j -= 1) {
|
||||||
|
bits.push(b % 2 ? 1 : 0); b = b >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bits.reverse();
|
||||||
|
str = bits.join('');
|
||||||
|
|
||||||
|
// Unpack sign, exponent, fraction
|
||||||
|
bias = (1 << (ebits - 1)) - 1;
|
||||||
|
s = parseInt(str.substring(0, 1), 2) ? -1 : 1;
|
||||||
|
e = parseInt(str.substring(1, 1 + ebits), 2);
|
||||||
|
f = parseInt(str.substring(1 + ebits), 2);
|
||||||
|
|
||||||
|
// Produce number
|
||||||
|
if (e === (1 << ebits) - 1) {
|
||||||
|
return f !== 0 ? NaN : s * Infinity;
|
||||||
|
}
|
||||||
|
else if (e > 0) {
|
||||||
|
// Normalized
|
||||||
|
return s * Math.pow(2, e - bias) * (1 + f / Math.pow(2, fbits));
|
||||||
|
}
|
||||||
|
else if (f !== 0) {
|
||||||
|
// Denormalized
|
||||||
|
return s * Math.pow(2, -(bias - 1)) * (f / Math.pow(2, fbits));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return s < 0 ? -0 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unpackFloat64(b) { return unpackIEEE754(b, 11, 52); }
|
||||||
|
function packFloat64(v) { return packIEEE754(v, 11, 52); }
|
||||||
|
function unpackFloat32(b) { return unpackIEEE754(b, 8, 23); }
|
||||||
|
function packFloat32(v) { return packIEEE754(v, 8, 23); }
|
||||||
|
|
||||||
|
|
||||||
|
if (!ArrayBuffer) {
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
//
|
||||||
|
// 3 The ArrayBuffer Type
|
||||||
|
//
|
||||||
|
|
||||||
|
ArrayBuffer = function (length) {
|
||||||
|
length = ECMAScript.ToInt32(length);
|
||||||
|
if (length < 0) { throw new RangeError('ArrayBuffer size is not a small enough positive integer.'); }
|
||||||
|
|
||||||
|
this.byteLength = length;
|
||||||
|
this._bytes = [];
|
||||||
|
this._bytes.length = length;
|
||||||
|
|
||||||
|
var i;
|
||||||
|
for (i = 0; i < this.byteLength; i += 1) {
|
||||||
|
this._bytes[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
configureProperties(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 4 The ArrayBufferView Type
|
||||||
|
//
|
||||||
|
|
||||||
|
// NOTE: this constructor is not exported
|
||||||
|
ArrayBufferView = function () {
|
||||||
|
//this.buffer = null;
|
||||||
|
//this.byteOffset = 0;
|
||||||
|
//this.byteLength = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// 5 The Typed Array View Types
|
||||||
|
//
|
||||||
|
|
||||||
|
function makeTypedArrayConstructor(bytesPerElement, pack, unpack) {
|
||||||
|
// Each TypedArray type requires a distinct constructor instance with
|
||||||
|
// identical logic, which this produces.
|
||||||
|
|
||||||
|
var ctor;
|
||||||
|
ctor = function (buffer, byteOffset, length) {
|
||||||
|
var array, sequence, i, s;
|
||||||
|
|
||||||
|
// Constructor(unsigned long length)
|
||||||
|
if (!arguments.length || typeof arguments[0] === 'number') {
|
||||||
|
this.length = ECMAScript.ToInt32(arguments[0]);
|
||||||
|
if (length < 0) { throw new RangeError('ArrayBufferView size is not a small enough positive integer.'); }
|
||||||
|
|
||||||
|
this.byteLength = this.length * this.BYTES_PER_ELEMENT;
|
||||||
|
this.buffer = new ArrayBuffer(this.byteLength);
|
||||||
|
this.byteOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor(TypedArray array)
|
||||||
|
else if (typeof arguments[0] === 'object' && arguments[0].constructor === ctor) {
|
||||||
|
array = arguments[0];
|
||||||
|
|
||||||
|
this.length = array.length;
|
||||||
|
this.byteLength = this.length * this.BYTES_PER_ELEMENT;
|
||||||
|
this.buffer = new ArrayBuffer(this.byteLength);
|
||||||
|
this.byteOffset = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < this.length; i += 1) {
|
||||||
|
this._setter(i, array._getter(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor(sequence<type> array)
|
||||||
|
else if (typeof arguments[0] === 'object' && !(arguments[0] instanceof ArrayBuffer)) {
|
||||||
|
sequence = arguments[0];
|
||||||
|
|
||||||
|
this.length = ECMAScript.ToUint32(sequence.length);
|
||||||
|
this.byteLength = this.length * this.BYTES_PER_ELEMENT;
|
||||||
|
this.buffer = new ArrayBuffer(this.byteLength);
|
||||||
|
this.byteOffset = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < this.length; i += 1) {
|
||||||
|
s = sequence[i];
|
||||||
|
this._setter(i, Number(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor(ArrayBuffer buffer,
|
||||||
|
// optional unsigned long byteOffset, optional unsigned long length)
|
||||||
|
else if (typeof arguments[0] === 'object' && arguments[0] instanceof ArrayBuffer) {
|
||||||
|
this.buffer = buffer;
|
||||||
|
|
||||||
|
this.byteOffset = ECMAScript.ToUint32(byteOffset);
|
||||||
|
if (this.byteOffset > this.buffer.byteLength) {
|
||||||
|
raise_INDEX_SIZE_ERR(); // byteOffset out of range
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.byteOffset % this.BYTES_PER_ELEMENT) {
|
||||||
|
// The given byteOffset must be a multiple of the element
|
||||||
|
// size of the specific type, otherwise an exception is raised.
|
||||||
|
//raise_INDEX_SIZE_ERR();
|
||||||
|
throw new RangeError("ArrayBuffer length minus the byteOffset is not a multiple of the element size.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.length < 3) {
|
||||||
|
this.byteLength = this.buffer.byteLength - this.byteOffset;
|
||||||
|
|
||||||
|
if (this.byteLength % this.BYTES_PER_ELEMENT) {
|
||||||
|
raise_INDEX_SIZE_ERR(); // length of buffer minus byteOffset not a multiple of the element size
|
||||||
|
}
|
||||||
|
this.length = this.byteLength / this.BYTES_PER_ELEMENT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.length = ECMAScript.ToUint32(length);
|
||||||
|
this.byteLength = this.length * this.BYTES_PER_ELEMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) {
|
||||||
|
raise_INDEX_SIZE_ERR(); // byteOffset and length reference an area beyond the end of the buffer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new TypeError("Unexpected argument type(s)");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.constructor = ctor;
|
||||||
|
|
||||||
|
// ES5-only magic
|
||||||
|
configureProperties(this);
|
||||||
|
makeArrayAccessors(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
ctor.prototype = new ArrayBufferView();
|
||||||
|
ctor.prototype.BYTES_PER_ELEMENT = bytesPerElement;
|
||||||
|
ctor.prototype._pack = pack;
|
||||||
|
ctor.prototype._unpack = unpack;
|
||||||
|
ctor.BYTES_PER_ELEMENT = bytesPerElement;
|
||||||
|
|
||||||
|
// getter type (unsigned long index);
|
||||||
|
ctor.prototype._getter = function (index) {
|
||||||
|
if (arguments.length < 1) { throw new SyntaxError("Not enough arguments"); }
|
||||||
|
|
||||||
|
index = ECMAScript.ToUint32(index);
|
||||||
|
if (index >= this.length) {
|
||||||
|
//raise_INDEX_SIZE_ERR(); // Array index out of range
|
||||||
|
return; // undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytes = [], i, o;
|
||||||
|
for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT;
|
||||||
|
i < this.BYTES_PER_ELEMENT;
|
||||||
|
i += 1, o += 1) {
|
||||||
|
bytes.push(this.buffer._bytes[o]);
|
||||||
|
}
|
||||||
|
return this._unpack(bytes);
|
||||||
|
};
|
||||||
|
|
||||||
|
// NONSTANDARD: convenience alias for getter: type get(unsigned long index);
|
||||||
|
ctor.prototype.get = ctor.prototype._getter;
|
||||||
|
|
||||||
|
// setter void (unsigned long index, type value);
|
||||||
|
ctor.prototype._setter = function (index, value) {
|
||||||
|
if (arguments.length < 2) { throw new SyntaxError("Not enough arguments"); }
|
||||||
|
|
||||||
|
index = ECMAScript.ToUint32(index);
|
||||||
|
if (index >= this.length) {
|
||||||
|
//raise_INDEX_SIZE_ERR(); // Array index out of range
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bytes = this._pack(value), i, o;
|
||||||
|
for (i = 0, o = this.byteOffset + index * this.BYTES_PER_ELEMENT;
|
||||||
|
i < this.BYTES_PER_ELEMENT;
|
||||||
|
i += 1, o += 1) {
|
||||||
|
this.buffer._bytes[o] = bytes[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// void set(TypedArray array, optional unsigned long offset);
|
||||||
|
// void set(sequence<type> array, optional unsigned long offset);
|
||||||
|
ctor.prototype.set = function (index, value) {
|
||||||
|
if (arguments.length < 1) { throw new SyntaxError("Not enough arguments"); }
|
||||||
|
var array, sequence, offset, len,
|
||||||
|
i, s, d,
|
||||||
|
byteOffset, byteLength, tmp;
|
||||||
|
|
||||||
|
// void set(TypedArray array, optional unsigned long offset);
|
||||||
|
if (typeof arguments[0] === 'object' && arguments[0].constructor === this.constructor) {
|
||||||
|
array = arguments[0];
|
||||||
|
offset = ECMAScript.ToUint32(arguments[1]);
|
||||||
|
|
||||||
|
if (offset + array.length > this.length) {
|
||||||
|
raise_INDEX_SIZE_ERR(); // Offset plus length of array is out of range
|
||||||
|
}
|
||||||
|
|
||||||
|
byteOffset = this.byteOffset + offset * this.BYTES_PER_ELEMENT;
|
||||||
|
byteLength = array.length * this.BYTES_PER_ELEMENT;
|
||||||
|
|
||||||
|
if (array.buffer === this.buffer) {
|
||||||
|
tmp = [];
|
||||||
|
for (i = 0, s = array.byteOffset; i < byteLength; i += 1, s += 1) {
|
||||||
|
tmp[i] = array.buffer._bytes[s];
|
||||||
|
}
|
||||||
|
for (i = 0, d = byteOffset; i < byteLength; i += 1, d += 1) {
|
||||||
|
this.buffer._bytes[d] = tmp[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (i = 0, s = array.byteOffset, d = byteOffset;
|
||||||
|
i < byteLength; i += 1, s += 1, d += 1) {
|
||||||
|
this.buffer._bytes[d] = array.buffer._bytes[s];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// void set(sequence<type> array, optional unsigned long offset);
|
||||||
|
else if (typeof arguments[0] === 'object' && typeof arguments[0].length !== 'undefined') {
|
||||||
|
sequence = arguments[0];
|
||||||
|
len = ECMAScript.ToUint32(sequence.length);
|
||||||
|
offset = ECMAScript.ToUint32(arguments[1]);
|
||||||
|
|
||||||
|
if (offset + len > this.length) {
|
||||||
|
raise_INDEX_SIZE_ERR(); // Offset plus length of array is out of range
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < len; i += 1) {
|
||||||
|
s = sequence[i];
|
||||||
|
this._setter(offset + i, Number(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
throw new TypeError("Unexpected argument type(s)");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// TypedArray subarray(long begin, optional long end);
|
||||||
|
ctor.prototype.subarray = function (start, end) {
|
||||||
|
function clamp(v, min, max) { return v < min ? min : v > max ? max : v; }
|
||||||
|
|
||||||
|
start = ECMAScript.ToInt32(start);
|
||||||
|
end = ECMAScript.ToInt32(end);
|
||||||
|
|
||||||
|
if (arguments.length < 1) { start = 0; }
|
||||||
|
if (arguments.length < 2) { end = this.length; }
|
||||||
|
|
||||||
|
if (start < 0) { start = this.length + start; }
|
||||||
|
if (end < 0) { end = this.length + end; }
|
||||||
|
|
||||||
|
start = clamp(start, 0, this.length);
|
||||||
|
end = clamp(end, 0, this.length);
|
||||||
|
|
||||||
|
var len = end - start;
|
||||||
|
if (len < 0) {
|
||||||
|
len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new this.constructor(this.buffer, start * this.BYTES_PER_ELEMENT, len);
|
||||||
|
};
|
||||||
|
|
||||||
|
return ctor;
|
||||||
|
}
|
||||||
|
|
||||||
|
Int8Array = Int8Array || makeTypedArrayConstructor(1, packInt8, unpackInt8);
|
||||||
|
Uint8Array = Uint8Array || makeTypedArrayConstructor(1, packUint8, unpackUint8);
|
||||||
|
Int16Array = Int16Array || makeTypedArrayConstructor(2, packInt16, unpackInt16);
|
||||||
|
Uint16Array = Uint16Array || makeTypedArrayConstructor(2, packUint16, unpackUint16);
|
||||||
|
Int32Array = Int32Array || makeTypedArrayConstructor(4, packInt32, unpackInt32);
|
||||||
|
Uint32Array = Uint32Array || makeTypedArrayConstructor(4, packUint32, unpackUint32);
|
||||||
|
Float32Array = Float32Array || makeTypedArrayConstructor(4, packFloat32, unpackFloat32);
|
||||||
|
Float64Array = Float64Array || makeTypedArrayConstructor(8, packFloat64, unpackFloat64);
|
||||||
|
|
||||||
|
} ());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (!DataView) {
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
//
|
||||||
|
// 6 The DataView View Type
|
||||||
|
//
|
||||||
|
|
||||||
|
function r(array, index) {
|
||||||
|
if (typeof array.get === 'function') {
|
||||||
|
return array.get(index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return array[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var IS_BIG_ENDIAN = (function () {
|
||||||
|
var u16array = new Uint16Array([0x1234]),
|
||||||
|
u8array = new Uint8Array(u16array.buffer);
|
||||||
|
return r(u8array, 0) === 0x12;
|
||||||
|
} ());
|
||||||
|
|
||||||
|
// Constructor(ArrayBuffer buffer,
|
||||||
|
// optional unsigned long byteOffset,
|
||||||
|
// optional unsigned long byteLength)
|
||||||
|
DataView = function (buffer, byteOffset, byteLength) {
|
||||||
|
if (!(typeof buffer === 'object' && buffer instanceof ArrayBuffer)) {
|
||||||
|
throw new TypeError("TypeError");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.buffer = buffer;
|
||||||
|
|
||||||
|
this.byteOffset = ECMAScript.ToUint32(byteOffset);
|
||||||
|
if (this.byteOffset > this.buffer.byteLength) {
|
||||||
|
raise_INDEX_SIZE_ERR(); // byteOffset out of range
|
||||||
|
}
|
||||||
|
|
||||||
|
if (arguments.length < 3) {
|
||||||
|
this.byteLength = this.buffer.byteLength - this.byteOffset;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.byteLength = ECMAScript.ToUint32(byteLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this.byteOffset + this.byteLength) > this.buffer.byteLength) {
|
||||||
|
raise_INDEX_SIZE_ERR(); // byteOffset and length reference an area beyond the end of the buffer
|
||||||
|
}
|
||||||
|
|
||||||
|
// ES5-only magic
|
||||||
|
configureProperties(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ArrayBufferView) {
|
||||||
|
DataView.prototype = new ArrayBufferView();
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeDataView_getter(arrayType) {
|
||||||
|
return function (byteOffset, littleEndian) {
|
||||||
|
/*jslint newcap: false*/
|
||||||
|
byteOffset = ECMAScript.ToUint32(byteOffset);
|
||||||
|
|
||||||
|
if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) {
|
||||||
|
raise_INDEX_SIZE_ERR(); // Array index out of range
|
||||||
|
}
|
||||||
|
byteOffset += this.byteOffset;
|
||||||
|
|
||||||
|
var uint8Array = new Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT),
|
||||||
|
bytes = [], i;
|
||||||
|
for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) {
|
||||||
|
bytes.push(r(uint8Array, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) {
|
||||||
|
bytes.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
return r(new arrayType(new Uint8Array(bytes).buffer), 0);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
DataView.prototype.getUint8 = makeDataView_getter(Uint8Array);
|
||||||
|
DataView.prototype.getInt8 = makeDataView_getter(Int8Array);
|
||||||
|
DataView.prototype.getUint16 = makeDataView_getter(Uint16Array);
|
||||||
|
DataView.prototype.getInt16 = makeDataView_getter(Int16Array);
|
||||||
|
DataView.prototype.getUint32 = makeDataView_getter(Uint32Array);
|
||||||
|
DataView.prototype.getInt32 = makeDataView_getter(Int32Array);
|
||||||
|
DataView.prototype.getFloat32 = makeDataView_getter(Float32Array);
|
||||||
|
DataView.prototype.getFloat64 = makeDataView_getter(Float64Array);
|
||||||
|
|
||||||
|
function makeDataView_setter(arrayType) {
|
||||||
|
return function (byteOffset, value, littleEndian) {
|
||||||
|
/*jslint newcap: false*/
|
||||||
|
byteOffset = ECMAScript.ToUint32(byteOffset);
|
||||||
|
if (byteOffset + arrayType.BYTES_PER_ELEMENT > this.byteLength) {
|
||||||
|
raise_INDEX_SIZE_ERR(); // Array index out of range
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get bytes
|
||||||
|
var typeArray = new arrayType([value]),
|
||||||
|
byteArray = new Uint8Array(typeArray.buffer),
|
||||||
|
bytes = [], i, byteView;
|
||||||
|
|
||||||
|
for (i = 0; i < arrayType.BYTES_PER_ELEMENT; i += 1) {
|
||||||
|
bytes.push(r(byteArray, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flip if necessary
|
||||||
|
if (Boolean(littleEndian) === Boolean(IS_BIG_ENDIAN)) {
|
||||||
|
bytes.reverse();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write them
|
||||||
|
byteView = new Uint8Array(this.buffer, byteOffset, arrayType.BYTES_PER_ELEMENT);
|
||||||
|
byteView.set(bytes);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
DataView.prototype.setUint8 = makeDataView_setter(Uint8Array);
|
||||||
|
DataView.prototype.setInt8 = makeDataView_setter(Int8Array);
|
||||||
|
DataView.prototype.setUint16 = makeDataView_setter(Uint16Array);
|
||||||
|
DataView.prototype.setInt16 = makeDataView_setter(Int16Array);
|
||||||
|
DataView.prototype.setUint32 = makeDataView_setter(Uint32Array);
|
||||||
|
DataView.prototype.setInt32 = makeDataView_setter(Int32Array);
|
||||||
|
DataView.prototype.setFloat32 = makeDataView_setter(Float32Array);
|
||||||
|
DataView.prototype.setFloat64 = makeDataView_setter(Float64Array);
|
||||||
|
|
||||||
|
} ());
|
||||||
|
}
|
||||||
|
|
||||||
|
} ());
|
||||||
|
|
1
files_reader/js/libs/typedarray.min.js
vendored
Normal file
1
files_reader/js/libs/typedarray.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
241
files_reader/js/libs/zip-ext.js
Normal file
241
files_reader/js/libs/zip-ext.js
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
538
files_reader/js/libs/zip-fs.js
Normal file
538
files_reader/js/libs/zip-fs.js
Normal file
|
@ -0,0 +1,538 @@
|
||||||
|
/*
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
|
||||||
|
})();
|
801
files_reader/js/libs/zip.js
Normal file
801
files_reader/js/libs/zip.js
Normal file
|
@ -0,0 +1,801 @@
|
||||||
|
/*
|
||||||
|
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);
|
30
files_reader/js/libs/zip.min.js
vendored
Normal file
30
files_reader/js/libs/zip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
85
files_reader/js/loader.js
Normal file
85
files_reader/js/loader.js
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
}();
|
125
files_reader/js/plugins/search.js
Normal file
125
files_reader/js/plugins/search.js
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
EPUBJS.reader.search = {};
|
||||||
|
|
||||||
|
// Search Server -- https://github.com/futurepress/epubjs-search
|
||||||
|
EPUBJS.reader.search.SERVER = "https://example.com/";
|
||||||
|
|
||||||
|
EPUBJS.reader.search.request = function(q, callback) {
|
||||||
|
var fetch = $.ajax({
|
||||||
|
dataType: "json",
|
||||||
|
url: EPUBJS.reader.search.SERVER + "/search?q=" + encodeURIComponent(q)
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch.fail(function(err) {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
fetch.done(function(results) {
|
||||||
|
callback(results);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
EPUBJS.reader.plugins.SearchController = function(Book) {
|
||||||
|
var reader = this;
|
||||||
|
|
||||||
|
var $searchBox = $("#searchBox"),
|
||||||
|
$searchResults = $("#searchResults"),
|
||||||
|
$searchView = $("#searchView"),
|
||||||
|
iframeDoc;
|
||||||
|
|
||||||
|
var searchShown = false;
|
||||||
|
|
||||||
|
var onShow = function() {
|
||||||
|
query();
|
||||||
|
searchShown = true;
|
||||||
|
$searchView.addClass("shown");
|
||||||
|
};
|
||||||
|
|
||||||
|
var onHide = function() {
|
||||||
|
searchShown = false;
|
||||||
|
$searchView.removeClass("shown");
|
||||||
|
};
|
||||||
|
|
||||||
|
var query = function() {
|
||||||
|
var q = $searchBox.val();
|
||||||
|
|
||||||
|
if(q == '') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$searchResults.empty();
|
||||||
|
$searchResults.append("<li><p>Searching...</p></li>");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EPUBJS.reader.search.request(q, function(data) {
|
||||||
|
var results = data.results;
|
||||||
|
|
||||||
|
$searchResults.empty();
|
||||||
|
|
||||||
|
if(iframeDoc) {
|
||||||
|
$(iframeDoc).find('body').unhighlight();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(results.length == 0) {
|
||||||
|
$searchResults.append("<li><p>No Results Found</p></li>");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
iframeDoc = $("#viewer iframe")[0].contentDocument;
|
||||||
|
$(iframeDoc).find('body').highlight(q, { element: 'span' });
|
||||||
|
|
||||||
|
results.forEach(function(result) {
|
||||||
|
var $li = $("<li></li>");
|
||||||
|
var $item = $("<a href='"+result.href+"' data-cfi='"+result.cfi+"'><span>"+result.title+"</span><p>"+result.highlight+"</p></a>");
|
||||||
|
|
||||||
|
$item.on("click", function(e) {
|
||||||
|
var $this = $(this),
|
||||||
|
cfi = $this.data("cfi");
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
Book.gotoCfi(cfi+"/1:0");
|
||||||
|
|
||||||
|
Book.on("renderer:chapterDisplayed", function() {
|
||||||
|
iframeDoc = $("#viewer iframe")[0].contentDocument;
|
||||||
|
$(iframeDoc).find('body').highlight(q, { element: 'span' });
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
});
|
||||||
|
$li.append($item);
|
||||||
|
$searchResults.append($li);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
$searchBox.on("search", function(e) {
|
||||||
|
var q = $searchBox.val();
|
||||||
|
|
||||||
|
//-- SearchBox is empty or cleared
|
||||||
|
if(q == '') {
|
||||||
|
$searchResults.empty();
|
||||||
|
if(reader.SidebarController.getActivePanel() == "Search") {
|
||||||
|
reader.SidebarController.changePanelTo("Toc");
|
||||||
|
}
|
||||||
|
|
||||||
|
$(iframeDoc).find('body').unhighlight();
|
||||||
|
iframeDoc = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader.SidebarController.changePanelTo("Search");
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
"show" : onShow,
|
||||||
|
"hide" : onHide
|
||||||
|
};
|
||||||
|
};
|
1124
files_reader/js/reader.js
Normal file
1124
files_reader/js/reader.js
Normal file
File diff suppressed because it is too large
Load diff
2
files_reader/js/reader.min.js
vendored
Normal file
2
files_reader/js/reader.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
171
files_reader/js/ready.js
Normal file
171
files_reader/js/ready.js
Normal file
|
@ -0,0 +1,171 @@
|
||||||
|
function disableStyles(doc, disable) {
|
||||||
|
for ( var i=0; i<doc.styleSheets.length; i++) {
|
||||||
|
void(doc.styleSheets.item(i).disabled=disable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function addStyleSheet() {
|
||||||
|
var style = document.createElement("style");
|
||||||
|
// WebKit hack :(
|
||||||
|
style.appendChild(document.createTextNode(""));
|
||||||
|
document.head.appendChild(style);
|
||||||
|
return style.sheet;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCSSRule(sheet, selector, del) {
|
||||||
|
lcSelector = selector.toLowerCase();
|
||||||
|
for ( var i=0; i<sheet.cssRules.length; i++) {
|
||||||
|
if (sheet.cssRules.item(i).selectorText.toLowerCase() == lcSelector) {
|
||||||
|
if (del) {
|
||||||
|
sheet.deleteRule(i);
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return sheet.cssRules.item(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCSSRule(sheet, selector, rules, index) {
|
||||||
|
if("insertRule" in sheet) {
|
||||||
|
sheet.insertRule(selector + "{" + rules + "}", index);
|
||||||
|
}
|
||||||
|
else if("addRule" in sheet) {
|
||||||
|
sheet.addRule(selector, rules, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function delCSSRule(sheet, selector) {
|
||||||
|
getCSSRule(sheet, selector, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// some parameters...
|
||||||
|
EPUBJS.filePath = "js/libs/";
|
||||||
|
EPUBJS.cssPath = "css/";
|
||||||
|
|
||||||
|
// device-specific rules
|
||||||
|
//
|
||||||
|
// webworkers...
|
||||||
|
if(!window.Worker) {
|
||||||
|
// use zip.js without webworkers, include inflate.js
|
||||||
|
zip.useWebWorkers = false;
|
||||||
|
$.getScript('js/libs/inflate.js');
|
||||||
|
} else {
|
||||||
|
zip.workerScriptsPath = document.getElementsByTagName('base')[0].href + 'js/libs/';
|
||||||
|
}
|
||||||
|
|
||||||
|
// touch-enabled devices...
|
||||||
|
$('#touch_nav').prop('checked', !('ontouchstart' in document.documentElement));
|
||||||
|
if (!($('#touch_nav').prop('checked'))) {
|
||||||
|
$("#next").addClass("touch_nav");
|
||||||
|
$("#prev").addClass("touch_nav");
|
||||||
|
}
|
||||||
|
|
||||||
|
// idevices...
|
||||||
|
if (navigator.userAgent.match(/(iPad|iPhone|iPod)/g)) {
|
||||||
|
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', document.getElementsByTagName("base").item(0).href + 'css/idevice.css'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function nightModeConfig() {
|
||||||
|
delCSSRule(EPUBJS.nightSheet, EPUBJS.nightSelector);
|
||||||
|
addCSSRule(EPUBJS.nightSheet, EPUBJS.nightSelector, 'color: ' + EPUBJS.nightModeColor + ' !important; background: ' + EPUBJS.nightModeBackground + ' !important;');
|
||||||
|
}
|
||||||
|
|
||||||
|
// nightMode
|
||||||
|
EPUBJS.nightMode = false;
|
||||||
|
EPUBJS.nightSheet = addStyleSheet();
|
||||||
|
EPUBJS.nightSelector = '.night *';
|
||||||
|
EPUBJS.nightModeBackground = $('#nightModeBackground').val();
|
||||||
|
EPUBJS.nightModeColor = $('#nightModeColor').val();
|
||||||
|
addCSSRule(EPUBJS.nightSheet, '.nonight', 'background: initial !important;');
|
||||||
|
nightModeConfig();
|
||||||
|
|
||||||
|
$('#nightModeBackground').on('change', function() {
|
||||||
|
EPUBJS.nightModeBackground = $('#nightModeBackground').val();
|
||||||
|
nightModeConfig();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#nightModeColor').on('change', function() {
|
||||||
|
EPUBJS.nightModeColor = $('#nightModeColor').val();
|
||||||
|
nightModeConfig();
|
||||||
|
});
|
||||||
|
|
||||||
|
var reader = ePubReader(document.getElementById("dllink").value, { contained: true });
|
||||||
|
|
||||||
|
// enable night/day mode switch by clicking on the book title/author
|
||||||
|
// just switching in the "night" class works on some browsers but not on others, hence the trickery with
|
||||||
|
// setStyle/removeStyle...
|
||||||
|
$('#metainfo').on('click', function() {
|
||||||
|
if(EPUBJS.nightMode) {
|
||||||
|
reader.book.removeStyle("background");
|
||||||
|
reader.book.removeStyle("color");
|
||||||
|
$("#outerContainer").removeClass("night");
|
||||||
|
EPUBJS.nightMode = false;
|
||||||
|
} else {
|
||||||
|
reader.book.setStyle("background", EPUBJS.nightModeBackground);
|
||||||
|
reader.book.setStyle("color", EPUBJS.nightModeColor);
|
||||||
|
$("#outerContainer").addClass("night");
|
||||||
|
EPUBJS.nightMode = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// extra-wide page turn area?
|
||||||
|
$('#touch_nav').on('click', function() {
|
||||||
|
if ($('#touch_nav').prop('checked')) {
|
||||||
|
$("#prev").removeClass("touch_nav");
|
||||||
|
$("#next").removeClass("touch_nav");
|
||||||
|
} else {
|
||||||
|
$("#prev").addClass("touch_nav");
|
||||||
|
$("#next").addClass("touch_nav");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// user-defined font
|
||||||
|
EPUBJS.ignore_css = false;
|
||||||
|
EPUBJS.bookFrame = null;
|
||||||
|
EPUBJS.user_fontFamily = $('#fontFamily').val();
|
||||||
|
EPUBJS.user_fontSize = $('#fontSize').val() + '%';
|
||||||
|
|
||||||
|
$('#ignore_css').on('click', function() {
|
||||||
|
EPUBJS.bookFrame = document.getElementsByTagName('iframe')[0].contentDocument;
|
||||||
|
if ($('#ignore_css').prop('checked')) {
|
||||||
|
$('#fontFamily').prop('disabled',false);
|
||||||
|
$('#fontSize').prop('disabled',false);
|
||||||
|
EPUBJS.ignore_css = true;
|
||||||
|
reader.book.setStyle('font-size', EPUBJS.user_fontSize);
|
||||||
|
reader.book.setStyle('font-family', EPUBJS.user_fontFamily);
|
||||||
|
} else {
|
||||||
|
$('#fontFamily').prop('disabled',true);
|
||||||
|
$('#fontSize').prop('disabled',true);
|
||||||
|
EPUBJS.ignore_css = false;
|
||||||
|
reader.book.removeStyle('font-size');
|
||||||
|
reader.book.removeStyle('font-family');
|
||||||
|
}
|
||||||
|
disableStyles(EPUBJS.bookFrame, EPUBJS.ignore_css);
|
||||||
|
;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#fontSize').on('change', function() {
|
||||||
|
EPUBJS.user_fontSize = $('#fontSize').val() + '%';
|
||||||
|
$('#font_example').css('font-size', EPUBJS.user_fontSize);
|
||||||
|
reader.book.setStyle('font-size', EPUBJS.user_fontSize);
|
||||||
|
});
|
||||||
|
$('#fontFamily').on('change', function() {
|
||||||
|
EPUBJS.user_fontFamily = $('#fontFamily').val();
|
||||||
|
$('#font_example').css('font-family', EPUBJS.user_fontFamily);
|
||||||
|
reader.book.setStyle('font-family', EPUBJS.user_fontFamily);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
182
files_reader/templates/reader.php
Normal file
182
files_reader/templates/reader.php
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
<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']);?>">
|
||||||
|
<title>
|
||||||
|
<?php p($_['title']);?>
|
||||||
|
</title>
|
||||||
|
<link rel="shortcut icon" href="img/book.png">
|
||||||
|
<link rel="stylesheet" href="css/normalize.css">
|
||||||
|
<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.js"> </script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<input type="hidden" id="dllink" value="<?php print_unescaped($_['dllink']);?>">
|
||||||
|
<div id="outerContainer">
|
||||||
|
<div id="sidebar">
|
||||||
|
<div id="panels">
|
||||||
|
<input id="searchBox" placeholder="not implemented yet" type="search" disabled="">
|
||||||
|
<a id="show-Search" class="show_view icon-search" data-view="Search">
|
||||||
|
Search
|
||||||
|
</a>
|
||||||
|
<a id="show-Toc" class="show_view icon-list-1 active" data-view="Toc">
|
||||||
|
TOC
|
||||||
|
</a>
|
||||||
|
<a id="show-Bookmarks" class="show_view icon-bookmark" data-view="Bookmarks">
|
||||||
|
Bookmarks
|
||||||
|
</a>
|
||||||
|
<a id="show-Notes" class="show_view icon-edit" data-view="Notes">
|
||||||
|
Notes
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div id="tocView" class="view">
|
||||||
|
</div>
|
||||||
|
<div id="searchView" class="view">
|
||||||
|
<ul id="searchResults">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="bookmarksView" class="view">
|
||||||
|
<ul id="bookmarks">
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="notesView" class="view">
|
||||||
|
<div id="new-note">
|
||||||
|
<textarea id="note-text">
|
||||||
|
</textarea>
|
||||||
|
<button id="note-anchor">
|
||||||
|
Anchor
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<ol id="notes">
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="main">
|
||||||
|
<div id="titlebar">
|
||||||
|
<div id="opener">
|
||||||
|
<a id="slider" class="icon-menu">
|
||||||
|
Menu
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div id="metainfo">
|
||||||
|
<span id="book-title">
|
||||||
|
</span>
|
||||||
|
<span id="title-seperator">
|
||||||
|
–
|
||||||
|
</span>
|
||||||
|
<span id="chapter-title">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div id="title-controls">
|
||||||
|
<a id="bookmark" class="icon-bookmark-empty">
|
||||||
|
Bookmark
|
||||||
|
</a>
|
||||||
|
<a id="setting" class="icon-cog">
|
||||||
|
Settings
|
||||||
|
</a>
|
||||||
|
<a id="fullscreen" class="icon-resize-full">
|
||||||
|
Fullscreen
|
||||||
|
</a>
|
||||||
|
<a id="close" class="icon-cancel-circled2">
|
||||||
|
Close
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="divider">
|
||||||
|
</div>
|
||||||
|
<div id="prev" class="arrow nonight">
|
||||||
|
<div class="nonight">
|
||||||
|
‹
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="viewer">
|
||||||
|
</div>
|
||||||
|
<div id="next" class="arrow nonight">
|
||||||
|
<div class="nonight">
|
||||||
|
›
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="loader" class="nonight">
|
||||||
|
<img src="img/loading.gif">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal md-effect-1" id="settings-modal">
|
||||||
|
<div class="md-content">
|
||||||
|
<h3>
|
||||||
|
Settings
|
||||||
|
</h3>
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<input type="checkbox" id="ignore_css" name="ignore_css">
|
||||||
|
<label for="ignore_css">
|
||||||
|
Always use
|
||||||
|
</label>
|
||||||
|
<select id="fontFamily" disabled="">
|
||||||
|
<option value="verdana, trebuchet, droid sans serif, sans, sans-serif">
|
||||||
|
Sans
|
||||||
|
</option>
|
||||||
|
<option value="georgia, times new roman, droid serif, serif">
|
||||||
|
Serif
|
||||||
|
</option>
|
||||||
|
<option value="monospace">
|
||||||
|
Monospace
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
font scaled to
|
||||||
|
<input type="number" id="fontSize" value="100" min="50" max="150" disabled="">
|
||||||
|
%
|
||||||
|
</p>
|
||||||
|
<div id="font_example" class="user">
|
||||||
|
Et nos esse veri viri scire volemus
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<input type="checkbox" id="sidebarReflow" name="sidebarReflow">
|
||||||
|
<label for="sidebarReflow">
|
||||||
|
Reflow text when sidebars are open.
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Night mode background
|
||||||
|
<input type="color" id="nightModeBackground" value="#000000">
|
||||||
|
and text
|
||||||
|
<input type="color" id="nightModeColor" value="#3A516B">
|
||||||
|
colour
|
||||||
|
</p>
|
||||||
|
<div id="nightModeExample" class="night">
|
||||||
|
<div>
|
||||||
|
Et nos esse veri viri scire volemus
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p>
|
||||||
|
<input type="checkbox" id="touch_nav" name="touch_nav">
|
||||||
|
<label for="touch_nav" class="tooltip">
|
||||||
|
Disable extra-wide page turn areas
|
||||||
|
<span>
|
||||||
|
The extra-wide page turn areas as used by default on touch-screen devices interfere with the ability to select links in ebooks. When this option is enabled, the page-turn area is always outside the ebook margins so links are reachable.
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="closer icon-cancel-circled nonight">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="overlay nonight">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
26
files_reader/viewer.php
Normal file
26
files_reader/viewer.php
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
<?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::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