Cosmetics.

This commit is contained in:
Lars Jung 2012-10-05 19:55:48 +02:00
parent 7494491637
commit c71f891af2
311 changed files with 55 additions and 46 deletions

View file

@ -0,0 +1,239 @@
<?php
require_once(str_replace("\\", "/", dirname(__FILE__)) . "/inc/H5ai.php");
$h5ai = new H5ai(__FILE__);
$options = $h5ai->getOptions();
function json_exit($obj) {
$obj["code"] = 0;
echo json_encode($obj);
exit;
}
function json_fail($code, $msg = "", $cond = true) {
if ($cond) {
echo json_encode(array("code" => $code, "msg" => $msg));
exit;
}
}
function check_keys($keys) {
$values = array();
foreach ($keys as $key) {
json_fail(101, "parameter '$key' is missing", !array_key_exists($key, $_REQUEST));
$values[] = $_REQUEST[$key];
}
return $values;
}
function delete_tempfile($file) {
@unlink($file);
}
list($action) = check_keys(array("action"));
if ($action === "getthumbsrc") {
if (!$options["thumbnails"]["enabled"]) {
json_fail(1, "thumbnails disabled");
}
H5ai::req_once("/server/php/inc/Thumb.php");
if (!Thumb::is_supported()) {
json_fail(2, "thumbnails not supported");
}
list($type, $srcAbsHref, $mode, $width, $height) = check_keys(array("type", "href", "mode", "width", "height"));
$thumb = new Thumb($h5ai);
$thumbHref = $thumb->thumb($type, $srcAbsHref, $mode, $width, $height);
if ($thumbHref === null) {
json_fail(3, "thumbnail creation failed");
}
json_exit(array("absHref" => $thumbHref));
}
else if ($action === "archive") {
json_fail(1, "downloads disabled", !$options["download"]["enabled"]);
list($execution, $format, $hrefs) = check_keys(array("execution", "format", "hrefs"));
H5ai::req_once("/server/php/inc/Archive.php");
$archive = new Archive($h5ai);
$hrefs = explode(":", trim($hrefs));
$target = $archive->create($execution, $format, $hrefs);
if (!is_string($target)) {
json_fail($target, "package creation failed");
}
json_exit(array("id" => basename($target), "size" => filesize($target)));
}
else if ($action === "getarchive") {
json_fail(1, "downloads disabled", !$options["download"]["enabled"]);
list($id, $as) = check_keys(array("id", "as"));
json_fail(2, "file not found", !preg_match("/^package-/", $id));
$target = $h5ai->getTempAbsPath() . "/" . $id;
json_fail(3, "file not found", !file_exists($target));
header("Content-Type: application/octet-stream");
header("Content-Length: " . filesize($target));
header("Content-Disposition: attachment; filename=\"$as\"");
header("Connection: close");
register_shutdown_function("delete_tempfile", $target);
readfile($target);
}
else if ($action === "getchecks") {
$php = version_compare(PHP_VERSION, "5.2.1") >= 0;
$archive = class_exists("PharData");
$gd = false;
if (function_exists("gd_info")) {
$gdinfo = gd_info();
$gd = array_key_exists("JPG Support", $gdinfo) && $gdinfo["JPG Support"] || array_key_exists("JPEG Support", $gdinfo) && $gdinfo["JPEG Support"];
}
$cache = @is_writable($h5ai->getCacheAbsPath());
$temp = @is_writable($h5ai->getTempAbsPath());
$tar = @preg_match("/tar$/", `which tar`) > 0;
$zip = @preg_match("/zip$/", `which zip`) > 0;
$convert = @preg_match("/convert$/", `which convert`) > 0;
$ffmpeg = @preg_match("/ffmpeg$/", `which ffmpeg`) > 0;
$du = @preg_match("/du$/", `which du`) > 0;
json_exit(array(
"php" => $php,
"cache" => $cache,
"thumbs" => $gd,
"temp" => $temp,
"archive" => $archive,
"tar" => $tar,
"zip" => $zip,
"convert" => $convert,
"ffmpeg" => $ffmpeg,
"du" => $du
));
}
else if ($action === "getentries") {
list($href, $content) = check_keys(array("href", "content"));
$content = intval($content, 10);
json_exit(array("entries" => $h5ai->getEntries($href, $content)));
}
else if ($action === "upload") {
list($href) = check_keys(array("href"));
json_fail(1, "wrong HTTP method", strtolower($_SERVER["REQUEST_METHOD"]) !== "post");
json_fail(2, "something went wrong", !array_key_exists("userfile", $_FILES));
$userfile = $_FILES["userfile"];
json_fail(3, "something went wrong [" . $userfile["error"] . "]", $userfile["error"] !== 0);
json_fail(4, "folders not supported", file_get_contents($userfile["tmp_name"]) === "null");
$upload_dir = $h5ai->getAbsPath($href);
$code = $h5ai->getHttpCode($href);
json_fail(5, "upload dir no h5ai folder or ignored", $code !== "h5ai" || $h5ai->is_ignored($upload_dir));
$dest = $upload_dir . "/" . utf8_encode($userfile["name"]);
json_fail(6, "already exists", file_exists($dest));
json_fail(7, "can't move uploaded file", !move_uploaded_file($userfile["tmp_name"], $dest));
json_exit();
}
else if ($action === "delete") {
json_fail(1, "deletion disabled", !$options["delete"]["enabled"]);
list($hrefs) = check_keys(array("hrefs"));
$hrefs = explode(":", trim($hrefs));
$errors = array();
foreach ($hrefs as $href) {
$d = H5ai::normalize_path(dirname($href), true);
$n = basename($href);
$code = $h5ai->getHttpCode($d);
if ($code == 401) {
}
if ($code == "h5ai" && !$h5ai->is_ignored($n)) {
$absPath = $h5ai->getAbsPath($href);
if (!unlink($absPath)) {
$errors[] = $href;
}
}
}
if ($errors->size) {
json_fail(2, "deletion failed for some");
} else {
json_exit();
}
}
else if ($action === "rename") {
json_fail(1, "renaming disabled", !$options["rename"]["enabled"]);
list($href, $name) = check_keys(array("href", "name"));
$d = H5ai::normalize_path(dirname($href), true);
$n = basename($href);
$code = $h5ai->getHttpCode($d);
if ($code == 401) {
}
if ($code == "h5ai" && !$h5ai->is_ignored($n)) {
$absPath = $h5ai->getAbsPath($href);
$folder = H5ai::normalize_path(dirname($absPath));
if (!rename($absPath, $folder . "/" . $name)) {
json_fail(2, "renaming failed");
}
}
json_exit();
}
else {
json_fail(100, "unsupported action");
}
?>

