Initial Commit

This commit is contained in:
Junior 2023-08-18 12:50:45 -04:00
commit cecd71ebc2
34 changed files with 869 additions and 0 deletions

28
.gitignore vendored Normal file
View File

@ -0,0 +1,28 @@
# OS generated files
.DS_Store
.DS_Store?
._*
.Trashes
Thumbs.db
# Ignore temporary office docs
~$*
# The active config file copied from config-dist.php
variables.php
# Vim
*.swp
*.swo
# sass generated files
.sass-cache/
install/.sass-cache/
compressed
*.map
# IDE generated
.idea/
comics/
thumbs/

1
.htaccess Normal file
View File

@ -0,0 +1 @@
php_flag opcache.enable off

15
README.md Normal file
View File

@ -0,0 +1,15 @@
# Comics Viewer
This small project provides a web based viewer for comics in the CBZ and CBR formats.
## This project requires
* PHP ImageMagick
* PHP RAR (PECL)
## Don't forget to:
* Create a MySQL/MariaDB database for the app with privileges granted to a user
* Import the `install/initial_db_mysql.sql` database structure
* Change the ownership of the `comics/` and `thumbs/` folders to the web server user
* Copy the `variables-dist.php` file to `variables.php` and edit that file appropriately

11
ajax/sess.php Normal file
View File

@ -0,0 +1,11 @@
<?php
require '../header.php';
require_login();
$data = $_SESSION;
header('Content-Type: application/json');
echo json_encode($data);
exit();

28
ajax/setpage.php Normal file
View File

@ -0,0 +1,28 @@
<?php
require '../header.php';
require_login();
$data = array();
if ( !isset($_REQUEST['page']) ) {
exit();
}
$page = intval($_REQUEST['page']);
$query = "INSERT INTO pagetracker (username, comic, issue, currentpage, lastupdate) ";
$query .= "VALUES(:username, :comic, :issue, :currentpage, NOW()) ";
$query .= "ON DUPLICATE KEY UPDATE currentpage=:currentpage, lastupdate=NOW()";
$fields = array();
$fields[':username'] = $_SESSION['username'];
$fields[':comic'] = str_replace("/", "", $_SESSION['compath']);
$fields[':issue'] = $_SESSION['comfile'];
$fields[':currentpage'] = $page;
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
$data['message'] = "Page set to $page for {$_SESSION['username']} reading {$_SESSION['comfile']}";
header('Content-Type: application/json');
echo json_encode($data);
exit();

91
ajax/showcomic.php Normal file
View File

@ -0,0 +1,91 @@
<?php
require '../header.php';
require_login();
if ( isset($_REQUEST['comic']) ) {
$comic = makePathSafe(base64_decode(urldecode(($_REQUEST['comic']))));
$comicfull = COMICSDIR . $comic;
$comicoutputurl = "comics" . str_replace("#", "", $comic) . "/";
$comicoutputfull = "../" . EXTRACTSDIR . str_replace("#", "", $comic) . "/";
} else {
exit();
}
$ext = strtolower(substr($comic, -3));
$_SESSION['comfile'] = basename($comic);
$data = array();
// Get the current page for this comic or 0 (zero) if never opened
$query = "SELECT currentpage FROM pagetracker WHERE username=:username AND issue=:issue";
$fields = array();
$fields[':username'] = $_SESSION['username'];
$fields[':issue'] = $_SESSION['comfile'];
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
if ( $row = $sth->fetch(PDO::FETCH_ASSOC) ) {
$currentpage = intval($row['currentpage']);
} else {
$currentpage = 0;
}
$data["startindex"] = $currentpage;
if ( !is_dir($comicoutputfull) ) {
mkdir($comicoutputfull, 0755, true);
}
$files = array();
if ( $ext == "cbz" ) {
$zip = new ZipArchive();
$opened = $zip->open($comicfull);
for ( $i=0; $i<$zip->numFiles; $i++ ) {
$imgname = basename($zip->getNameIndex($i));
$myext = substr($imgname, -3);
if ( ($myext == "jpg") || ($myext == "png") ) {
$imgname = str_replace("#", "", $imgname);
$imgcontents = $zip->getFromIndex($i);
$written = file_put_contents($comicoutputfull . $imgname, $imgcontents);
if ( $written ) $files[] = $imgname;
}
}
} elseif ( $ext == "cbr" ) {
$junk = `/usr/local/bin/rar e -ep -o+ "$comicfull" "$comicoutputfull"`;
$fh = opendir($comicoutputfull);
while ( false !== ($file = readdir($fh)) ) {
$myfile = $comicoutputfull . $file;
$mynewfile = $comicoutputfull . str_replace("#", "", $file);
$myext = strtolower(substr($file, -3));
if ( ($myext == "jpg") || ($myext == "png") ) {
rename($myfile, $mynewfile);
$files[] = basename($mynewfile);
}
}
closedir($fh);
} else {
exit();
}
natsort($files);
$images = array();
$captions = array();
$last = count($files);
$count = 0;
foreach ( $files as $file ) {
$count++;
$images[] = $comicoutputurl . $file;
$captions[] = substr(basename($comicoutputurl), 0, -4) . ": {$count} of {$last}";
}
$debug = (DEBUG_SHOWCOMICAJAX || DEBUG_ALL);
$data["debug"] = $debug;
$data["images"] = $images;
$data["captions"] = $captions;
header('Content-Type: application/json');
echo json_encode($data);
exit();
// vim: set ts=3 sw=3 et:

