diff options
-rw-r--r-- | backend.php | 13 | ||||
-rw-r--r-- | db.php | 20 | ||||
-rw-r--r-- | index.php | 15 | ||||
-rw-r--r-- | login.php | 73 | ||||
-rw-r--r-- | logout.php | 10 | ||||
-rw-r--r-- | schema.sql | 16 | ||||
-rw-r--r-- | sessions.php | 68 | ||||
-rw-r--r-- | useradm.php | 59 | ||||
-rw-r--r-- | worker.js | 42 |
9 files changed, 295 insertions, 21 deletions
diff --git a/backend.php b/backend.php index 7a4b63e..4ab000d 100644 --- a/backend.php +++ b/backend.php @@ -1,15 +1,16 @@ <?php require_once "config.php"; + require_once "sessions.php"; + require_once "db.php"; + + $ldb = Db::get(); $op = $_REQUEST["op"]; header("Content-type: text/json"); - $ldb = new SQLite3(SCRATCH_DB); - $ldb->busyTimeout(30*1000); - - $owner = SQLite3::escapeString($_SERVER["PHP_AUTH_USER"]); + $owner = SQLite3::escapeString($_SESSION["owner"]); if (!$owner) { header($_SERVER["SERVER_PROTOCOL"]." 401 Unauthorized"); @@ -43,7 +44,11 @@ } break; + case "getowner": + $owner = SQLite3::escapeString($_SESSION["owner"]);; + print json_encode(["owner" => $owner]); + break; case "getinfo": $id = (int) $_REQUEST["id"]; @@ -0,0 +1,20 @@ +<?php +class Db { + private static $instance; + private $dbh; + + private function __construct() { + $this->dbh = new SQLite3(__DIR__ . "/" . SCRATCH_DB); + $this->dbh->busyTimeout(30*1000); + } + + public static function get() { + if (self::$instance == null) + self::$instance = new self(); + + return self::$instance->dbh; + } + +}; + +?> @@ -4,9 +4,15 @@ } require_once "config.php"; + require_once "sessions.php"; + require_once "db.php"; - $owner = SQLite3::escapeString($_SERVER["PHP_AUTH_USER"]); + @$owner = SQLite3::escapeString($_SESSION["owner"]); + if (!$owner) { + header("Location: login.php"); + exit; + } if (basename(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH)) != 'index.php') { header('Location: index.php'); @@ -27,8 +33,7 @@ die(dirname(SCRATCH_DB) . " directory is not writable"); } - $ldb = new SQLite3(SCRATCH_DB); - $ldb->busyTimeout(30*1000); + $ldb = Db::get(); ?> <!DOCTYPE html> <html> @@ -85,6 +90,10 @@ <button type="submit" class="btn btn-default">Search</button> </form> + <ul class="nav navbar-nav navbar-right"> + <li><a href="logout.php">Logout</a></li> + </li> + </div> </div> diff --git a/login.php b/login.php new file mode 100644 index 0000000..e54d989 --- /dev/null +++ b/login.php @@ -0,0 +1,73 @@ +<?php + require_once "config.php"; + require_once "sessions.php"; + + @$op = $_REQUEST["op"]; + + if ($op == "perform-login") { + $user = SQLite3::escapeString($_REQUEST["user"]); + $password = SQLite3::escapeString('SHA256:' . hash('sha256', "$user:" . $_REQUEST["password"])); + + $dbh = Db::get(); + + $res = $dbh->query("SELECT id FROM epube_users WHERE user = '$user' AND pass = '$password'"); + + if ($line = $res->fetchArray(SQLITE3_ASSOC)) { + $_SESSION["owner"] = $user; + header("Location: index.php"); + } + } + +?> +<!DOCTYPE html> +<html> +<head> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <link href="lib/bootstrap/v3/css/bootstrap.min.css" rel="stylesheet" media="screen"> + <link href="lib/bootstrap/v3/css/bootstrap-theme.min.css" rel="stylesheet" media="screen"> + <link href="lib/qtip2/jquery.qtip.min.css" rel="stylesheet" media="screen"> + <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> + <script src="lib/bootstrap/v3/js/jquery.js"></script> + <script src="lib/bootstrap/v3/js/bootstrap.min.js"></script> + <script src="lib/holder.min.js"></script> + <script src="lib/localforage.min.js"></script> + <script src="lib/qtip2/jquery.qtip.min.js"></script> + <title>The Epube</title> + <link type="text/css" rel="stylesheet" media="screen" href="css/index.css" /> + <link rel="shortcut icon" type="image/png" href="img/favicon.png" /> + <link rel="icon" sizes="192x192" href="img/favicon_hires.png"> + <link rel="manifest" href="manifest.json"> + <meta name="mobile-web-app-capable" content="yes"> + <script src="js/index.js"></script> + <script src="js/common.js"></script> +</head> +<body> + +<div class="navbar navbar-default navbar-static-top"> +<div class="container"> + <div class="navbar-header"> + <span class="navbar-brand"><a href="?">The Epube</a></span> + </div> +</div> +</div> + +<div class="container"> + + <form> + <input type="hidden" name="op" value="perform-login"> + + <div class="form-group"> + <label>User</label> + <input class="form-control" required="true" name="user"> + </div> + <div class="form-group"> + <label>Password</label> + <input type="password" class="form-control" name="password" required="true"> + </div> + <button type="submit" class="btn btn-default">Log in</button> + </form> + +</div> + +</body> +</html> diff --git a/logout.php b/logout.php new file mode 100644 index 0000000..e4d40ed --- /dev/null +++ b/logout.php @@ -0,0 +1,10 @@ +<?php + require_once "config.php"; + require_once "sessions.php"; + + session_destroy(); + + header("Location: login.php"); + +?> + @@ -1,5 +1,9 @@ drop table if exists epube_pagination; drop table if exists epube_books; +drop table if exists epube_users; +drop table if exists epube_sessions; + +drop index if exists epube_sessions_expire; create table epube_pagination( id integer not null primary key autoincrement, @@ -13,3 +17,15 @@ create table epube_books( owner varchar(200) not null, lastcfi varchar(200) not null, lastread integer not null); + +create table epube_users( + id integer not null primary key autoincrement, + user varchar(100) not null, + pass varchar(200) not null); + +create table epube_sessions ( + id varchar(250) not null primary key, + data text, + expire integer not null); + +create index epube_sessions_expire on epube_sessions(expire); diff --git a/sessions.php b/sessions.php new file mode 100644 index 0000000..9a90ad4 --- /dev/null +++ b/sessions.php @@ -0,0 +1,68 @@ +<?php + require_once "config.php"; + require_once "db.php"; + + define('SESSION_LIFETIME', 365 * 86400); + + ini_set("session.name", "epube_sid"); + ini_set("session.use_only_cookies", true); + ini_set("session.gc_maxlifetime", SESSION_LIFETIME); + ini_set("session.cookie_lifetime", SESSION_LIFETIME); + + if (@$_SERVER['HTTPS'] == "on") { + ini_set("session.cookie_secure", true); + } + + session_set_cookie_params(SESSION_LIFETIME); + + function s_open ($s, $n) { + return true; + } + + function s_read ($id){ + $res = Db::get()->query("SELECT data FROM epube_sessions WHERE id='$id'"); + + if ($line = $res->fetchArray(SQLITE3_ASSOC)) { + return base64_decode($line["data"]); + } else { + $expire = time() + SESSION_LIFETIME; + + Db::get()->query("INSERT INTO epube_sessions (id, data, expire) + VALUES ('$id', '', '$expire')"); + } + + } + + function s_write ($id, $data) { + $data = base64_encode($data); + $expire = time() + SESSION_LIFETIME; + + Db::get()->query("UPDATE epube_sessions SET data = '$data', expire = '$expire' WHERE id = '$id'"); + + return true; + } + + function s_close () { + return true; + } + + function s_destroy($id) { + Db::get()->query("DELETE FROM epube_sessions WHERE id = '$id'"); + + return true; + } + + function s_gc ($expire) { + Db::get()->query("DELETE FROM epube_sessions WHERE expire < " . time()); + + return true; + } + session_set_save_handler("s_open", + "s_close", "s_read", "s_write", + "s_destroy", "s_gc"); + + register_shutdown_function('session_write_close'); + + session_start(); + +?> diff --git a/useradm.php b/useradm.php new file mode 100644 index 0000000..2af25d2 --- /dev/null +++ b/useradm.php @@ -0,0 +1,59 @@ +#!/usr/bin/php +<?php + require_once "config.php"; + require_once "db.php"; + + $dbh = Db::get(); + + $longopts = [ "add:", "del:", "list", "help" ]; + + $options = getopt("", $longopts); + + if (count($options) == 0 || isset($options["help"])) { + print "Manage Epube user database. Usage: + --add USER:PASSWORD + --del USER + --list\n"; + } + + if (isset($options["del"])) { + $user = SQLite3::escapeString($options["del"]); + + print "Deleting user $user...\n"; + $dbh->query("DELETE FROM epube_users WHERE user = '$user'"); + } + + if (isset($options["list"])) { + $res = $dbh->query("SELECT id, user FROM epube_users ORDER BY user"); + + while ($line = $res->fetchArray(SQLITE3_ASSOC)) { + printf("%d. %s\n", $line["id"], $line["user"]); + } + + } + + if (isset($options["add"])) { + @list($user, $pass) = explode(":", $options["add"]); + + if (!$user || !$pass) { + print "Not enough arguments.\n"; + exit; + } + + $user = SQLite3::escapeString($user); + $pass_hash = SQLite3::escapeString('SHA256:' . hash('sha256', "$user:$pass")); + + print "Adding user $user with password $pass...\n"; + + $res = $dbh->query("SELECT user FROM epube_users WHERE user = '$user'"); + + if ($line = $res->fetchArray(SQLITE3_ASSOC)) { + print "User already exists.\n"; + } else { + $dbh->query("INSERT INTO epube_users (user, pass) + VALUES ('$user', '$pass_hash')"); + } + + } + +?> @@ -44,7 +44,7 @@ self.addEventListener('message', function(event){ cache.keys().then(function(keys) { for (var i = 0; i < keys.length; i++) { - fetch(keys[i],{credentials:'same-origin'}).then(function(resp) { + fetch(keys[i]).then(function(resp) { if (resp.status == 200) { cache.put(resp.url, resp); } @@ -59,24 +59,38 @@ self.addEventListener('message', function(event){ this.addEventListener('fetch', function(event) { var req = event.request.clone(); - if (!navigator.onLine) { - event.respondWith( - caches.match(req).then(function(resp) { + event.respondWith( + caches.match(req).then(function(resp) { - if (resp) return resp; + if (resp) { + return resp; + } - if (req.url.match("read.html")) { - return caches.match("read.html"); - } + if (req.url.match("read.html")) { + return caches.match("read.html"); + } - if (req.url.match("offline.html")) { - return caches.match("offline.html"); + if (req.url.match("offline.html")) { + return caches.match("offline.html"); + } + + return fetch(req).then(function(resp) { + + if (resp.status == 200) { + if (resp.url.match("backend.php\\?op=cover")) { + return caches.open(CACHE_NAME).then(function(cache) { + cache.put(resp.url, resp.clone()); + return resp; + }); + } } - if (req.url.match("index.php")) { + return resp; + }).catch(function() { + if (req.url[req.url.length-1] == "/" || req.url.match("index.php")) { return caches.match("offline.html"); } - }) - ); - } + }); + }) + ); }); |