View file

@ -0,0 +1,131 @@
<?php
class Archive {
private static $TAR_CMD = "$(cd [ROOTDIR] && tar --no-recursion -cf [TARGET] [DIRS] [FILES])";
private static $ZIP_CMD = "$(cd [ROOTDIR] && zip [TARGET] [FILES])";
private $h5ai, $dirs, $files, $sc401;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
}
public function create($execution, $format, $hrefs) {
$this->dirs = array();
$this->files = array();
$this->sc401 = false;
$this->add_hrefs($hrefs);
if ($this->sc401) {
return 401;
} else if (count($this->dirs) === 0 && count($this->files) === 0) {
return 404;
}
$target = $this->h5ai->getTempAbsPath() . "/package-" . sha1(microtime(true) . rand()) . "." . $format;
try {
if ($execution === "shell") {
if ($format === "tar") {
$cmd = Archive::$TAR_CMD;
} else if ($format === "zip") {
$cmd = Archive::$ZIP_CMD;
} else {
return null;
}
$cmd = str_replace("[ROOTDIR]", "\"" . $this->h5ai->getRootAbsPath() . "\"", $cmd);
$cmd = str_replace("[TARGET]", "\"" . $target . "\"", $cmd);
$cmd = str_replace("[DIRS]", count($this->dirs) ? "\"" . implode("\" \"", array_values($this->dirs)) . "\"" : "", $cmd);
$cmd = str_replace("[FILES]", count($this->files) ? "\"" . implode("\" \"", array_values($this->files)) . "\"" : "", $cmd);
`$cmd`;
} else if ($execution === "php") {
$archive = new PharData($target);
foreach ($this->dirs as $archivedDir) {
$archive->addEmptyDir($archivedDir);
}
foreach ($this->files as $realFile => $archivedFile) {
$archive->addFile($realFile, $archivedFile); // very, very slow :/
}
}
} catch (Exeption $err) {
return 500;
}
return @filesize($target) ? $target : null;
}
private function add_hrefs($hrefs) {
foreach ($hrefs as $href) {
$d = H5ai::normalize_path(dirname($href), true);
$n = basename($href);
$code = $this->h5ai->getHttpCode($d);
if ($code == 401) {
$this->sc401 = true;
}
if ($code == "h5ai" && !$this->h5ai->is_ignored($n)) {
$realFile = $this->h5ai->getAbsPath($href);
$archivedFile = preg_replace("!^" . H5ai::normalize_path($this->h5ai->getRootAbsPath(), true) . "!", "", $realFile);
if (is_dir($realFile)) {
$this->add_dir($realFile, $archivedFile);
} else {
$this->add_file($realFile, $archivedFile);
}
}
}
}
private function add_file($realFile, $archivedFile) {
if (is_readable($realFile)) {
$this->files[$realFile] = $archivedFile;
}
}
private function add_dir($realDir, $archivedDir) {
$code = $this->h5ai->getHttpCode($this->h5ai->getAbsHref($realDir));
if ($code == 401) {
$this->sc401 = true;
}
if ($code == "h5ai") {
$this->dirs[] = $archivedDir;
$files = $this->h5ai->read_dir($realDir);
foreach ($files as $file) {
$realFile = $realDir . "/" . $file;
$archivedFile = $archivedDir . "/" . $file;
if (is_dir($realFile)) {
$this->add_dir($realFile, $archivedFile);
} else {
$this->add_file($realFile, $archivedFile);
}
}
}
}
}
?>