19
authfunctions.php Normal file
View File

@ -0,0 +1,19 @@
<?php
//
// This function is called at the beginning of any pages where
// user login is required. Feel free to change the logic between
// the lines indicated below.
//
function require_login () {
if ( !$_SESSION['validated'] ) {
// ******** START OF AUTH LOGIC ********
$_SESSION['appurl'] = $_SERVER['REQUEST_URI'];
header('Location: /jajauth/login.php');
exit();
// ********* END OF AUTH LOGIC *********
}
}
?>

3
comics/README.md Normal file
View File

@ -0,0 +1,3 @@
# Comics "Viewing" Folder
This is the folder where comics get extracted for viewing in the web browser. The folder must be owned by the user which runs the web server.

4
core/jquery-1.7.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
core/jquery-3.6.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
core/simpleLightbox.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1
core/simpleLightbox.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
core/simpleLightbox.txt Normal file
View File

@ -0,0 +1 @@
Project source: https://github.com/dbrekalo/simpleLightbox

1
core/toastr.min.css vendored Normal file

File diff suppressed because one or more lines are too long

2
core/toastr.min.js vendored Normal file

File diff suppressed because one or more lines are too long

100
css/comics.css Normal file
View File

@ -0,0 +1,100 @@
body {
background-color: #121211;
color: #ddddd1;
font-family: 'Comic Sans MS';
font-weight: bold;
font-size: 10pt;
}
a, a:link, a:visited, a:active {
text-decoration: none;
color: #22dd22;
}
.header {
font-size: 24pt;
font-weight: bold;
font-family: 'Comic Sans MS';
text-align: center;
margin-left: 20px;
margin-right: 20px;
border-bottom: 2px solid #ddddd1;
}
.listcontainer {
margin-top: 10px;
text-align: center;
width: 100%;
/*
margin-left: auto;
margin-right: auto;
overflow: auto;
width: -moz-fit-content;
width: -webkit-fit-content;
width: fit-content;
*/
}
.list {
width: 100%;
margin: 10px auto auto auto;
position: relative;
display: flex;
flex-wrap: wrap;
justify-content: center;
text-align: center;
/*
text-align: center;
margin-left: auto;
margin-right: auto;
margin: 0 auto 0 auto;
width: 1190px;
*/
}
.item {
cursor: pointer;
width: 220px;
height: 330px;
margin: 5px;
border: 2px solid #ddddd1;
padding: 2px;
display: inline-block;
/*
float: left;
*/
overflow: hidden;
}
.readborder {
border-color: green !important;
}
.debug {
position: absolute;
top: 0px;
left: 0px;
z-index: 42;
}
div.sorter {
position: absolute;
float: left;
top: 0px;
left: 0px;
z-index: 10;
font-size: 24pt;
font-weight: bold;
font-family: 'Comic Sans MS';
}
div.name {
position: absolute;
float: right;
top: 0px;
right: 5px;
z-index: 20;
font-size: 24pt;
font-weight: bold;
font-family: 'Comic Sans MS';
}

48
css/reset.css Normal file
View File

@ -0,0 +1,48 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

23
downloadcomic.php Normal file
View File