View file

@ -0,0 +1,131 @@
<?php
class Entry {
private static $FOLDER_SIZE_CMD = "du -sb \"[DIR]\"";
private static $cache = array();
private static function starts_with($sequence, $part) {
return (substr($sequence, 0, strlen($part)) === $part);
}
public static function get_cache() {
return Entry::$cache;
}
public static function get($h5ai, $absPath, $absHref) {
if (!Entry::starts_with($absHref, $h5ai->getRootAbsHref())) {
error_log("ILLEGAL REQUEST: " . $absHref . ", " . $absPath . ", " . $h5ai->getRootAbsHref());
return null;
}
if (array_key_exists($absHref, Entry::$cache)) {
return Entry::$cache[$absHref];
}
return new Entry($h5ai, $absPath, $absHref);
}
public static function sort() {
function cmp($entry1, $entry2) {
return strcasecmp($entry1->absHref, $entry2->absHref);
}
uasort(Entry::$cache, "cmp");
}
public $h5ai, $absPath, $absHref, $date, $size, $isFolder, $parent, $isContentFetched;
private function __construct($h5ai, $absPath, $absHref) {
$this->h5ai = $h5ai;
$this->absPath = H5ai::normalize_path($absPath);
$this->isFolder = is_dir($this->absPath);
$this->absHref = H5ai::normalize_path($absHref, $this->isFolder);
$this->date = filemtime($this->absPath);
if ($this->isFolder) {
$this->size = null;
$options = $h5ai->getOptions();
if ($options["foldersize"]["enabled"]) {
$cmd = str_replace("[DIR]", $this->absPath, Entry::$FOLDER_SIZE_CMD);
$this->size = intval(preg_replace("/\s.*$/", "", `$cmd`), 10);
}
} else {
$this->size = filesize($this->absPath);
}
$this->parent = null;
$parentAbsHref = H5ai::normalize_path(dirname($this->absHref), true);
if ($this->absHref !== "/" && Entry::starts_with($parentAbsHref, $h5ai->getRootAbsHref())) {
$this->parent = Entry::get($this->h5ai, H5ai::normalize_path(dirname($this->absPath)), $parentAbsHref);
}
$this->isContentFetched = false;
Entry::$cache[$this->absHref] = $this;
}
public function toJsonObject($withStatus) {
$obj = array(
"absHref" => $this->absHref,
"time" => ($this->date * 1000),
"size" => $this->size
);
if ($withStatus && $this->isFolder) {
$obj["status"] = $this->h5ai->getHttpCode($this->absHref);
$obj["content"] = $this->isContentFetched;
}
return $obj;
}
public function getParent() {
return $this->parent;
}
public function getContent() {
$content = array();
if ($this->h5ai->getHttpCode($this->absHref) !== "h5ai") {
return $content;
}
$files = $this->h5ai->read_dir($this->absPath);
foreach ($files as $file) {
$entry = Entry::get($this->h5ai, $this->absPath . "/" . $file, $this->absHref . rawurlencode($file));
$content[$entry->absPath] = $entry;
}
$this->isContentFetched = true;
return $content;
}
}
?>

View file

@ -0,0 +1,378 @@
<?php
define("H5AI_ABS_PATH", H5ai::normalize_path(dirname(dirname(dirname(dirname(__FILE__))))));
H5ai::req_once("/conf/config.php");
H5ai::req_once("/server/php/inc/Entry.php");
class H5ai {
public static final function normalize_path($path, $endWithSlash = false) {
$path = str_replace("\\", "/", $path);
return preg_match("#^(\w:)?/$#", $path) ? $path : (preg_replace('#/$#', '', $path) . ($endWithSlash ? "/" : ""));
}
public static final function req_once($lib) {
require_once(H5AI_ABS_PATH . $lib);
}
private static final function load_config($file) {
if (!file_exists($file)) {
return array();
}
$str = file_get_contents($file);
// remove comments to get pure json
$str = preg_replace("/\/\*.*?\*\/|\/\/.*?(\n|$)/s", "", $str);
return json_decode($str, true);
}
private static final function merge_config($a, $b) {
$result = array_merge(array(), $a);
foreach ($b as $key => $value) {
$result[$key] = array_merge($result[$key], $b[$key]);
}
return $result;
}
private static $H5AI_CONTENT_TYPE = "Content-Type: text/html;h5ai=";
private $requested_from,
$h5aiAbsPath,
$rootAbsPath, $ignore_names, $ignore_patterns, $index_files,
$config, $options,
$rootAbsHref, $h5aiAbsHref,
$absHref, $absPath;
public function __construct($requested_from) {
$this->requested_from = H5ai::normalize_path($requested_from);
$this->h5aiAbsPath = H5ai::normalize_path(H5AI_ABS_PATH);
$this->rootAbsPath = H5ai::normalize_path(dirname(H5AI_ABS_PATH));
global $H5AI_CONFIG;
$this->ignore_names = $H5AI_CONFIG["IGNORE"];
$this->ignore_patterns = $H5AI_CONFIG["IGNORE_PATTERNS"];
$this->index_files = $H5AI_CONFIG["INDEX_FILES"];
$this->config = array("options" => array(), "types" => array(), "langs" => array());
$this->config = H5ai::merge_config($this->config, H5ai::load_config($this->h5aiAbsPath . "/conf/config.json"));
$this->options = $this->config["options"];
$this->h5aiAbsHref = H5ai::normalize_path($this->options["h5aiAbsHref"], true);
$this->rootAbsHref = H5ai::normalize_path(dirname($this->options["h5aiAbsHref"]), true);
$this->absHref = H5ai::normalize_path(preg_replace('/[^\\/]*$/', '', getenv("REQUEST_URI")), true);
$this->absPath = $this->getAbsPath($this->absHref);
$this->config = H5ai::merge_config($this->config, H5ai::load_config($this->absPath . "/_h5ai.config.json"));
$this->options = $this->config["options"];
}
public function getRootAbsPath() {
return $this->rootAbsPath;
}
public function getH5aiAbsPath() {
return $this->h5aiAbsPath;
}
public function getRootAbsHref() {
return $this->rootAbsHref;
}
public function getH5aiAbsHref() {
return $this->h5aiAbsHref;
}
public function getCacheAbsPath() {
return $this->h5aiAbsPath . '/cache';
}
public function getCacheAbsHref() {
return $this->h5aiAbsHref . 'cache/';
}
public function getTempAbsPath() {
// return H5ai::normalize_path(sys_get_temp_dir());
return $this->h5aiAbsPath . '/cache';
}
public function getOptions() {
return $this->options;
}
public function getAbsHref($absPath = null, $endWithSlash = true) {
if ($absPath === null) {
return $this->absHref;
}
$absPath = substr($absPath, strlen($this->rootAbsPath));
$parts = explode("/", $absPath);
$encodedParts = array();
foreach ($parts as $part) {
$encodedParts[] = rawurlencode($part);
}
return H5ai::normalize_path($this->rootAbsHref . implode("/", $encodedParts), $endWithSlash);
}
public function getAbsPath($absHref = null) {
if ($absHref === null) {
return $this->absPath;
}
$absHref = substr($absHref, strlen($this->rootAbsHref));
return H5ai::normalize_path($this->rootAbsPath . "/" . rawurldecode($absHref));
}
public function is_ignored($name) {
// always ignore
if ($name === "." || $name === "..") {
return true;
}
if (in_array($name, $this->ignore_names)) {
return true;
}
foreach ($this->ignore_patterns as $re) {
if (preg_match($re, $name)) {
return true;
}
}
return false;
}
public function read_dir($path) {
$content = array();
if (is_dir($path)) {
if ($dir = opendir($path)) {
while (($file = readdir($dir)) !== false) {
if (!$this->is_ignored($file) && !$this->is_ignored($this->getAbsHref($path) . $file)) {
$content[] = $file;
}
}
closedir($dir);
}
}
return $content;
}
public function getHttpCode($absHref) {
if (!is_dir($this->getAbsPath($absHref))) {
return null;
}
if ($this->options["folderstatus"]["enabled"]) {
$folders = $this->options["folderstatus"]["folders"];
if (array_key_exists($absHref, $folders)) {
return $folders[$absHref];
}
}
// return $this->fetchHttpCode($absHref);
return $this->guessHttpCode($absHref);
}
public function guessHttpCode($absHref) {
$absPath = $this->getAbsPath($absHref);
foreach ($this->index_files as $if) {
if (file_exists($absPath . "/" . $if)) {
if ($if === "index.php") {
$fileheader = file_get_contents($absPath . "/" . $if, false, null, -1, 50);
return stripos($fileheader, H5ai::$H5AI_CONTENT_TYPE) === false ? 200 : "h5ai";
}
return 200;
}
}
return "h5ai";
}
public function fetchHttpCode($absHref) {
$host = getenv("HTTP_HOST");
$port = getenv("SERVER_PORT");
$msg = "HEAD $absHref HTTP/1.1\r\nHost: $host\r\nConnection: Close\r\n";
if (isset($_SERVER['PHP_AUTH_USER'])) {
$msg .= "Authorization: Basic " . base64_encode($_SERVER['PHP_AUTH_USER'] . ":" . $_SERVER['PHP_AUTH_PW']) . "\r\n";
}
$msg .= "\r\n";
$errno = "";
$errstr = "";
$socket = fsockopen($host, $port, $errno, $errstr, 30);
if($socket === 0) {
return null;
}
fwrite($socket, $msg);
$content = fgets($socket);
$code = intval(trim(substr($content, 9, 4)));
if ($code === 200) {
while ($content !== false && stripos($content, "Content-Type") === false) {
$content = fgets($socket);
}
if (stripos($content, H5ai::$H5AI_CONTENT_TYPE) !== false) {
$code = "h5ai";
}
}
fclose($socket);
return $code;
}
private function fileExists($file) {
return is_string($file) && file_exists($file);
}
public function getGenericJson() {
$entries = $this->getEntries($this->absHref, 1);
$header = $this->options["custom"]["header"];
$footer = $this->options["custom"]["footer"];
$header = $this->fileExists($header ? $this->absPath . "/" . $header : null) ? $header : null;
$footer = $this->fileExists($footer ? $this->absPath . "/" . $footer : null) ? $footer : null;
$json = array(
"id" => $this->requested_from === $this->h5aiAbsPath . "/server/php/index.php" ? "php" : "idx.php",
"serverName" => strtolower(preg_replace("/\\/.*$/", "", getenv("SERVER_SOFTWARE"))),
"serverVersion" => strtolower(preg_replace("/^.*\\//", "", preg_replace("/\\s.*$/", "", getenv("SERVER_SOFTWARE")))),
"customHeader" => $header,
"customFooter" => $footer,
"entries" => $entries
);
return json_encode($json) . "\n";
}
public function getCustomConfig() {
$config = "_h5ai.config.json";
$config = $this->fileExists($config ? $this->absPath . "/" . $config : "ignore") ? $config : "ignore";
return $config;
}
public function getEntries($absHref, $content) {
$folder = Entry::get($this, $this->getAbsPath($absHref), $absHref);
if ($content > 1 && $folder !== null) {
foreach ($folder->getContent() as $entry) {
$entry->getContent();
}
$folder = $folder->getParent();
}
while ($content > 0 && $folder !== null) {
$folder->getContent();
$folder = $folder->getParent();
}
Entry::sort();
$entries = array();
foreach (Entry::get_cache() as $entry) {
$entries[] = $entry->toJsonObject(true);
}
return $entries;
}
public function getNoJsFallback() {
date_default_timezone_set ("UTC");
function _cmp($entry1, $entry2) {
if ($entry1->isFolder && !$entry2->isFolder) {
return -1;
}
if (!$entry1->isFolder && $entry2->isFolder) {
return 1;
}
return strcasecmp($entry1->absHref, $entry2->absHref);
}
$folder = Entry::get($this, $this->absPath, $this->absHref);
$entries = $folder->getContent();
uasort($entries, "_cmp");
$html = "<table>";
$html .= "<tr><th></th><th><span>Name</span></th><th><span>Last modified</span></th><th><span>Size</span></th></tr>";
if ($folder->parent) {
$html .= "<tr><td></td><td><a href=\"..\">Parent Directory</a></td><td></td><td></td></tr>";
}
foreach ($entries as $entry) {
$html .= "<tr>";
$html .= "<td></td>";
$html .= "<td><a href=\"" . $entry->absHref . "\">" . basename($entry->absPath) . ($entry->isFolder ? "/" : "") . "</a></td>";
$html .= "<td>" . date("Y-m-d H:i", $entry->date) . "</td>";
$html .= "<td>" . ($entry->size !== null ? intval($entry->size / 1000) . " KB" : "" ) . "</td>";
$html .= "</tr>";
}
$html .= "</table>";
return $html;
}
}
?>