@ -0,0 +1,23 @@
<?php
require 'header.php';
require_login();
if ( isset($_REQUEST['comic']) ) {
$comic = makePathSafe(base64_decode(urldecode(($_REQUEST['comic']))));
$comicfull = COMICSDIR . $comic;
} else {
exit();
}
header("Pragma: public");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"" . trim(basename($comicfull)) . "\"");
header("Content-Description: " . trim(basename($comicfull)));
header("Expires: 0");
header("Cache-Control: must-revalidate");
header("Content-length: " . filesize($comicfull));
readfile($comicfull);
exit();

122
functions.php Normal file
View File

@ -0,0 +1,122 @@
<?php
function microtime_float() {
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
function makePathSafe($path = "") {
if ( $path == "" ) return "";
// Stick forward slashes on the ends to make matching more consistent
$path = "/" . $path . "/";
// Remove all instances of dots between forward slashes
while ( preg_match("/\/\.{0,}\//", $path) ) {
$path = preg_replace("/\/\.{0,}\//", "/", $path);
}
// Replace all instances of two consecutive forward slashes
while ( strpos($path, "//") !== false ) {
$path = str_replace("//", "/", $path);
}
// Remove all leading forward slashes
while ( substr($path, 0, 1) == '/' ) {
$path = substr($path, 1);
}
// Remove all trailing forward slashes
while ( substr($path, -1) == '/' ) {
$path = substr($path, 0, strlen($path)-1);
}
$path = "/" . $path;
return $path;
}
function makeThumb($item = "") {
if ( $item == "" ) { return false; }
if ( is_dir($item) ) {
$isfolder = true;
$folder = $item;
$files = array();
if ( $fh = opendir($folder) ) {
while ( false !== ($entry = readdir($fh)) ) {
if ( is_file($item . "/" . $entry) ) {
$files[] = $entry;
}
}
closedir($fh);
natsort($files);
}
if ( count($files) == 0 ) { return false; }
reset($files);
$comic = $folder . "/" . current($files);
$outfile = THUMBSDIR . substr($folder, strlen(COMICSDIR)) . "_oem";
} elseif ( is_file($item) ) {
$isfolder = false;
$file = $item;
$comic = $file;
$targetdir = THUMBSDIR . substr(dirname($file), strlen(COMICSDIR)) . "/";
if ( !is_dir($targetdir) ) {
mkdir($targetdir, 0755, true);
}
$outfile = $targetdir . substr(basename($file), 0, -4) . "_oem";
} else {
return false;
}
if ( substr($comic, -3) == "cbz" ) {
$zip = new ZipArchive();
$opened = $zip->open($comic);
if ( !$opened ) { return false; }
$lowest = "~";
$imgdata = null;
for ( $i=0; $i<$zip->numFiles; $i++ ) {
$imgname = basename($zip->getNameIndex($i));
if ( (strcmp($lowest, $imgname) > 0)
&& ((strcasecmp(substr($imgname, -3), "jpg") == 0)
|| (strcasecmp(substr($imgname, -3), "png") == 0)) ) {
$lowest = $imgname;
$imgdata = $zip->getFromIndex($i);
}
}
$zip->close();
if ( is_null($imgdata) ) return false;
$didwrite = file_put_contents($outfile, $imgdata);
if ( !$didwrite ) return false;
} elseif ( substr($comic, -3) == "cbr" ) {
$rar_file = rar_open($comic);
if ( $rar_file === false ) { return false; }
$entries = rar_list($rar_file);
$lowest = "~";
foreach ( $entries as $entry ) {
$imgname = $entry->getName();
if ( (strcmp($lowest, $imgname) > 0)
&& ((strcasecmp(substr($imgname, -3), "jpg") == 0)
|| (strcasecmp(substr($imgname, -3), "png") == 0)) ) {
$lowest = $imgname;
$ext = strtolower(substr($imgname, -3));
$didwrite = $entry->extract(false, $outfile);
if ( !$didwrite ) { return false; }
}
}
rar_close($rar_file);
} else {
return false;
}
$input = new Imagick($outfile);
$input->setImageFormat("jpg");
$width = $input->getImageWidth();
$height = $input->getImageHeight();
$scale = 200 / $width;
$newx = 200;
$newy = intval($height * $scale);
if ( $newy > 300 ) {
$newy = 300;
$scale = $height / 300;
$newx = intval($width / $scale);
}
$thumb = substr($outfile, 0, -4) . ".jpg";
$thumb = str_replace("#", "", $thumb);
$input->resizeImage($newx, $newy, Imagick::FILTER_SINC, 1);
$written = file_put_contents($thumb, $input->getImageBlob());
unlink($outfile);
return (($written === false) ? false : true);
}
// vim: set ai et ts=3 sw=3:

51
header.php Normal file
View File

@ -0,0 +1,51 @@
<?php
// Script defining constants and variables used in the comics system
require 'variables.php';
// Script containing global functions used by all scripts
require 'functions.php';
// Script containing the "require_login() function"
// This can be changed to suit local implementation needs but must
// be named "require_login() and take no parameters
require 'authfunctions.php';
// Start the session
session_name(SESSIONCOMICS);
session_start();
// This session variable is TRUE when successfully logged in
// If set to true, and using default authentication, no login will be required
if ( !isset($_SESSION['validated']) ) {
$_SESSION['validated'] = false;
}
// This session variable is set to the current browsing folder.
// It is relative to the COMICSDIR constant defined in variables.php
if ( !isset($_SESSION['compath']) ) {
$_SESSION['compath'] = '/';
}
// This session variable is set to the current comic in Base64
if ( !isset($_SESSION['comfile']) ) {
$_SESSION['comfile'] = "";
}
// Initialize the hash session variable used for SSO
// Set the hash to the passed in value if it exists
if ( !isset($_SESSION['hash']) ) {
$_SESSION['hash'] = "";
}
if ( isset($_REQUEST['hash']) ) {
$_SESSION['hash'] = $_REQUEST['hash'];
}
// Sorting for folders.
// Valid values (from constants): SORTBYNAME, SORTBYDATE
if ( !isset($_SESSION['sortorder']) ) {
$_SESSION['sortorder'] = SORTBYDATE;
}
// Make our PDO database connection which will be used in all scripts
$globaldbh = new PDO("mysql:host=" . DBHOST . ";dbname=" . DBNAME, DBUSER, DBPASS);
?>

BIN
img/comics.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
img/comics_120.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

BIN
img/comics_128.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
img/comics_152.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
img/comics_196.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

BIN
img/comics_76.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
img/nothumb.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

192
index.php Normal file
View File

@ -0,0 +1,192 @@
<?php
require 'header.php';
require_login();
if ( isset($_REQUEST['sortorder']) ) {
if ( ($_REQUEST['sortorder'] == SORTBYNAME) || ($_REQUEST['sortorder'] == SORTBYDATE) ) {
$_SESSION['sortorder'] = $_REQUEST['sortorder'];
}
}
$validext = array('cbr', 'cbz');
if ( isset($_REQUEST['newpath']) ) {
$newpath = makepathsafe($_REQUEST['newpath']);
if ( is_dir(COMICSDIR . $newpath) ) {
$_SESSION['compath'] = $newpath;
} else {
$_SESSION['compath'] = "/";
}
}
$compath = $_SESSION['compath'];
$fullcompath = COMICSDIR . $compath;
$header = basename($compath);
if ( $header == "" ) { $header = "Comics"; }
$fltime = microtime_float();
$folders = array();
$files = array();
if ( $fh = opendir($fullcompath) ) {
while ( false !== ($entry = readdir($fh)) ) {
$mtime = filemtime($fullcompath . "/" . $entry);
if ( ($entry != ".") && ($entry != "..") && is_dir($fullcompath . "/" . $entry) ) {
$folders[$mtime] = $entry;
}
if ( is_file($fullcompath . "/" . $entry)
&& in_array(substr($entry, -3), $validext) ) {
$files[] = $entry;
}
}
closedir($fh);
if ( $_SESSION['sortorder'] == SORTBYNAME ) {
natsort($folders);
} else {
ksort($folders);
$folders = array_reverse($folders);
}
sort($files);
}
$items = array_merge($folders, $files);
$fltime = microtime_float() - $fltime;
$updir = dirname($compath);
$updirlink = urlencode($updir);
// build up a list of comics and issues which have been
$query = "SELECT comic, issue FROM pagetracker WHERE username=:username";
$fields = array();
$fields[":username"] = $_SESSION['username'];
$sth = $globaldbh->prepare($query);
$sth->execute($fields);
$comics = array();
$issues = array();
while ( $row = $sth->fetch(PDO::FETCH_ASSOC) ) {
if ( !in_array($row['comic'], $comics) ) $comics[] = $row['comic'];
if ( !in_array($row['issue'], $issues) ) $issues[] = $row['issue'];
}
?>
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=0.5" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<link rel="icon" sizes="128x128" href="img/comics_128.png">
<link rel="icon" sizes="196x196" href="img/comics_196.png">
<link rel="apple-touch-icon" sizes="76x76" href="img/comics_76.png">
<link rel="apple-touch-icon" sizes="120x120" href="img/comics_120.png">
<link rel="apple-touch-icon" sizes="152x152" href="img/comics_152.png">
<title>Comics Fancy</title>
<link rel='stylesheet' type='text/css' href='css/reset.css' media='screen' />
<link rel='stylesheet' type='text/css' href='css/comics.css' media='screen' />
<link rel="stylesheet" type="text/css" href="core/simpleLightbox.min.css" />
<!-- Toastr CSS -->
<link rel="stylesheet" type="text/css" href="core/toastr.min.css" />
<script type='text/javascript' src='core/jquery-3.6.0.min.js'></script>
<script type='text/javascript' src='js/comics.js'></script>
<script type='text/javascript' src='core/simpleLightbox.min.js'></script>
<script type='text/javascript' src='core/toastr.min.js'></script>
<style type='text/css'>
.fancybox-outer { background: #323231; }
.fancybox-title { font: normal 10px "Comic Sans MS"; }
.fancybox-title-over-wrap { color: #bbb; padding: 0px 4px 0px 4px; }
.mtest {
margin-top: 0px;
margin-bottom: 0px;
padding-top: 0px;
padding-bottom: 0px;
border: 1px solid red;
}
</style>
</head>
<body>
<div class='sorter'>Sort:
<?php
if ( $_SESSION['sortorder'] == SORTBYNAME ) {
echo "<a href='index.php?sortorder=", SORTBYDATE, "'>Name</a>";
} else {
echo "<a href='index.php?sortorder=", SORTBYNAME, "'>Date</a>";
}
?>
</div>
<div class='header' id='header'><?php
/*
if ( $compath != "/" ) {
echo "<a href='index.php?newpath=$updirlink'>$updir";
if ( dirname($compath) == "/" ) { echo "Comics"; }
echo "</a>/";
}
echo $header;
*/
?>&nbsp;</div>
<!-- <div class='name'><a href='logout.php'><?php echo htmlspecialchars($_SESSION['name']); ?></a></div> -->
<div class='name'><?php
if ( $compath != "/" ) {
echo "<a href='index.php?newpath=$updirlink'>$updir";
if ( dirname($compath) == "/" ) { echo "Comics"; }
echo "</a>/";
}
?></div>
<div class='list'>
<!-- <div class='listcontainer'> -->
<?php
$htime = microtime_float();
$thumbtime = 0;
$newthumbs = 0;
$thumbfiles = "";
$total = count($items);
for ( $i=1; $i<=$total; $i++ ) {
//for ( $i=6; $i<=6; $i++ ) {
if ( $i <= count($folders) ) {
$np = urlencode($compath . "/" . $items[$i-1]);
$thumbfile = THUMBSDIR . $compath . "/" . $items[$i-1] . ".jpg";
} else {
$np = urlencode($compath . "/" . substr($items[$i-1], 0, -4) . ".jpg");
$thumbfile = THUMBSDIR . $compath . "/" . substr($items[$i-1], 0, -4) . ".jpg";
}
$thumbfile = str_replace("#", "", $thumbfile);
if ( !file_exists($thumbfile) ) {
$thumbfiles .= $thumbfile . "<br>";
$newthumbs++;
$st = microtime_float();
$havethumb = makeThumb($fullcompath . "/" . $items[$i-1]);
$thumbtime += microtime_float() - $st;
if ( !$havethumb ) {
$havethumb = true;
$thumb = "img/nothumb.png";
}
}
$thumb = "thumbs" . $compath . "/" .basename($thumbfile);
$comname = pathinfo($items[$i-1], PATHINFO_FILENAME);
if ( strpos($comname, " - ") !== false ) $comname = str_replace(" - ", "<br />", $comname);
$classmod = "";
if ( $i <= count($folders) ) {
if ( in_array($items[$i-1], $comics) ) $classmod=" readborder";
echo "<div class='item{$classmod}' ";
echo "onClick='document.location=\"index.php?newpath=$np\";'>";
$thumburl = htmlentities($thumb, ENT_QUOTES);
echo "<img src='$thumburl'><br clear=all />{$comname}</div>\n";
} else {
if ( in_array($items[$i-1], $issues) ) $classmod=" readborder";
$relcomic = trim(base64_encode($compath . "/" . $items[$i-1]), "=");
$thumburl = htmlentities($thumb, ENT_QUOTES);
echo "<div class='item{$classmod}' id='", $relcomic, "'><a onClick='showComic(\"", $relcomic, "\", \"", htmlspecialchars($comname, ENT_QUOTES), "\");' ";
echo "href='javascript:;'><img border=0 src='$thumburl'></a><br clear=all />";
echo "<a href='downloadcomic.php?comic={$relcomic}'>{$comname}</a></div>\n";
}
}
$htime = microtime_float() - $htime;
?>
<!-- </div> -->
<div id='debug' class='debug'>
</div>
</body>
</html><?php
// vim: set ai et ts=3 sw=3:

View File

@ -0,0 +1,11 @@
DROP TABLE IF EXISTS `pagetracker`;
CREATE TABLE `pagetracker` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`comic` varchar(255) NOT NULL,
`issue` varchar(255) NOT NULL,
`currentpage` int(11) unsigned NOT NULL DEFAULT 0,
`lastupdate` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `user_comic` (`username`,`issue`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC;

44
js/comics.js Normal file
View File

@ -0,0 +1,44 @@
// This function is executed after the page load completes on the client
$(document).ready(function() {
});
var lightbox = null;
function updateCurrentPage() {
var currentPage = lightbox.currentPosition;
$.ajax({
url : 'ajax/setpage.php',
data : {page: currentPage},
dataType : 'json',
success : function(data, stat, jqo) {
console.log(data.message);
}
});
}
//
// This JS function is called when a user clicks on a comic.
// "showcomic.php" is called with the comic to view as a parameter.
// It returns a JSON object representing the collection of images.
// If in debug mode the javascript code is displayed in the browser.
// If not in debug mode a lightbox object is created to display the comic.
//
function showComic(comic, name) {
$("#" + comic).addClass("readborder");
toastr.success("Extracting and showing the comic \"" + name + "\"...", "Showing Comic");
$.ajax({
url : 'ajax/showcomic.php',
data : {comic: comic},
dataType : 'json',
success : function(data, stat, jqo) {
// Clear out the debug DIV and start the fancybox.
$("#debug").html("");
lightbox = SimpleLightbox.open({
items: data.images,
captions: data.captions,
startAt: data.startindex,
beforeSetContent: updateCurrentPage
});
}
});
}

11
logout.php Normal file
View File

@ -0,0 +1,11 @@
<?php
require 'header.php';
require_login();
session_destroy();
header('Location: index.php');
exit();
?>

10
sess.php Normal file
View File

@ -0,0 +1,10 @@
<?php
require 'header.php';
require_login();
$data = array();
header('Content-Type: application/json');
echo json_encode($_SESSION);
exit();

3
thumbs/README.md Normal file
View File

@ -0,0 +1,3 @@
# Thumbnail Folder
This is the folder for auto-generated thumbnails. There will be a top level file for each comics folder, and sub-folder named by the comic to hold the thumbnails for each issue. This folder must be owned by the user which runs the web server process.

46
variables-dist.php Normal file
View File

@ -0,0 +1,46 @@
<?php
//
// This is the session name. Set it to whatever you want.
//
define('SESSIONCOMICS', 'JackpotGeneric');
//
// The folder under which your comics are stored (no trailing slash)
//
define('COMICSDIR', '/storage/Comics');
//
// The folder where the thumbnails for folders and comics get generated.
// This folder is expected to be in the same folder as the project.
// This folder must be writable by the web server.
//
define('THUMBSDIR', 'thumbs');
//
// The folder where the comics get extracted for vieweing.
// This folder is expected to be in the same folder as the project.
// This folder must be writable by the web server.
//
define('EXTRACTSDIR', 'comics');
//
// Database information for tracking last read page
//
define('DBHOST', 'localhost');
define('DBUSER', 'comics');
define('DBPASS', 'comics');
define('DBNAME', 'comics');
//
// These are some variables used for development and debugging.
// They can be safely ignored.
//
define('DEBUG_ALL', false);
define('DEBUG_SHOWCOMICAJAX', false);
//
// Constants
//
define('SORTBYNAME', 10000001);
define('SORTBYDATE', 10000002);