View file

@ -0,0 +1,376 @@
<?php
class Thumb {
private static $FFMPEG = "ffmpeg -i \"[SOURCE]\" -an -ss 3 -vframes 1 \"[TARGET]\"";
private static $CONVERT = "convert -strip \"[SOURCE][0]\" \"[TARGET]\"";
public static final function is_supported() {
if (!function_exists("gd_info")) {
return false;
}
$gdinfo = gd_info();
return array_key_exists("JPG Support", $gdinfo) && $gdinfo["JPG Support"] || array_key_exists("JPEG Support", $gdinfo) && $gdinfo["JPEG Support"];
}
private $h5ai;
public function __construct($h5ai) {
$this->h5ai = $h5ai;
}
public function thumb($type, $sourceAbsHref, $mode, $width, $height) {
$sourceAbsPath = $this->h5ai->getAbsPath($sourceAbsHref);
if ($type === "img") {
$captureAbsPath = $sourceAbsPath;
} else if ($type === "mov") {
$captureAbsPath = $this->capture(Thumb::$FFMPEG, $sourceAbsPath);
} else if ($type === "doc") {
$captureAbsPath = $this->capture(Thumb::$CONVERT, $sourceAbsPath);
}
return $this->thumb_href($captureAbsPath, $mode, $width, $height);
}
private function thumb_href($sourceAbsPath, $mode, $width, $height) {
if (!file_exists($sourceAbsPath)) {
return null;
}
$name = "thumb-" . sha1("$sourceAbsPath-$width-$height-$mode") . ".jpg";
$thumbAbsPath = $this->h5ai->getCacheAbsPath() . "/" . $name;
$thumbAbsHref = $this->h5ai->getCacheAbsHref() . $name;
if (!file_exists($thumbAbsPath) || filemtime($sourceAbsPath) >= filemtime($thumbAbsPath)) {
$image = new Image();
$image->setSource($sourceAbsPath);
$image->thumb($mode, $width, $height);
$image->saveDestJpeg($thumbAbsPath, 80);
}
return file_exists($thumbAbsPath) ? $thumbAbsHref : null;
}
private function capture($cmd, $sourceAbsPath) {
if (!file_exists($sourceAbsPath)) {
return null;
}
$captureAbsPath = $this->h5ai->getCacheAbsPath() . "/capture-" . sha1($sourceAbsPath) . ".jpg";
if (!file_exists($captureAbsPath) || filemtime($sourceAbsPath) >= filemtime($captureAbsPath)) {
$cmd = str_replace("[SOURCE]", $sourceAbsPath, $cmd);
$cmd = str_replace("[TARGET]", $captureAbsPath, $cmd);
`$cmd`;
}
return file_exists($captureAbsPath) ? $captureAbsPath : null;
}
}
class Magic {
private static $GET_SIZE_CMD = "identify -format \"%w %h\" \"[SOURCE]\"";
private static $RESIZE_CMD = "convert -strip -transparent-color \"#ffffff\" -resize [WIDTH]x[HEIGHT] -quality 80 \"[SOURCE]\" \"[TARGET]\"";
private static $SQUARE_CMD = "convert -strip -transparent-color \"#ffffff\" -crop [CWIDTH]x[CWIDTH]+[CLEFT]+[CTOP] -resize [WIDTH]x[WIDTH] -quality 80 \"[SOURCE]\" \"[TARGET]\"";
private static final function img_size($source) {
$cmd = str_replace("[SOURCE]", str_replace("\"", "\\\"", $source), Magic::$GET_SIZE_CMD);
$size = explode(" ", `$cmd`);
$size[0] = intval($size[0]);
$size[1] = intval($size[1]);
return $size;
}
private static final function rational($source, $target, $width, $height) {
$cmd = str_replace("[SOURCE]", str_replace("\"", "\\\"", $source), Magic::$RESIZE_CMD);
$cmd = str_replace("[TARGET]", str_replace("\"", "\\\"", $target), $cmd);
$cmd = str_replace("[WIDTH]", $width, $cmd);
$cmd = str_replace("[HEIGHT]", $height, $cmd);
`$cmd`;
}
private static final function square($source, $target, $width) {
$size = Magic::img_size($source);
$w = $size[0];
$h = $size[1];
$cwidth = min($w, $h);
$cleft = ($w - $cwidth) / 2;
$ctop = ($h - $cwidth) / 2;
$cmd = str_replace("[SOURCE]", str_replace("\"", "\\\"", $source), Magic::$SQUARE_CMD);
$cmd = str_replace("[TARGET]", str_replace("\"", "\\\"", $target), $cmd);
$cmd = str_replace("[CWIDTH]", $cwidth, $cmd);
$cmd = str_replace("[CLEFT]", $cleft, $cmd);
$cmd = str_replace("[CTOP]", $ctop, $cmd);
$cmd = str_replace("[WIDTH]", $width, $cmd);
`$cmd`;
}
public static final function thumb($mode, $source, $target, $width, $height = null, $color = null) {
if ($height === null) {
$height = $width;
}
if ($mode === "square") {
Magic::square($source, $target, $width);
} elseif ($mode === "rational") {
Magic::rational($source, $target, $width, $height);
}
}
}
class Image {
private $sourceFile, $source, $width, $height, $type, $dest;
public static final function is_supported() {
if (!function_exists("gd_info")) {
return false;
}
$gdinfo = gd_info();
return array_key_exists("JPG Support", $gdinfo) && $gdinfo["JPG Support"] || array_key_exists("JPEG Support", $gdinfo) && $gdinfo["JPEG Support"];
}
public function __construct($filename = null) {
$this->sourceFile = null;
$this->source = null;
$this->width = null;
$this->height = null;
$this->type = null;
$this->dest = null;
$this->setSource($filename);
}
public function __destruct() {
$this->releaseSource();
$this->releaseDest();
}
public function setSource($filename) {
$this->releaseSource();
$this->releaseDest();
if (is_null($filename)) {
return;
}
$this->sourceFile = $filename;
list($this->width, $this->height, $this->type) = @getimagesize($this->sourceFile);
if (!$this->width || !$this->height) {
$this->sourceFile = null;
$this->width = null;
$this->height = null;
$this->type = null;
return;
}
$this->source = imagecreatefromstring(file_get_contents($this->sourceFile));
}
public function saveDestJpeg($filename, $quality = 80) {
if (!is_null($this->dest)) {
@imagejpeg($this->dest, $filename, $quality);
@chmod($filename, 0775);
}
}
public function saveDestPng($filename, $quality = 9) {
if (!is_null($this->dest)) {
@imagepng($this->dest, $filename, $quality);
@chmod($filename, 0775);
}
}
public function releaseDest() {
if (!is_null($this->dest)) {
@imagedestroy($this->dest);
$this->dest = null;
}
}
public function releaseSource() {
if (!is_null($this->source)) {
@imagedestroy($this->source);
$this->sourceFile = null;
$this->source = null;
$this->width = null;
$this->height = null;
$this->type = null;
}
}
private function magic($destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight, $canWidth = null, $canHeight = null, $color = null) {
if (is_null($this->source)) {
return;
}
if ($canWidth === 0) {
$canWidth = 1;
}
if ($canHeight === 0) {
$canHeight = 1;
}
if ($destWidth === 0) {
$destWidth = 1;
}
if ($destHeight === 0) {
$destHeight = 1;
}
if (!is_null($canWidth) && !is_null($canHeight)) {
$this->dest = imagecreatetruecolor($canWidth, $canHeight);
} else {
$this->dest = imagecreatetruecolor($destWidth, $destHeight);
}
if (is_null($color)) {
$color = array(255, 255, 255);
}
$icol = imagecolorallocate($this->dest, $color[0], $color[1], $color[2]);
imagefill($this->dest, 0, 0, $icol);
imagecopyresampled($this->dest, $this->source, $destX, $destY, $srcX, $srcY, $destWidth, $destHeight, $srcWidth, $srcHeight);
}
public function thumb($mode, $width, $height = null, $color = null) {
if ($height === null) {
$height = $width;
}
if ($mode === "square") {
$this->squareThumb($width);
} elseif ($mode === "rational") {
$this->rationalThumb($width, $height);
} elseif ($mode === "center") {
$this->centerThumb($width, $height, $color);
} else {
$this->freeThumb($width, $height);
}
}
public function squareThumb($width) {
if (is_null($this->source)) {
return;
}
$a = min($this->width, $this->height);
$x = intval(($this->width - $a) / 2);
$y = intval(($this->height - $a) / 2);
$this->magic(0, 0, $x, $y, $width, $width, $a, $a);
}
public function rationalThumb($width, $height) {
if (is_null($this->source)) {
return;
}
$r = 1.0 * $this->width / $this->height;
$h = $height;
$w = $r * $h;
if ($w > $width) {
$w = $width;
$h = 1.0 / $r * $w;
}
$w = intval($w);
$h = intval($h);
$this->magic(0, 0, 0, 0, $w, $h, $this->width, $this->height);
}
public function centerThumb($width, $height, $color = null) {
if (is_null($this->source)) {
return;
}
$r = 1.0 * $this->width / $this->height;
$h = $height;
$w = $r * $h;
if ($w > $width) {
$w = $width;
$h = 1.0 / $r * $w;
}
$w = intval($w);
$h = intval($h);
$x = intval(($width - $w) / 2);
$y = intval(($height - $h) / 2);
$this->magic($x, $y, 0, 0, $w, $h, $this->width, $this->height, $width, $height, $color);
}
public function freeThumb($width, $height) {
if (is_null($this->source)) {
return;
}
$w = intval($width);
$h = intval($height);
$this->magic(0, 0, 0, 0, $w, $h, $this->width, $this->height);
}
}
?>

View file

@ -0,0 +1,66 @@
|<?php
| header("Content-type: text/html;{{pkg.name}}={{pkg.version}}");
| $h5ai_php = str_replace("\\", "/", dirname(__FILE__)) . "/inc/H5ai.php";
| if (!file_exists($h5ai_php)) {
| function find_h5ai($path, $h5ai) {
| if (file_exists($path . $h5ai)) { return $path . $h5ai; }
| $parent = str_replace("\\", "/", dirname($path));
| if ($parent !== $path) { return find_h5ai($parent, $h5ai); }
| error_log("h5ai not found: " . __FILE__);
| }
| $h5ai_php = find_h5ai(str_replace("\\", "/", dirname(__FILE__)), "/_{{pkg.name}}/server/php/inc/H5ai.php");
| }
| require_once($h5ai_php);
| $h5ai = new H5ai(__FILE__);
| $h5aiAbsHref = $h5ai->getH5aiAbsHref();
| $isHeadRequest = stripos($_SERVER["REQUEST_METHOD"], "HEAD");
|?>
- var appHref = "<?php echo $h5aiAbsHref; ?>client"
- var json = "<?php if (!$isHeadRequest) { echo $h5ai->getGenericJson(); }?>"
- var fallback = "<?php if (!$isHeadRequest) { echo $h5ai->getNoJsFallback(); }?>"
- var config = "<?php if (!$isHeadRequest) { echo $h5ai->getCustomConfig(); }?>"
doctype 5
//if lt IE 9
<html class="no-js oldie" lang="en">
//[if gt IE 8]><!
html.no-js( lang="en" )
//<![endif]
head
meta( charset="utf-8" )
meta( http-equiv="X-UA-Compatible", content="IE=edge,chrome=1" )
title Directory index · styled with {{pkg.name}} {{pkg.version}}
meta( name="description", content="Directory index styled with {{pkg.name}} {{pkg.version}} ({{pkg.url}})" )
meta( name="viewport", content="width=device-width" )
link( rel="shortcut icon", href!="#{appHref}/images/app-16x16.ico" )
link( rel="apple-touch-icon", type="image/png", href!="#{appHref}/images/app-48x48.png" )
link( rel="stylesheet", href="//fonts.googleapis.com/css?family=Ubuntu+Mono:400,700,400italic,700italic|Ubuntu:400,700,400italic,700italic" )
link( rel="stylesheet", href!="#{appHref}/css/styles.css" )
script( src!="#{appHref}/js/scripts.js", data-config!="#{config}" )
body#h5ai-main
div#topbar.clearfix
ul#navbar
div#content
div#extended.clearfix
div#bottombar.clearfix
span.left
a#h5ai-reference( href="{{pkg.url}}", title="{{pkg.name}} project page" )
| {{pkg.name}} {{pkg.version}}
span.hideOnJs.noJsMsg
| ⚡ JavaScript is disabled! ⚡
span.oldBrowser
| ⚡ Some features disabled! Works best in
a( href="http://browsehappy.com" ) modern browsers
| . ⚡
span.right
span.center
div#data-generic-json.hidden !{json}
div#data-php-no-js-fallback.hideOnJs !{fallback}