diff options
| author | root | 2014-10-19 03:54:53 +0200 |
|---|---|---|
| committer | root | 2014-10-19 03:54:53 +0200 |
| commit | 2330bb06ececee220d854883a2870a3adf17c277 (patch) | |
| tree | e49f6b561faf5b39a81d57d54fa57a1550074c0f | |
| parent | a3009bf57d50fbc25a707b32fb3c5c170d011680 (diff) | |
| download | jungegemeinde-2330bb06ececee220d854883a2870a3adf17c277.tar.gz | |
Version 4.1. Support for photo galleries and advanced caching.
| -rw-r--r-- | action.php | 65 | ||||
| -rw-r--r-- | bootstrap.php | 9 | ||||
| -rw-r--r-- | class/cache.php | 74 | ||||
| -rw-r--r-- | class/moar.php | 58 | ||||
| -rw-r--r-- | class/mysql.php | 17 | ||||
| -rw-r--r-- | error.png | bin | 0 -> 2216 bytes | |||
| -rw-r--r-- | error.svg | 5 | ||||
| -rw-r--r-- | foto/nginx.conf | 4 | ||||
| -rw-r--r-- | foto/protected.php | 25 | ||||
| -rw-r--r-- | foto/upload.php | 57 | ||||
| -rw-r--r-- | functions.php | 419 | ||||
| -rwxr-xr-x | images/UploadHandler.php | 1351 | ||||
| -rw-r--r-- | images/index.php | 47 | ||||
| -rw-r--r-- | index.php | 42 | ||||
| -rw-r--r-- | js/gallery.min.js | 1 | ||||
| -rw-r--r-- | js/upload.min.js | 1 | ||||
| -rw-r--r-- | loading.gif | bin | 0 -> 3897 bytes | |||
| -rw-r--r-- | play-pause.png | bin | 0 -> 606 bytes | |||
| -rw-r--r-- | play-pause.svg | 6 | ||||
| -rw-r--r-- | progressbar.gif | bin | 0 -> 3323 bytes | |||
| -rw-r--r-- | protected/README | 7 | ||||
| -rwxr-xr-x | static/footer.php | 31 | ||||
| -rw-r--r-- | static/gallery.min.css | 2 | ||||
| -rw-r--r-- | static/header.php | 17 | ||||
| -rw-r--r-- | static/modal-delete-gallery.php | 24 | ||||
| -rw-r--r-- | static/modal-edit-gallery.php | 40 | ||||
| -rw-r--r-- | static/modal-new-gallery.html | 40 | ||||
| -rw-r--r-- | static/style.css | 24 | ||||
| -rw-r--r-- | static/style.min.css | 2 | ||||
| -rw-r--r-- | video-play.png | bin | 0 -> 2811 bytes | |||
| -rw-r--r-- | video-play.svg | 5 |
31 files changed, 2242 insertions, 131 deletions
@@ -12,7 +12,7 @@ if ( ! isset($_GET["task"]) || $_GET["task"] == "" ){ ob_clean(); exit; } -$cache = false; +$c->bypassCache = true; switch($_GET["task"]){ case("login"): @@ -287,6 +287,69 @@ JG Adlershof"; ob_end_flush(); exit; break; + case("gallery"): + lredirect("foto"); + if ( $_SERVER['REQUEST_METHOD'] != 'POST' ){ + header($_SERVER["SERVER_PROTOCOL"] . " 405 Method Not Allowed"); + ob_clean(); + echo "Method not allowed"; + exit; + } + if ( ! isset($_POST["name"]) || $_POST["name"] == "" ){ + //print_gallery("name"); + redirect("foto"); + } + if ( ! isset($_POST["desc"]) ){ + $_POST["desc"] = ""; + } + $sql = $db->prepare("INSERT INTO " . DBPREFIX . "gallery (id, name, description, owner, restricted, time) VALUES (NULL, %s, %s, %d, %d, %d);", $_POST["name"], $_POST["desc"], $user->getUserId(), 0, time() ); + if ( $db->doQuery($sql) ){ + $c->flush2(); + redirect("foto"); + } else { + redirect("foto"); + //print_gallery("database"); + } + break; + case("editGallery"): + if ( $_SERVER['REQUEST_METHOD'] != 'POST' ){ + header($_SERVER["SERVER_PROTOCOL"] . " 405 Method Not Allowed"); + ob_clean(); + echo "Method not allowed"; + exit; + } + if ( ! isset($_GET["gallery"]) || $_GET["gallery"] == "" ){ + $_GET["gallery"] = 0; + } + lredirect( "gallery;gallery=".htmlentities($_GET["gallery"]).";edit=1" ); + if ( ! isset($_POST["name"]) || $_POST["name"] == "" || ! isset($_POST["desc"]) || $_POST["desc"] == "" || $_GET["gallery"] == 0 ){ + redirect("foto"); + } + $sql = $db->prepare("UPDATE " . DBPREFIX . "gallery SET name = %s, description = %s WHERE id = %d;", $_POST["name"], $_POST["desc"], $_GET["gallery"]); + if ( $db->doQuery($sql) ){ + $c->flush2(); + redirect( "gallery&gallery=" . htmlentities($_GET["gallery"]) ); + } else { + redirect("foto"); + } + break; + case("deleteGallery"): + if ( $_SERVER['REQUEST_METHOD'] != 'POST' ){ + header($_SERVER["SERVER_PROTOCOL"] . " 405 Method Not Allowed"); + ob_clean(); + echo "Method not allowed"; + exit; + } + lredirect( "gallery;gallery=".htmlentities($_GET["gallery"]) ); + if ( ! isset($_GET["gallery"]) || $_GET["gallery"] == "" ){ + redirect( "gallery;gallery=".htmlentities($_GET["gallery"]) ); + } + rrmdir( IMAGE_PATH . $_GET["gallery"] ); + $sql = $db->prepare("DELETE FROM " . DBPREFIX . "gallery WHERE id = %d;", $_GET["gallery"]); + if ( $db->doQuery($sql) ) + $c->flush2(); + redirect("foto"); + break; default: print_404(); break; diff --git a/bootstrap.php b/bootstrap.php index aab8bbe..ed260d9 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -21,6 +21,10 @@ if ( ! defined('HOST') ) if ( ! defined('DOMAIN') ) define('DOMAIN', SCHEME . HOST); + define('PROTECTED_BASE', 'protected/'); + define('IMAGE_PATH', ABSPATH . PROTECTED_BASE); + define('IMAGE_URL' , DOMAIN . '/images/'); + # define session name if ( ! defined('SESSION') ) define('SESSION', 'JGSID'); @@ -36,6 +40,10 @@ if ( ! defined('INCLASS') ) define('REDIS_CONNECT', '/var/run/redis/redis.sock'); if ( ! defined('REDIS_DB') ) define('REDIS_DB', 2); + if ( ! defined('PAGECACHE_DB') ) + define('PAGECACHE_DB', 1); + if ( ! defined('SECOND_CACHE') ) + define('SECOND_CACHE', 3); if ( ! defined('CACHEPREFIX') ) define('CACHEPREFIX', 'jg_'); @@ -50,6 +58,7 @@ require(ABSPATH . 'functions.php'); require(ABSPATH . INCLASS . 'cache.php'); require(ABSPATH . INCLASS . 'mysql.php'); require(ABSPATH . INCLASS . 'user.php'); +require(ABSPATH . INCLASS . 'moar.php'); # first install only if ( file_exists(ABSPATH . 'setup.php') ) diff --git a/class/cache.php b/class/cache.php index 8005484..b64ab9d 100644 --- a/class/cache.php +++ b/class/cache.php @@ -2,11 +2,17 @@ class cache { public $token = ""; + public $bypassCache; private $db; + private $dbnmr; + private $dbpagecache; + private $db2nd; + public function __construct($rconnect, $rdb){ $this->db = new Redis(); + $this->bypassCache=false; try { $this->db->connect($rconnect); @@ -23,6 +29,9 @@ class cache { } catch (Exception $e) { return $e->getMessage(); } + $this->dbnmr = $rdb; + $this->dbpagecache = PAGECACHE_DB; + $this->db2nd = SECOND_CACHE; } public function check(){ @@ -58,12 +67,75 @@ class cache { return $this->db->delete($key); } + public function setPageCache($key, $value, $ttl = 3600){ + $this->db->select( $this->dbpagecache ); + $this->db->set( $key, $value, $ttl ); + $this->db->select( $this->dbnmr ); + } + + public function getPageCache($key){ + $this->db->select( $this->dbpagecache ); + $data = $this->db->get( $key ); + $this->db->select( $this->dbnmr ); + return $data; + } + + public function existsPageCache($key){ + $this->db->select( $this->dbpagecache ); + $data = $this->exists( $key ); + $this->db->select( $this->dbnmr ); + return $data; + } + + public function flushPageCache(){ + $this->db->select( $this->dbpagecache ); + $this->db->flushDB(); + $this->db->select( $this->dbnmr ); + } + public function flush($token = null){ + $this->flushPageCache(); if ( is_null($token) ) return $this->db->flushDB(); else return $this->db->delete($token); } -} + public function flushAll(){ + $this->db->flushDB(); + $this->flushPageCache(); + $this->flush2(); + } + public function set2($key, $value, $ttl = null){ + $this->db->select( $this->db2nd ); + $this->db->set($key, $value, $ttl); + $this->db->select( $this->dbnmr ); + } + + public function get2($key){ + $this->db->select( $this->db2nd ); + $data = $this->db->get($key); + $this->db->select( $this->dbnmr ); + return $data; + } + + public function exists2($key){ + $this->db->select( $this->db2nd ); + $data = $this->db->exists($key); + $this->db->select( $this->dbnmr ); + return $data; + } + + public function flush2($token = null){ + $this->db->select( $this->db2nd ); + if ( is_null($token) ) + $data = $this->db->flushDB(); + else + $data = $this->db->delete($token); + + $this->db->select( $this->dbnmr ); + $this->flushPageCache(); + return $data; + } +} diff --git a/class/moar.php b/class/moar.php new file mode 100644 index 0000000..822640f --- /dev/null +++ b/class/moar.php @@ -0,0 +1,58 @@ +<?php + +class Moar { + + private $header = array(); + private $footer = array(); + + public function __construct(){ + return true; + } + + public function addHeader($string){ + $this->header[] = $string; + } + + public function addFooter($string){ + $this->footer[] = $string; + } + + public function playHeader(){ + if ( ! empty( $this->header ) ){ + foreach( $this->header as $value ){ + echo $value; + } + } + $this->deleteHeader(); + } + + public function playFooter(){ + if ( ! empty( $this->footer ) ){ + foreach( $this->footer as $value ){ + echo $value; + } + } + $this->deleteFooter(); + } + + public function deleteHeader(){ + unset( $this->header ); + } + + public function deleteFooter(){ + unset( $this->footer ); + + } + + public function magicHeader($html){ + ob_start(); + $this->playHeader(); + $header = ob_get_contents(); + ob_end_clean(); + return preg_replace("/\<\!\-\-%%placeholder\-head%%\-\-\>/", $header, $html); + } + + public function __destruct(){ + return true; + } +} diff --git a/class/mysql.php b/class/mysql.php index 8d75538..eea5f95 100644 --- a/class/mysql.php +++ b/class/mysql.php @@ -72,6 +72,10 @@ class db { return true; } + public function affectedRows(){ + return $this->db->affected_rows; + } + # code by WordPress. See @link https://core.trac.wordpress.org/browser/branches/4.0/src/wp-includes/wp-db.php#L1154 # syntax like sprintf() public function prepare( $query, $args ) { @@ -143,7 +147,18 @@ class db { ) ENGINE=InnoDB;'; - if ( ! $this->execMultipleQueries('BEGIN; '. $user_table . ' ' . $banned_user_table . ' ' . $jg_table . ' COMMIT;') ) + $gallery_table = + 'CREATE TABLE IF NOT EXISTS ' . DBPREFIX . 'gallery + ( id INTEGER AUTO_INCREMENT NOT NULL, PRIMARY KEY(id), + name varchar(70), UNIQUE(name), + description varchar(500), + owner INTEGER, FOREIGN KEY(owner) REFERENCES ' . DBPREFIX . 'user(id), + restricted INTEGER, + time INTEGER + ) + ENGINE=InnoDB;'; + + if ( ! $this->execMultipleQueries('BEGIN; '. $user_table . ' ' . $banned_user_table . ' ' . $jg_table . ' ' . $gallery_table . ' COMMIT;') ) failure("<p>There was a problem during bootstrapping the database schema. " . $this->db->error . "</p>", '500 Server Failure', false, "<h1>CREATE TABLE FAILED</h1>"); } diff --git a/error.png b/error.png Binary files differnew file mode 100644 index 0000000..a5577c3 --- /dev/null +++ b/error.png diff --git a/error.svg b/error.svg new file mode 100644 index 0000000..184206a --- /dev/null +++ b/error.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="64" height="64"> + <circle cx="32" cy="32" r="25" stroke="red" stroke-width="7" fill="black" fill-opacity="0.2"/> + <rect x="28" y="7" width="8" height="50" fill="red" transform="rotate(45, 32, 32)"/> +</svg> diff --git a/foto/nginx.conf b/foto/nginx.conf deleted file mode 100644 index f6dbc71..0000000 --- a/foto/nginx.conf +++ /dev/null @@ -1,4 +0,0 @@ - - location /protected { - rewrite /protected/([a-zA-Z]+)/([a-zA-Z0-9]+)/?.* /protected.php?type=$1&id=$2 last; - } diff --git a/foto/protected.php b/foto/protected.php deleted file mode 100644 index c70772d..0000000 --- a/foto/protected.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -lredirect("index"); - -if ( ! isset($_GET["type"]) || ! isset($_GET["id"]) ) - exit; - -switch($_GET["type"]){ - case("image"): - $sql = $db->prepare("SELECT name, mime, size, hash FROM " . DBPREFIX . "image WHERE id = %s;", $_GET["id"]); - $result = $db->doQuery($sql); - $f = $result->fetch_array(MYSQLI_ASSOC); - if ( ! file_exists(IMAGE_PATH . $f["hash"] . ".gz") ){ - header($_SERVER["HTTP_PROTOCOL"] . " 404 Not Found"); - } else { - header("Content-Type: " . $f["mime"]); - header("Content-Disposition: inline; filename=".$f["name"]); - header("Content-Length: " . $f["size"]); - - readgzfile(IMAGE_PATH . $f["hash"] . ".gz"); - } - break; - default: - header($_SERVER["HTTP_PROTOCOL"] . " 404 Not Found"); -} diff --git a/foto/upload.php b/foto/upload.php deleted file mode 100644 index e8d1549..0000000 --- a/foto/upload.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -if ( ! isset($_FILES["images"]) || $_SERVER["REQUEST_METHOD"] != "POST" ){ - exit; -} -lredirect("gallery"); - -if ( ! isset($_POST["gallery"]) || ! preg_match("/[0-9]+/", $_POST["gallery"]) ) - exit; - -//$extension = array("jpeg", "jpg", "png", "gif"); -$extension = array("jpeg", "jpg", "png", "gif", "webm", "mp4", "avi", "mkv"); -$count = 0; -$message = array(); -define("IMAGE_MAXSIZE", "2000"); -define("IMAGE_PATH", ABSPATH . "/../images/"); - -foreach($_FILES["images"]["tmp_name"] as $f => $tmp_name ){ - if ( $_FILES["images"]["error"][$f] == 4 ) - // no file was uploaded - continue; - - if ( $_FILES["images"]["error"][$f] != 0 ){ - continue; - } - if ( $_FILES["images"]["size"][$f] > IMAGE_MAXSIZE ){ - $message[$count] = $_FILES["images"]["name"][$f] . " is too large!"; - $count++; - continue; - } elseif ( ! in_array( pathinfo($_FILES["images"]["name"][$f], PATHINFO_EXTENSION), $extension ) ){ - $message[$count] = $_FILES["images"]["name"][$f] . " - Extension not allowed!"; - $count++; - continue; - } - $hash = hash_file("md5", $tmp_name); - - $sql = $db->prepare("INSERT INTO " . DBPREFIX . "image (id, gallery, name, desc, owner, mime, size, hash, time) VALUES (NULL, %s, %s, %s, %d, %s, %d, %s, %d);", $_POST["gallery"], $_FILES["images"]["name"][$f], "", $_SESSION["userid"], $_FILES["images"]["mime"][$f], $_FILES["images"]["size"][$f], $hash, time()); - - if ( ! file_exists(IMAGE_PATH . $hash . ".gz") ){ - move_uploaded_file($tmp_name, IMAGE_PATH . $hash); - - $gzfile = IMAGE_PATH . $hash . ".gz"; - $fp = gzopen($gzfile, "w9"); - - if ( ! gzwrite($fp, file_get_contents(IMAGE_PATH . $hash)) ) - exit; - - if ( ! gzclose($fp) ) - exit; - - if ( ! unlink(IMAGE_PATH . $hash) ) - exit; - } - - if ( ! $db->doQuery($sql) ) - exit; -} diff --git a/functions.php b/functions.php index 9f5ff49..31eeb94 100644 --- a/functions.php +++ b/functions.php @@ -24,7 +24,7 @@ function failure($reason, $httpcode, $ajax = true, $heading = NULL){ exit; } - // TODO: Put pretty HTML here, please + // TODO: Put pretty HTML here, please --deprecated? # print full error page if($heading != NULL) @@ -111,8 +111,8 @@ if( isset($_GET["goto"]) && $_GET["goto"] != "" ) { } function print_logout(){ - global $cache; - $cache = false; + global $c; + $c->bypassCache = true; global $user; if ( $user->isLoggedIn() ){ $user->logout(); @@ -348,8 +348,8 @@ function _add_entry(){ function print_404(){ header($_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found'); - global $cache; - $cache = false; + global $c; + $c->bypassCache=true; ?> <!--h1 style="color:red;font-size:3.0em;">404 - Not Found</h1--> <h1>Error 404 - Not Found</h1> @@ -368,7 +368,7 @@ function print_404(){ </div> <br> <p>Wir haben die Seite <strong>'<?php echo htmlentities($_SERVER['REQUEST_URI']); ?>'</strong> nicht gefunden!</p> - <a href="javascript:history.go(-1)" title="Index">Geh eins zurück!</a> + <a href="javascript:history.go(-1)" title="Index"><span class="fa fa-hand-o-left"></span> Geh eins zurück!</a> </div> <?php } @@ -476,8 +476,8 @@ function print_register($option = false){ } function print_account($option = false){ - global $cache; - $cache = false; + global $c; + $c->bypassCache = true; lredirect("account"); global $user; ?> @@ -619,8 +619,8 @@ function print_recover($option = false){ } function print_download(){ - global $cache; - $cache = false; + global $c; + $c->bypassCache = true; if ( ! isset($_GET["type"]) || $_GET["type"] == "plain" ) $type = "plain"; else @@ -641,12 +641,388 @@ function print_download(){ <?php } +function show_gallery(){ + if ( isset($_GET["gallery"]) && ! is_null($_GET["gallery"]) && $_GET["gallery"] != "" ) + $_SESSION["gallery"] = $_GET["gallery"]; + else + $_SESSION["gallery"] = 0; + lredirect("gallery;gallery=".$_SESSION["gallery"]); + + global $c; + global $db; + $sql = $db->prepare("SELECT name, description, owner, time FROM " . DBPREFIX . "gallery WHERE id = %d ;", $_GET["gallery"]); + $res = $db->doQuery($sql); + require 'static/modal-new-gallery.html'; + if ( $res->num_rows <= 0 ) { + // Start 404 + $c->bypassCache=true; + +?> + <h1>Keine Galerie gefunden!</h1> + <hr width="50%"> + <h4>Vielleicht wäre es angebracht eine neue Galerie zu erstellen?</h4> + <br> + <button class="btn btn-primary " data-toggle="modal" data-target="#modal-new-gallery" data-loading-text="Lade..."> + <span class="fa fa-folder-open"></span> Erstelle eine Neue! + </button> + </div> + +<?php + // End 404 + } else { + // Start non-404 + + global $moar; + $moar->addHeader( "<style>".file_get_contents('static/gallery.min.css')."</style>" ); + $moar->addFooter('<script src="/js/gallery.min.js" defer></script>'); + + if ( isset($_GET["edit"]) ){ + $moar->addFooter('<script>$("#modal-edit-gallery").modal("show");</script>'); + } + if ( isset($_GET["new"]) ){ + $moar->addFooter('<script>$("#modal-new-gallery").modal("show");</script>'); + } + + if ( $c->exists2( CACHEPREFIX . "gallery_headline_" . $_SESSION["gallery"] ) ){ + echo $c->get2( CACHEPREFIX . "gallery_headline_" . $_SESSION["gallery"] ); + } else { + ob_start(); + $row = $res->fetch_array(MYSQLI_ASSOC); + $owner = $db->doQuery("SELECT name FROM " . DBPREFIX . "user WHERE id = " . $row["owner"] . ";"); + $owner = $owner->fetch_array(MYSQLI_NUM); + $owner = $owner[0]; + + require 'static/modal-edit-gallery.php'; + require 'static/modal-delete-gallery.php'; + +?> + <ul class="list-inline"> + <li><h1><span class="fa fa-camera-retro"></span> <?php echo htmlentities($row["name"]); ?> <span class="desc">|</span> </h1></li> + <li><h5 class="desc">erstellt von <?php echo htmlentities($owner . " am " . date("j.n.Y", $row["time"])); ?></h5></li> + </ul> + <h5><?php echo htmlentities($row["description"]); ?></h5> +<?php + $c->set2( CACHEPREFIX . "gallery_headline_" . $_SESSION["gallery"], ob_get_contents() ); + ob_end_flush(); + } +?> + </div> + </div> + <div class="row"> + <!-- Tab Navigation! --> + <ul class="nav nav-tabs" role="tablist"> +<?php +# determines active class for tab naviagation + if ( ! isset($_GET["mode"]) || $_GET["mode"] == "" ) + $_GET["mode"] = "show"; + + $active = array('show' => 'Galerie', 'upload' => 'Hochladen'); + foreach($active as $tab => $msg){ + if ( $tab == "show" ) { + $span = '<span class="fa fa-picture-o"></span> '; + } elseif ( $tab == "upload") { + $span = '<span class="fa fa-upload"></span> '; + } else { + $span=""; + } + + if ( $tab == $_GET["mode"] ) + echo '<li class="active"><a href="/?page=gallery&gallery='.htmlentities($_GET["gallery"]).'&mode='.$tab.'" role="tab">'.$span.$msg.'</a></li>'; + else + echo '<li><a href="/?page=gallery&gallery='.htmlentities($_GET["gallery"]).'&mode='.$tab.'" role="tab">'.$span.$msg.'</a></li>'; + } +?> + <li><a href="#change" role="tab" onclick="$('#modal-edit-gallery').modal('show');"><span class="glyphicon glyphicon-cog"></span> Ändern</a></li> + <li><a href="#new" role="tab" onclick="$('#modal-new-gallery').modal('show')"><span class="fa fa-plus"></span> Neu</a></li> + <li><a href="#delete" role="tab" onclick="$('#modal-delete-gallery').modal('show')"><span class="glyphicon glyphicon-trash"></span> Löschen</a></li> + </ul> + <div class="tab-content"> +<?php + if ( $_GET["mode"] == "show" ){ +?> + <!-- Start Tab 'Gallery' --> + <div class="tab-pane active effect" id="galerie"> + +<div id="blueimp-gallery" class="blueimp-gallery" data-use-bootstrap-modal="false"> + <!-- The container for the modal slides --> + <div class="slides"></div> + <!-- Controls for the borderless lightbox --> + <h3 class="title"></h3> + <a class="prev">‹</a> + <a class="next">›</a> + <a class="close">×</a> + <a class="play-pause"></a> + <ol class="indicator"></ol> + <!-- The modal dialog, which will be used to wrap the lightbox content --> + <div class="modal fade"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" aria-hidden="true">×</button> + <h4 class="modal-title"></h4> + </div> + <div class="modal-body next"></div> + <div class="modal-footer"> + <button type="button" class="btn btn-default pull-left prev"> + <i class="glyphicon glyphicon-chevron-left"></i> + Previous + </button> + <button type="button" class="btn btn-primary next"> + Next + <i class="glyphicon glyphicon-chevron-right"></i> + </button> + </div> + </div> + </div> + </div> +</div> +<?php + if ( $c->exists( CACHEPREFIX . "gallery_imagelinks_" . $_SESSION["gallery"] ) ){ + echo $c->get2( CACHEPREFIX . "gallery_imagelinks_" . $_SESSION["gallery"] ); + } else { + ob_start(); + $images = array_diff( scandir(IMAGE_PATH . $_SESSION["gallery"] . '/thumbnail' ), array('..', '.') ); + if ( ! is_null($images) ){ + echo '<div id="links">'; + foreach($images as $image){ + echo '<a href="'.IMAGE_URL.'?file='.$image.'&download=1" title="'.$image.'" data-gallery> + <img src="'.IMAGE_URL.'?file='.$image.'&thumb=1" alt="'.$image.'"> + </a>'; + } + echo "</div>"; + } else { + echo "<h4>Keine Bilder in der aktuellen Gallerie vorhanden!</h4>"; + } + $c->set2( CACHEPREFIX . "gallery_imagelinks_" . $_SESSION["gallery"], ob_get_contents() ); + ob_end_flush(); + } +?> + <!-- End Tab 'Galerie' --> + </div> +<?php + } elseif ( $_GET["mode"] == "upload" ){ + $moar->addFooter('<script src="/js/upload.min.js" defer></script>'); +?> + <!-- Start Tab 'Upload' --> + <div class="tab-pane active effect" id="upload"> + <!-- The file upload form used as target for the file upload widget --> + <form id="fileupload" action="/images/" method="POST" enctype="multipart/form-data"> + <!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload --> + <div class="row fileupload-buttonbar"> + <div class="col-lg-7"> + <!-- The fileinput-button span is used to style the file input field as button --> + <span class="btn btn-success fileinput-button"> + <i class="glyphicon glyphicon-plus"></i> + <span>Add files...</span> + <input type="file" name="files[]" multiple> + </span> + <button type="submit" class="btn btn-primary start"> + <i class="glyphicon glyphicon-upload"></i> + <span>Start upload</span> + </button> + <button type="reset" class="btn btn-warning cancel"> + <i class="glyphicon glyphicon-ban-circle"></i> + <span>Cancel upload</span> + </button> + <button type="button" class="btn btn-danger delete"> + <i class="glyphicon glyphicon-trash"></i> + <span>Delete</span> + </button> + <input type="checkbox" class="toggle"> + <!-- The global file processing state --> + <span class="fileupload-process"></span> + </div> + <!-- The global progress state --> + <div class="col-lg-5 fileupload-progress fade"> + <!-- The global progress bar --> + <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100"> + <div class="progress-bar progress-bar-success" style="width:0%;"></div> + </div> + <!-- The extended global progress state --> + <div class="progress-extended"> </div> + </div> + </div> + <!-- The table listing the files available for upload/download --> + <table role="presentation" class="table table-striped"><tbody class="files"></tbody></table> + </form> + <!-- The blueimp Gallery widget --> + <div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even"> + <div class="slides"></div> + <h3 class="title"></h3> + <a class="prev">‹</a> + <a class="next">›</a> + <a class="close">×</a> + <a class="play-pause"></a> + <ol class="indicator"></ol> + </div> + <!-- End Tab 'Upload' --> + </div> +<!-- The template to display files available for upload --> +<script id="template-upload" type="text/x-tmpl"> +{% for (var i=0, file; file=o.files[i]; i++) { %} + <tr class="template-upload fade"> + <td> + <span class="preview"></span> + </td> + <td> + <p class="name">{%=file.name%}</p> + <strong class="error text-danger"></strong> + </td> + <td> + <p class="size">Processing...</p> + <div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="progress-bar progress-bar-success" style="width:0%;"></div></div> + </td> + <td> + {% if (!i && !o.options.autoUpload) { %} + <button class="btn btn-primary start" disabled> + <i class="glyphicon glyphicon-upload"></i> + <span>Start</span> + </button> + {% } %} + {% if (!i) { %} + <button class="btn btn-warning cancel"> + <i class="glyphicon glyphicon-ban-circle"></i> + <span>Cancel</span> + </button> + {% } %} + </td> + </tr> +{% } %} +</script> +<!-- The template to display files available for download --> +<script id="template-download" type="text/x-tmpl"> +{% for (var i=0, file; file=o.files[i]; i++) { %} + <tr class="template-download fade"> + <td> + <span class="preview"> + {% if (file.thumbnailUrl) { %} + <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a> + {% } %} + </span> + </td> + <td> + <p class="name"> + {% if (file.url) { %} + <a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a> + {% } else { %} + <span>{%=file.name%}</span> + {% } %} + </p> + {% if (file.error) { %} + <div><span class="label label-danger">Error</span> {%=file.error%}</div> + {% } %} + </td> + <td> + <span class="size">{%=o.formatFileSize(file.size)%}</span> + </td> + <td> + {% if (file.deleteUrl) { %} + <button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}> + <i class="glyphicon glyphicon-trash"></i> + <span>Delete</span> + </button> + <input type="checkbox" name="delete" value="1" class="toggle"> + {% } else { %} + <button class="btn btn-warning cancel"> + <i class="glyphicon glyphicon-ban-circle"></i> + <span>Cancel</span> + </button> + {% } %} + </td> + </tr> +{% } %} +</script> + +<?php + } else { + $c->bypassCache = true; + } +?> + <!-- End Tab Content --> + </div> + +<?php +// End non-404 + } +?> +<?php +} + +function list_gallery(){ + lredirect("foto"); + require 'static/modal-new-gallery.html'; +?> + <h1>Liste aller Galerien</h1> + <hr width="%0%"> + <!-- End Text-Center--> + </div> +</div> + <div class="row"> +<?php + global $c; + if ( $c->exists2( CACHEPREFIX . 'list_all_gallery' ) ){ + echo $c->get2( CACHEPREFIX . 'list_all_gallery' ); + } else { + global $db; + $res = $db->doQuery("SELECT * FROM " . DBPREFIX . "gallery;"); + $numb = $db->affectedRows(); + + $class = array('fa fa-camera', 'fa fa-camera-retro', 'fa fa-picture-o'); + ob_start(); + while ( $row = $res->fetch_array(MYSQLI_ASSOC) ){ + + $res_n = $db->doQuery("SELECT name FROM " . DBPREFIX . "user WHERE id = " . $row["owner"] . ";"); + $name = $res_n->fetch_array(MYSQLI_ASSOC); + $name = $name["name"]; + $span = '<span class="'.$class[ mt_rand(0, count($class)-1 ) ].' fa-2x a-black"></span> '; + +?> + <ul class="list-unstyled effect"> + <li> + <ul class="list-inline "> + <li> + <h2><a href="/?page=gallery&gallery=<?php echo $row["id"]; ?>&mode=show" class="a-restore"><?php echo $span . htmlentities($row["name"]);?></a></h2> + </li> + <li> + <h5 class="desc">Erstellt von <u><?php echo htmlentities($name); ?></u> am <?php echo date("j.n.Y", $row["time"]); ?>.</h5> + </li> + <li> + <a href="/?page=gallery&gallery=<?php echo $row["id"]; ?>&edit=1" class="desc"><span class="glyphicon glyphicon-link font-small"></span>edit</a> + </li> + </ul> + </li> + <li> + <h5 class="des"><?php echo htmlentities($row["description"]); ?></h5> + </li> + <li> + <hr width="20%"> + </li> + </ul> +<?php + } +?> + + <div class="text-center"> +<?php + echo "<h3>$numb Ergebnisse gefunden</h3>"; +?> + <hr width="50%"> + <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#modal-new-gallery" data-loading-text="Lade..."> + <span class="fa fa-folder-open"></span> Neue Galerie + </button> + + </div> +<?php + $c->set2( CACHEPREFIX . 'list_all_gallery', ob_get_contents() ); + ob_end_flush(); + } +} + function flush_cache(){ lredirect("cache"); global $c; - $c->flush(); - global $cache; - $cache = false; + $c->flushAll(); + $c->bypassCache = true; ?> <h1>Cache flushed!</h1> </div> @@ -670,3 +1046,20 @@ function minify($buffer){ return $buffer; } + +# remove recursive all directories and files +function rrmdir($dir) { + if (is_dir($dir)) { + $objects = scandir($dir); + foreach ($objects as $object) { + if ($object != "." && $object != "..") { + if (filetype($dir."/".$object) == "dir") + rrmdir($dir."/".$object); + else + unlink($dir."/".$object); + } + } + reset($objects); + rmdir($dir); + } +} diff --git a/images/UploadHandler.php b/images/UploadHandler.php new file mode 100755 index 0000000..261101a --- /dev/null +++ b/images/UploadHandler.php @@ -0,0 +1,1351 @@ +<?php +/* + * jQuery File Upload Plugin PHP Class 8.1.0 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +class UploadHandler +{ + + protected $options; + + // PHP File Upload error message codes: + // http://php.net/manual/en/features.file-upload.errors.php + protected $error_messages = array( + 1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini', + 2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form', + 3 => 'The uploaded file was only partially uploaded', + 4 => 'No file was uploaded', + 6 => 'Missing a temporary folder', + 7 => 'Failed to write file to disk', + 8 => 'A PHP extension stopped the file upload', + 'post_max_size' => 'The uploaded file exceeds the post_max_size directive in php.ini', + 'max_file_size' => 'File is too big', + 'min_file_size' => 'File is too small', + 'accept_file_types' => 'Filetype not allowed', + 'max_number_of_files' => 'Maximum number of files exceeded', + 'max_width' => 'Image exceeds maximum width', + 'min_width' => 'Image requires a minimum width', + 'max_height' => 'Image exceeds maximum height', + 'min_height' => 'Image requires a minimum height', + 'abort' => 'File upload aborted', + 'image_resize' => 'Failed to resize image' + ); + + protected $image_objects = array(); + + function __construct($options = null, $initialize = true, $error_messages = null) { + $this->options = array( + 'script_url' => $this->get_full_url(). '/', + 'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/../protected/'.$_SESSION["gallery"].'/', + //'upload_dir' => '/tmp/images/' . $_SESSION["gallery"] . '/', + //'upload_url' => $this->get_full_url().'/files/', + //'upload_url' => $this->get_full_url().$_SESSION["gallery"] . '/images/', + //'upload_url' => '/images/', + 'upload_url' => '/protected/'.$_SESSION["gallery"].'/', + 'user_dirs' => false, + 'mkdir_mode' => 0755, + 'param_name' => 'files', + // Set the following option to 'POST', if your server does not support + // DELETE requests. This is a parameter sent to the client: + //'delete_type' => 'DELETE', + 'delete_type' => 'POST', + 'access_control_allow_origin' => '*', + 'access_control_allow_credentials' => false, + 'access_control_allow_methods' => array( + 'OPTIONS', + 'HEAD', + 'GET', + 'POST', + 'PUT', + 'PATCH', + 'DELETE' + ), + 'access_control_allow_headers' => array( + 'Content-Type', + 'Content-Range', + 'Content-Disposition' + ), + // Enable to provide file downloads via GET requests to the PHP script: + // 1. Set to 1 to download files via readfile method through PHP + // 2. Set to 2 to send a X-Sendfile header for lighttpd/Apache + // 3. Set to 3 to send a X-Accel-Redirect header for nginx + // If set to 2 or 3, adjust the upload_url option to the base path of + // the redirect parameter, e.g. '/files/'. + //'download_via_php' => false, + 'download_via_php' => 3, + // Read files in chunks to avoid memory limits when download_via_php + // is enabled, set to 0 to disable chunked reading of files: + 'readfile_chunk_size' => 10 * 1024 * 1024, // 10 MiB + // Defines which files can be displayed inline when downloaded: + 'inline_file_types' => '/\.(gif|jpe?g|png)$/i', + // Defines which files (based on their names) are accepted for upload: + 'accept_file_types' => '/.+$/i', + // The php.ini settings upload_max_filesize and post_max_size + // take precedence over the following max_file_size setting: + 'max_file_size' => null, + 'min_file_size' => 1, + // The maximum number of files for the upload directory: + 'max_number_of_files' => null, + // Defines which files are handled as image files: + 'image_file_types' => '/\.(gif|jpe?g|png)$/i', + // Use exif_imagetype on all files to correct file extensions: + 'correct_image_extensions' => false, + // Image resolution restrictions: + 'max_width' => null, + 'max_height' => null, + 'min_width' => 1, + 'min_height' => 1, + // Set the following option to false to enable resumable uploads: + 'discard_aborted_uploads' => true, + // Set to 0 to use the GD library to scale and orient images, + // set to 1 to use imagick (if installed, falls back to GD), + // set to 2 to use the ImageMagick convert binary directly: + 'image_library' => 1, + // Uncomment the following to define an array of resource limits + // for imagick: + /* + 'imagick_resource_limits' => array( + imagick::RESOURCETYPE_MAP => 32, + imagick::RESOURCETYPE_MEMORY => 32 + ), + */ + // Command or path for to the ImageMagick convert binary: + 'convert_bin' => 'convert', + // Uncomment the following to add parameters in front of each + // ImageMagick convert call (the limit constraints seem only + // to have an effect if put in front): + /* + 'convert_params' => '-limit memory 32MiB -limit map 32MiB', + */ + // Command or path for to the ImageMagick identify binary: + 'identify_bin' => 'identify', + 'image_versions' => array( + // The empty image version key defines options for the original image: + '' => array( + // Automatically rotate images based on EXIF meta data: + 'auto_orient' => true + ), + // Uncomment the following to create medium sized images: + /* + 'medium' => array( + 'max_width' => 800, + 'max_height' => 600 + ), + */ + 'thumbnail' => array( + // Uncomment the following to use a defined directory for the thumbnails + // instead of a subdirectory based on the version identifier. + // Make sure that this directory doesn't allow execution of files if you + // don't pose any restrictions on the type of uploaded files, e.g. by + // copying the .htaccess file from the files directory for Apache: + //'upload_dir' => dirname($this->get_server_var('SCRIPT_FILENAME')).'/thumb/', + //'upload_dir' => '/tmp/images/'.$_REQUEST["gallery"].'/thumbnails', + //'upload_url' => $this->get_full_url().'/thumb/', + // Uncomment the following to force the max + // dimensions and e.g. create square thumbnails: + //'crop' => true, + 'max_width' => 80, + 'max_height' => 80 + ) + ) + ); + if ($options) { + $this->options = $options + $this->options; + } + if ($error_messages) { + $this->error_messages = $error_messages + $this->error_messages; + } + if ($initialize) { + $this->initialize(); + } + } + + protected function initialize() { + switch ($this->get_server_var('REQUEST_METHOD')) { + case 'OPTIONS': + case 'HEAD': + $this->head(); + break; + case 'GET': + $this->get(); + break; + case 'PATCH': + case 'PUT': + case 'POST': + $this->post(); + break; + case 'DELETE': + $this->delete(); + break; + default: + $this->header('HTTP/1.1 405 Method Not Allowed'); + } + } + + protected function get_full_url() { + $https = !empty($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'], 'on') === 0 || + !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && + strcasecmp($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') === 0; + return + ($https ? 'https://' : 'http://'). + (!empty($_SERVER['REMOTE_USER']) ? $_SERVER['REMOTE_USER'].'@' : ''). + (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : ($_SERVER['SERVER_NAME']. + ($https && $_SERVER['SERVER_PORT'] === 443 || + $_SERVER['SERVER_PORT'] === 80 ? '' : ':'.$_SERVER['SERVER_PORT']))). + substr($_SERVER['SCRIPT_NAME'],0, strrpos($_SERVER['SCRIPT_NAME'], '/')) + ; + } + + protected function get_user_id() { + @session_start(); + return session_id(); + } + + protected function get_user_path() { + if ($this->options['user_dirs']) { + return $this->get_user_id().'/'; + } + return ''; + } + + protected function get_upload_path($file_name = null, $version = null) { + $file_name = $file_name ? $file_name : ''; + if (empty($version)) { + $version_path = ''; + } else { + $version_dir = @$this->options['image_versions'][$version]['upload_dir']; + if ($version_dir) { + return $version_dir.$this->get_user_path().$file_name; + } + $version_path = $version.'/'; + } + return $this->options['upload_dir'].$this->get_user_path() + .$version_path.$file_name; + } + + protected function get_query_separator($url) { + return strpos($url, '?') === false ? '?' : '&'; + } + + protected function get_download_url($file_name, $version = null, $direct = false) { + if (!$direct && $this->options['download_via_php']) { + $url = $this->options['script_url'] + .$this->get_query_separator($this->options['script_url']) + .$this->get_singular_param_name() + .'='.rawurlencode($file_name); + if ($version) { + $url .= '&version='.rawurlencode($version); + } + return $url.'&download=1'; + } + if (empty($version)) { + $version_path = ''; + } else { + $version_url = @$this->options['image_versions'][$version]['upload_url']; + if ($version_url) { + return $version_url.$this->get_user_path().rawurlencode($file_name); + } + $version_path = rawurlencode($version).'/'; + } + return $this->options['upload_url'].$this->get_user_path() + .$version_path.rawurlencode($file_name); + } + + protected function set_additional_file_properties($file) { + $file->deleteUrl = $this->options['script_url'] + .$this->get_query_separator($this->options['script_url']) + .$this->get_singular_param_name() + .'='.rawurlencode($file->name); + $file->deleteType = $this->options['delete_type']; + if ($file->deleteType !== 'DELETE') { + $file->deleteUrl .= '&_method=DELETE'; + } + if ($this->options['access_control_allow_credentials']) { + $file->deleteWithCredentials = true; + } + } + + // Fix for overflowing signed 32 bit integers, + // works for sizes up to 2^32-1 bytes (4 GiB - 1): + protected function fix_integer_overflow($size) { + if ($size < 0) { + $size += 2.0 * (PHP_INT_MAX + 1); + } + return $size; + } + + protected function get_file_size($file_path, $clear_stat_cache = false) { + if ($clear_stat_cache) { + if (version_compare(PHP_VERSION, '5.3.0') >= 0) { + clearstatcache(true, $file_path); + } else { + clearstatcache(); + } + } + return $this->fix_integer_overflow(filesize($file_path)); + } + + protected function is_valid_file_object($file_name) { + $file_path = $this->get_upload_path($file_name); + if (is_file($file_path) && $file_name[0] !== '.') { + return true; + } + return false; + } + + protected function get_file_object($file_name) { + if ($this->is_valid_file_object($file_name)) { + $file = new \stdClass(); + $file->name = $file_name; + $file->size = $this->get_file_size( + $this->get_upload_path($file_name) + ); + $file->url = $this->get_download_url($file->name); + foreach($this->options['image_versions'] as $version => $options) { + if (!empty($version)) { + if (is_file($this->get_upload_path($file_name, $version))) { + $file->{$version.'Url'} = $this->get_download_url( + $file->name, + $version + ); + } + } + } + $this->set_additional_file_properties($file); + return $file; + } + return null; + } + + protected function get_file_objects($iteration_method = 'get_file_object') { + $upload_dir = $this->get_upload_path(); + if (!is_dir($upload_dir)) { + return array(); + } + return array_values(array_filter(array_map( + array($this, $iteration_method), + scandir($upload_dir) + ))); + } + + protected function count_file_objects() { + return count($this->get_file_objects('is_valid_file_object')); + } + + protected function get_error_message($error) { + return array_key_exists($error, $this->error_messages) ? + $this->error_messages[$error] : $error; + } + + function get_config_bytes($val) { + $val = trim($val); + $last = strtolower($val[strlen($val)-1]); + switch($last) { + case 'g': + $val *= 1024; + case 'm': + $val *= 1024; + case 'k': + $val *= 1024; + } + return $this->fix_integer_overflow($val); + } + + protected function validate($uploaded_file, $file, $error, $index) { + if ($error) { + $file->error = $this->get_error_message($error); + return false; + } + $content_length = $this->fix_integer_overflow(intval( + $this->get_server_var('CONTENT_LENGTH') + )); + $post_max_size = $this->get_config_bytes(ini_get('post_max_size')); + if ($post_max_size && ($content_length > $post_max_size)) { + $file->error = $this->get_error_message('post_max_size'); + return false; + } + if (!preg_match($this->options['accept_file_types'], $file->name)) { + $file->error = $this->get_error_message('accept_file_types'); + return false; + } + if ($uploaded_file && is_uploaded_file($uploaded_file)) { + $file_size = $this->get_file_size($uploaded_file); + } else { + $file_size = $content_length; + } + if ($this->options['max_file_size'] && ( + $file_size > $this->options['max_file_size'] || + $file->size > $this->options['max_file_size']) + ) { + $file->error = $this->get_error_message('max_file_size'); + return false; + } + if ($this->options['min_file_size'] && + $file_size < $this->options['min_file_size']) { + $file->error = $this->get_error_message('min_file_size'); + return false; + } + if (is_int($this->options['max_number_of_files']) && + ($this->count_file_objects() >= $this->options['max_number_of_files']) && + // Ignore additional chunks of existing files: + !is_file($this->get_upload_path($file->name))) { + $file->error = $this->get_error_message('max_number_of_files'); + return false; + } + $max_width = @$this->options['max_width']; + $max_height = @$this->options['max_height']; + $min_width = @$this->options['min_width']; + $min_height = @$this->options['min_height']; + if (($max_width || $max_height || $min_width || $min_height) + && preg_match($this->options['image_file_types'], $file->name)) { + list($img_width, $img_height) = $this->get_image_size($uploaded_file); + } + if (!empty($img_width)) { + if ($max_width && $img_width > $max_width) { + $file->error = $this->get_error_message('max_width'); + return false; + } + if ($max_height && $img_height > $max_height) { + $file->error = $this->get_error_message('max_height'); + return false; + } + if ($min_width && $img_width < $min_width) { + $file->error = $this->get_error_message('min_width'); + return false; + } + if ($min_height && $img_height < $min_height) { + $file->error = $this->get_error_message('min_height'); + return false; + } + } + return true; + } + + protected function upcount_name_callback($matches) { + $index = isset($matches[1]) ? intval($matches[1]) + 1 : 1; + $ext = isset($matches[2]) ? $matches[2] : ''; + return ' ('.$index.')'.$ext; + } + + protected function upcount_name($name) { + return preg_replace_callback( + '/(?:(?: \(([\d]+)\))?(\.[^.]+))?$/', + array($this, 'upcount_name_callback'), + $name, + 1 + ); + } + + protected function get_unique_filename($file_path, $name, $size, $type, $error, + $index, $content_range) { + while(is_dir($this->get_upload_path($name))) { + $name = $this->upcount_name($name); + } + // Keep an existing filename if this is part of a chunked upload: + $uploaded_bytes = $this->fix_integer_overflow(intval($content_range[1])); + while(is_file($this->get_upload_path($name))) { + if ($uploaded_bytes === $this->get_file_size( + $this->get_upload_path($name))) { + break; + } + $name = $this->upcount_name($name); + } + return $name; + } + + protected function fix_file_extension($file_path, $name, $size, $type, $error, + $index, $content_range) { + // Add missing file extension for known image types: + if (strpos($name, '.') === false && + preg_match('/^image\/(gif|jpe?g|png)/', $type, $matches)) { + $name .= '.'.$matches[1]; + } + if ($this->options['correct_image_extensions'] && + function_exists('exif_imagetype')) { + switch(@exif_imagetype($file_path)){ + case IMAGETYPE_JPEG: + $extensions = array('jpg', 'jpeg'); + break; + case IMAGETYPE_PNG: + $extensions = array('png'); + break; + case IMAGETYPE_GIF: + $extensions = array('gif'); + break; + } + // Adjust incorrect image file extensions: + if (!empty($extensions)) { + $parts = explode('.', $name); + $extIndex = count($parts) - 1; + $ext = strtolower(@$parts[$extIndex]); + if (!in_array($ext, $extensions)) { + $parts[$extIndex] = $extensions[0]; + $name = implode('.', $parts); + } + } + } + return $name; + } + + protected function trim_file_name($file_path, $name, $size, $type, $error, + $index, $content_range) { + // Remove path information and dots around the filename, to prevent uploading + // into different directories or replacing hidden system files. + // Also remove control characters and spaces (\x00..\x20) around the filename: + $name = trim(basename(stripslashes($name)), ".\x00..\x20"); + // Use a timestamp for empty filenames: + if (!$name) { + $name = str_replace('.', '-', microtime(true)); + } + return $name; + } + + protected function get_file_name($file_path, $name, $size, $type, $error, + $index, $content_range) { + $name = $this->trim_file_name($file_path, $name, $size, $type, $error, + $index, $content_range); + return $this->get_unique_filename( + $file_path, + $this->fix_file_extension($file_path, $name, $size, $type, $error, + $index, $content_range), + $size, + $type, + $error, + $index, + $content_range + ); + } + + protected function handle_form_data($file, $index) { + // Handle form data, e.g. $_REQUEST['description'][$index] + } + + protected function get_scaled_image_file_paths($file_name, $version) { + $file_path = $this->get_upload_path($file_name); + if (!empty($version)) { + $version_dir = $this->get_upload_path(null, $version); + if (!is_dir($version_dir)) { + mkdir($version_dir, $this->options['mkdir_mode'], true); + } + $new_file_path = $version_dir.'/'.$file_name; + } else { + $new_file_path = $file_path; + } + return array($file_path, $new_file_path); + } + + protected function gd_get_image_object($file_path, $func, $no_cache = false) { + if (empty($this->image_objects[$file_path]) || $no_cache) { + $this->gd_destroy_image_object($file_path); + $this->image_objects[$file_path] = $func($file_path); + } + return $this->image_objects[$file_path]; + } + + protected function gd_set_image_object($file_path, $image) { + $this->gd_destroy_image_object($file_path); + $this->image_objects[$file_path] = $image; + } + + protected function gd_destroy_image_object($file_path) { + $image = (isset($this->image_objects[$file_path])) ? $this->image_objects[$file_path] : null ; + return $image && imagedestroy($image); + } + + protected function gd_imageflip($image, $mode) { + if (function_exists('imageflip')) { + return imageflip($image, $mode); + } + $new_width = $src_width = imagesx($image); + $new_height = $src_height = imagesy($image); + $new_img = imagecreatetruecolor($new_width, $new_height); + $src_x = 0; + $src_y = 0; + switch ($mode) { + case '1': // flip on the horizontal axis + $src_y = $new_height - 1; + $src_height = -$new_height; + break; + case '2': // flip on the vertical axis + $src_x = $new_width - 1; + $src_width = -$new_width; + break; + case '3': // flip on both axes + $src_y = $new_height - 1; + $src_height = -$new_height; + $src_x = $new_width - 1; + $src_width = -$new_width; + break; + default: + return $image; + } + imagecopyresampled( + $new_img, + $image, + 0, + 0, + $src_x, + $src_y, + $new_width, + $new_height, + $src_width, + $src_height + ); + return $new_img; + } + + protected function gd_orient_image($file_path, $src_img) { + if (!function_exists('exif_read_data')) { + return false; + } + $exif = @exif_read_data($file_path); + if ($exif === false) { + return false; + } + $orientation = intval(@$exif['Orientation']); + if ($orientation < 2 || $orientation > 8) { + return false; + } + switch ($orientation) { + case 2: + $new_img = $this->gd_imageflip( + $src_img, + defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2 + ); + break; + case 3: + $new_img = imagerotate($src_img, 180, 0); + break; + case 4: + $new_img = $this->gd_imageflip( + $src_img, + defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1 + ); + break; + case 5: + $tmp_img = $this->gd_imageflip( + $src_img, + defined('IMG_FLIP_HORIZONTAL') ? IMG_FLIP_HORIZONTAL : 1 + ); + $new_img = imagerotate($tmp_img, 270, 0); + imagedestroy($tmp_img); + break; + case 6: + $new_img = imagerotate($src_img, 270, 0); + break; + case 7: + $tmp_img = $this->gd_imageflip( + $src_img, + defined('IMG_FLIP_VERTICAL') ? IMG_FLIP_VERTICAL : 2 + ); + $new_img = imagerotate($tmp_img, 270, 0); + imagedestroy($tmp_img); + break; + case 8: + $new_img = imagerotate($src_img, 90, 0); + break; + default: + return false; + } + $this->gd_set_image_object($file_path, $new_img); + return true; + } + + protected function gd_create_scaled_image($file_name, $version, $options) { + if (!function_exists('imagecreatetruecolor')) { + error_log('Function not found: imagecreatetruecolor'); + return false; + } + list($file_path, $new_file_path) = + $this->get_scaled_image_file_paths($file_name, $version); + $type = strtolower(substr(strrchr($file_name, '.'), 1)); + switch ($type) { + case 'jpg': + case 'jpeg': + $src_func = 'imagecreatefromjpeg'; + $write_func = 'imagejpeg'; + $image_quality = isset($options['jpeg_quality']) ? + $options['jpeg_quality'] : 75; + break; + case 'gif': + $src_func = 'imagecreatefromgif'; + $write_func = 'imagegif'; + $image_quality = null; + break; + case 'png': + $src_func = 'imagecreatefrompng'; + $write_func = 'imagepng'; + $image_quality = isset($options['png_quality']) ? + $options['png_quality'] : 9; + break; + default: + return false; + } + $src_img = $this->gd_get_image_object( + $file_path, + $src_func, + !empty($options['no_cache']) + ); + $image_oriented = false; + if (!empty($options['auto_orient']) && $this->gd_orient_image( + $file_path, + $src_img + )) { + $image_oriented = true; + $src_img = $this->gd_get_image_object( + $file_path, + $src_func + ); + } + $max_width = $img_width = imagesx($src_img); + $max_height = $img_height = imagesy($src_img); + if (!empty($options['max_width'])) { + $max_width = $options['max_width']; + } + if (!empty($options['max_height'])) { + $max_height = $options['max_height']; + } + $scale = min( + $max_width / $img_width, + $max_height / $img_height + ); + if ($scale >= 1) { + if ($image_oriented) { + return $write_func($src_img, $new_file_path, $image_quality); + } + if ($file_path !== $new_file_path) { + return copy($file_path, $new_file_path); + } + return true; + } + if (empty($options['crop'])) { + $new_width = $img_width * $scale; + $new_height = $img_height * $scale; + $dst_x = 0; + $dst_y = 0; + $new_img = imagecreatetruecolor($new_width, $new_height); + } else { + if (($img_width / $img_height) >= ($max_width / $max_height)) { + $new_width = $img_width / ($img_height / $max_height); + $new_height = $max_height; + } else { + $new_width = $max_width; + $new_height = $img_height / ($img_width / $max_width); + } + $dst_x = 0 - ($new_width - $max_width) / 2; + $dst_y = 0 - ($new_height - $max_height) / 2; + $new_img = imagecreatetruecolor($max_width, $max_height); + } + // Handle transparency in GIF and PNG images: + switch ($type) { + case 'gif': + case 'png': + imagecolortransparent($new_img, imagecolorallocate($new_img, 0, 0, 0)); + case 'png': + imagealphablending($new_img, false); + imagesavealpha($new_img, true); + break; + } + $success = imagecopyresampled( + $new_img, + $src_img, + $dst_x, + $dst_y, + 0, + 0, + $new_width, + $new_height, + $img_width, + $img_height + ) && $write_func($new_img, $new_file_path, $image_quality); + $this->gd_set_image_object($file_path, $new_img); + return $success; + } + + protected function imagick_get_image_object($file_path, $no_cache = false) { + if (empty($this->image_objects[$file_path]) || $no_cache) { + $this->imagick_destroy_image_object($file_path); + $image = new \Imagick(); + if (!empty($this->options['imagick_resource_limits'])) { + foreach ($this->options['imagick_resource_limits'] as $type => $limit) { + $image->setResourceLimit($type, $limit); + } + } + $image->readImage($file_path); + $this->image_objects[$file_path] = $image; + } + return $this->image_objects[$file_path]; + } + + protected function imagick_set_image_object($file_path, $image) { + $this->imagick_destroy_image_object($file_path); + $this->image_objects[$file_path] = $image; + } + + protected function imagick_destroy_image_object($file_path) { + $image = (isset($this->image_objects[$file_path])) ? $this->image_objects[$file_path] : null ; + return $image && $image->destroy(); + } + + protected function imagick_orient_image($image) { + $orientation = $image->getImageOrientation(); + $background = new \ImagickPixel('none'); + switch ($orientation) { + case \imagick::ORIENTATION_TOPRIGHT: // 2 + $image->flopImage(); // horizontal flop around y-axis + break; + case \imagick::ORIENTATION_BOTTOMRIGHT: // 3 + $image->rotateImage($background, 180); + break; + case \imagick::ORIENTATION_BOTTOMLEFT: // 4 + $image->flipImage(); // vertical flip around x-axis + break; + case \imagick::ORIENTATION_LEFTTOP: // 5 + $image->flopImage(); // horizontal flop around y-axis + $image->rotateImage($background, 270); + break; + case \imagick::ORIENTATION_RIGHTTOP: // 6 + $image->rotateImage($background, 90); + break; + case \imagick::ORIENTATION_RIGHTBOTTOM: // 7 + $image->flipImage(); // vertical flip around x-axis + $image->rotateImage($background, 270); + break; + case \imagick::ORIENTATION_LEFTBOTTOM: // 8 + $image->rotateImage($background, 270); + break; + default: + return false; + } + $image->setImageOrientation(\imagick::ORIENTATION_TOPLEFT); // 1 + return true; + } + + protected function imagick_create_scaled_image($file_name, $version, $options) { + list($file_path, $new_file_path) = + $this->get_scaled_image_file_paths($file_name, $version); + $image = $this->imagick_get_image_object( + $file_path, + !empty($options['no_cache']) + ); + if ($image->getImageFormat() === 'GIF') { + // Handle animated GIFs: + $images = $image->coalesceImages(); + foreach ($images as $frame) { + $image = $frame; + $this->imagick_set_image_object($file_name, $image); + break; + } + } + $image_oriented = false; + if (!empty($options['auto_orient'])) { + $image_oriented = $this->imagick_orient_image($image); + } + $new_width = $max_width = $img_width = $image->getImageWidth(); + $new_height = $max_height = $img_height = $image->getImageHeight(); + if (!empty($options['max_width'])) { + $new_width = $max_width = $options['max_width']; + } + if (!empty($options['max_height'])) { + $new_height = $max_height = $options['max_height']; + } + if (!($image_oriented || $max_width < $img_width || $max_height < $img_height)) { + if ($file_path !== $new_file_path) { + return copy($file_path, $new_file_path); + } + return true; + } + $crop = !empty($options['crop']); + if ($crop) { + $x = 0; + $y = 0; + if (($img_width / $img_height) >= ($max_width / $max_height)) { + $new_width = 0; // Enables proportional scaling based on max_height + $x = ($img_width / ($img_height / $max_height) - $max_width) / 2; + } else { + $new_height = 0; // Enables proportional scaling based on max_width + $y = ($img_height / ($img_width / $max_width) - $max_height) / 2; + } + } + $success = $image->resizeImage( + $new_width, + $new_height, + isset($options['filter']) ? $options['filter'] : \imagick::FILTER_LANCZOS, + isset($options['blur']) ? $options['blur'] : 1, + $new_width && $new_height // fit image into constraints if not to be cropped + ); + if ($success && $crop) { + $success = $image->cropImage( + $max_width, + $max_height, + $x, + $y + ); + if ($success) { + $success = $image->setImagePage($max_width, $max_height, 0, 0); + } + } + $type = strtolower(substr(strrchr($file_name, '.'), 1)); + switch ($type) { + case 'jpg': + case 'jpeg': + if (!empty($options['jpeg_quality'])) { + $image->setImageCompression(\imagick::COMPRESSION_JPEG); + $image->setImageCompressionQuality($options['jpeg_quality']); + } + break; + } + if (!empty($options['strip'])) { + $image->stripImage(); + } + return $success && $image->writeImage($new_file_path); + } + + protected function imagemagick_create_scaled_image($file_name, $version, $options) { + list($file_path, $new_file_path) = + $this->get_scaled_image_file_paths($file_name, $version); + $resize = @$options['max_width'] + .(empty($options['max_height']) ? '' : 'X'.$options['max_height']); + if (!$resize && empty($options['auto_orient'])) { + if ($file_path !== $new_file_path) { + return copy($file_path, $new_file_path); + } + return true; + } + $cmd = $this->options['convert_bin']; + if (!empty($this->options['convert_params'])) { + $cmd .= ' '.$this->options['convert_params']; + } + $cmd .= ' '.escapeshellarg($file_path); + if (!empty($options['auto_orient'])) { + $cmd .= ' -auto-orient'; + } + if ($resize) { + // Handle animated GIFs: + $cmd .= ' -coalesce'; + if (empty($options['crop'])) { + $cmd .= ' -resize '.escapeshellarg($resize.'>'); + } else { + $cmd .= ' -resize '.escapeshellarg($resize.'^'); + $cmd .= ' -gravity center'; + $cmd .= ' -crop '.escapeshellarg($resize.'+0+0'); + } + // Make sure the page dimensions are correct (fixes offsets of animated GIFs): + $cmd .= ' +repage'; + } + if (!empty($options['convert_params'])) { + $cmd .= ' '.$options['convert_params']; + } + $cmd .= ' '.escapeshellarg($new_file_path); + exec($cmd, $output, $error); + if ($error) { + error_log(implode('\n', $output)); + return false; + } + return true; + } + + protected function get_image_size($file_path) { + if ($this->options['image_library']) { + if (extension_loaded('imagick')) { + $image = new \Imagick(); + try { + if (@$image->pingImage($file_path)) { + $dimensions = array($image->getImageWidth(), $image->getImageHeight()); + $image->destroy(); + return $dimensions; + } + return false; + } catch (Exception $e) { + error_log($e->getMessage()); + } + } + if ($this->options['image_library'] === 2) { + $cmd = $this->options['identify_bin']; + $cmd .= ' -ping '.escapeshellarg($file_path); + exec($cmd, $output, $error); + if (!$error && !empty($output)) { + // image.jpg JPEG 1920x1080 1920x1080+0+0 8-bit sRGB 465KB 0.000u 0:00.000 + $infos = preg_split('/\s+/', $output[0]); + $dimensions = preg_split('/x/', $infos[2]); + return $dimensions; + } + return false; + } + } + if (!function_exists('getimagesize')) { + error_log('Function not found: getimagesize'); + return false; + } + return @getimagesize($file_path); + } + + protected function create_scaled_image($file_name, $version, $options) { + if ($this->options['image_library'] === 2) { + return $this->imagemagick_create_scaled_image($file_name, $version, $options); + } + if ($this->options['image_library'] && extension_loaded('imagick')) { + return $this->imagick_create_scaled_image($file_name, $version, $options); + } + return $this->gd_create_scaled_image($file_name, $version, $options); + } + + protected function destroy_image_object($file_path) { + if ($this->options['image_library'] && extension_loaded('imagick')) { + return $this->imagick_destroy_image_object($file_path); + } + } + + protected function is_valid_image_file($file_path) { + if (!preg_match($this->options['image_file_types'], $file_path)) { + return false; + } + if (function_exists('exif_imagetype')) { + return @exif_imagetype($file_path); + } + $image_info = $this->get_image_size($file_path); + return $image_info && $image_info[0] && $image_info[1]; + } + + protected function handle_image_file($file_path, $file) { + $failed_versions = array(); + foreach($this->options['image_versions'] as $version => $options) { + if ($this->create_scaled_image($file->name, $version, $options)) { + if (!empty($version)) { + $file->{$version.'Url'} = $this->get_download_url( + $file->name, + $version + ); + } else { + $file->size = $this->get_file_size($file_path, true); + } + } else { + $failed_versions[] = $version ? $version : 'original'; + } + } + if (count($failed_versions)) { + $file->error = $this->get_error_message('image_resize') + .' ('.implode($failed_versions,', ').')'; + } + // Free memory: + $this->destroy_image_object($file_path); + } + + protected function handle_file_upload($uploaded_file, $name, $size, $type, $error, + $index = null, $content_range = null) { + $file = new \stdClass(); + $file->name = $this->get_file_name($uploaded_file, $name, $size, $type, $error, + $index, $content_range); + $file->size = $this->fix_integer_overflow(intval($size)); + $file->type = $type; + if ($this->validate($uploaded_file, $file, $error, $index)) { + $this->handle_form_data($file, $index); + $upload_dir = $this->get_upload_path(); + if (!is_dir($upload_dir)) { + mkdir($upload_dir, $this->options['mkdir_mode'], true); + } + $file_path = $this->get_upload_path($file->name); + $append_file = $content_range && is_file($file_path) && + $file->size > $this->get_file_size($file_path); + if ($uploaded_file && is_uploaded_file($uploaded_file)) { + // multipart/formdata uploads (POST method uploads) + if ($append_file) { + file_put_contents( + $file_path, + fopen($uploaded_file, 'r'), + FILE_APPEND + ); + } else { + move_uploaded_file($uploaded_file, $file_path); + } + } else { + // Non-multipart uploads (PUT method support) + file_put_contents( + $file_path, + fopen('php://input', 'r'), + $append_file ? FILE_APPEND : 0 + ); + } + $file_size = $this->get_file_size($file_path, $append_file); + if ($file_size === $file->size) { + $file->url = $this->get_download_url($file->name); + if ($this->is_valid_image_file($file_path)) { + $this->handle_image_file($file_path, $file); + } + } else { + $file->size = $file_size; + if (!$content_range && $this->options['discard_aborted_uploads']) { + unlink($file_path); + $file->error = $this->get_error_message('abort'); + } + } + $this->set_additional_file_properties($file); + } + return $file; + } + + protected function readfile($file_path) { + $file_size = $this->get_file_size($file_path); + $chunk_size = $this->options['readfile_chunk_size']; + if ($chunk_size && $file_size > $chunk_size) { + $handle = fopen($file_path, 'rb'); + while (!feof($handle)) { + echo fread($handle, $chunk_size); + @ob_flush(); + @flush(); + } + fclose($handle); + return $file_size; + } + return readfile($file_path); + } + + protected function body($str) { + echo $str; + } + + protected function header($str) { + header($str); + } + + protected function get_server_var($id) { + return isset($_SERVER[$id]) ? $_SERVER[$id] : ''; + } + + protected function generate_response($content, $print_response = true) { + if ($print_response) { + $json = json_encode($content); + $redirect = isset($_REQUEST['redirect']) ? + stripslashes($_REQUEST['redirect']) : null; + if ($redirect) { + $this->header('Location: '.sprintf($redirect, rawurlencode($json))); + return; + } + $this->head(); + if ($this->get_server_var('HTTP_CONTENT_RANGE')) { + $files = isset($content[$this->options['param_name']]) ? + $content[$this->options['param_name']] : null; + if ($files && is_array($files) && is_object($files[0]) && $files[0]->size) { + $this->header('Range: 0-'.( + $this->fix_integer_overflow(intval($files[0]->size)) - 1 + )); + } + } + $this->body($json); + } + return $content; + } + + protected function get_version_param() { + return isset($_GET['version']) ? basename(stripslashes($_GET['version'])) : null; + } + + protected function get_singular_param_name() { + return substr($this->options['param_name'], 0, -1); + } + + protected function get_file_name_param() { + $name = $this->get_singular_param_name(); + return isset($_REQUEST[$name]) ? basename(stripslashes($_REQUEST[$name])) : null; + } + + protected function get_file_names_params() { + $params = isset($_REQUEST[$this->options['param_name']]) ? + $_REQUEST[$this->options['param_name']] : array(); + foreach ($params as $key => $value) { + $params[$key] = basename(stripslashes($value)); + } + return $params; + } + + protected function get_file_type($file_path) { + switch (strtolower(pathinfo($file_path, PATHINFO_EXTENSION))) { + case 'jpeg': + case 'jpg': + return 'image/jpeg'; + case 'png': + return 'image/png'; + case 'gif': + return 'image/gif'; + default: + return ''; + } + } + + protected function download() { + switch ($this->options['download_via_php']) { + case 1: + $redirect_header = null; + break; + case 2: + $redirect_header = 'X-Sendfile'; + break; + case 3: + $redirect_header = 'X-Accel-Redirect'; + break; + default: + return $this->header('HTTP/1.1 403 Forbidden'); + } + $file_name = $this->get_file_name_param(); + if (!$this->is_valid_file_object($file_name)) { + return $this->header('HTTP/1.1 404 Not Found'); + } + if ($redirect_header) { + return $this->header( + $redirect_header.': '.$this->get_download_url( + $file_name, + $this->get_version_param(), + true + ) + ); + } + $file_path = $this->get_upload_path($file_name, $this->get_version_param()); + // Prevent browsers from MIME-sniffing the content-type: + $this->header('X-Content-Type-Options: nosniff'); + if (!preg_match($this->options['inline_file_types'], $file_name)) { + $this->header('Content-Type: application/octet-stream'); + $this->header('Content-Disposition: attachment; filename="'.$file_name.'"'); + } else { + $this->header('Content-Type: '.$this->get_file_type($file_path)); + $this->header('Content-Disposition: inline; filename="'.$file_name.'"'); + } + $this->header('Content-Length: '.$this->get_file_size($file_path)); + $this->header('Last-Modified: '.gmdate('D, d M Y H:i:s T', filemtime($file_path))); + $this->readfile($file_path); + } + + protected function send_content_type_header() { + $this->header('Vary: Accept'); + if (strpos($this->get_server_var('HTTP_ACCEPT'), 'application/json') !== false) { + $this->header('Content-type: application/json'); + } else { + $this->header('Content-type: text/plain'); + } + } + + protected function send_access_control_headers() { + $this->header('Access-Control-Allow-Origin: '.$this->options['access_control_allow_origin']); + $this->header('Access-Control-Allow-Credentials: ' + .($this->options['access_control_allow_credentials'] ? 'true' : 'false')); + $this->header('Access-Control-Allow-Methods: ' + .implode(', ', $this->options['access_control_allow_methods'])); + $this->header('Access-Control-Allow-Headers: ' + .implode(', ', $this->options['access_control_allow_headers'])); + } + + public function head() { + $this->header('Pragma: no-cache'); + $this->header('Cache-Control: no-store, no-cache, must-revalidate'); + $this->header('Content-Disposition: inline; filename="files.json"'); + // Prevent Internet Explorer from MIME-sniffing the content-type: + $this->header('X-Content-Type-Options: nosniff'); + if ($this->options['access_control_allow_origin']) { + $this->send_access_control_headers(); + } + $this->send_content_type_header(); + } + + public function get($print_response = true) { + if ($print_response && isset($_GET['download'])) { + return $this->download(); + } + $file_name = $this->get_file_name_param(); + if ($file_name) { + $response = array( + $this->get_singular_param_name() => $this->get_file_object($file_name) + ); + } else { + $response = array( + $this->options['param_name'] => $this->get_file_objects() + ); + } + return $this->generate_response($response, $print_response); + } + + public function post($print_response = true) { + if (isset($_REQUEST['_method']) && $_REQUEST['_method'] === 'DELETE') { + return $this->delete($print_response); + } + $upload = isset($_FILES[$this->options['param_name']]) ? + $_FILES[$this->options['param_name']] : null; + // Parse the Content-Disposition header, if available: + $file_name = $this->get_server_var('HTTP_CONTENT_DISPOSITION') ? + rawurldecode(preg_replace( + '/(^[^"]+")|("$)/', + '', + $this->get_server_var('HTTP_CONTENT_DISPOSITION') + )) : null; + // Parse the Content-Range header, which has the following form: + // Content-Range: bytes 0-524287/2000000 + $content_range = $this->get_server_var('HTTP_CONTENT_RANGE') ? + preg_split('/[^0-9]+/', $this->get_server_var('HTTP_CONTENT_RANGE')) : null; + $size = $content_range ? $content_range[3] : null; + $files = array(); + if ($upload && is_array($upload['tmp_name'])) { + // param_name is an array identifier like "files[]", + // $_FILES is a multi-dimensional array: + foreach ($upload['tmp_name'] as $index => $value) { + $files[] = $this->handle_file_upload( + $upload['tmp_name'][$index], + $file_name ? $file_name : $upload['name'][$index], + $size ? $size : $upload['size'][$index], + $upload['type'][$index], + $upload['error'][$index], + $index, + $content_range + ); + } + } else { + // param_name is a single object identifier like "file", + // $_FILES is a one-dimensional array: + $files[] = $this->handle_file_upload( + isset($upload['tmp_name']) ? $upload['tmp_name'] : null, + $file_name ? $file_name : (isset($upload['name']) ? + $upload['name'] : null), + $size ? $size : (isset($upload['size']) ? + $upload['size'] : $this->get_server_var('CONTENT_LENGTH')), + isset($upload['type']) ? + $upload['type'] : $this->get_server_var('CONTENT_TYPE'), + isset($upload['error']) ? $upload['error'] : null, + null, + $content_range + ); + } + return $this->generate_response( + array($this->options['param_name'] => $files), + $print_response + ); + } + + public function delete($print_response = true) { + $file_names = $this->get_file_names_params(); + if (empty($file_names)) { + $file_names = array($this->get_file_name_param()); + } + $response = array(); + foreach($file_names as $file_name) { + $file_path = $this->get_upload_path($file_name); + $success = is_file($file_path) && $file_name[0] !== '.' && unlink($file_path); + if ($success) { + foreach($this->options['image_versions'] as $version => $options) { + if (!empty($version)) { + $file = $this->get_upload_path($file_name, $version); + if (is_file($file)) { + unlink($file); + } + } + } + } + $response[$file_name] = $success; + } + return $this->generate_response($response, $print_response); + } + +} diff --git a/images/index.php b/images/index.php new file mode 100644 index 0000000..b839b69 --- /dev/null +++ b/images/index.php @@ -0,0 +1,47 @@ +<?php +/* + * jQuery File Upload Plugin PHP Example 5.14 + * https://github.com/blueimp/jQuery-File-Upload + * + * Copyright 2010, Sebastian Tschan + * https://blueimp.net + * + * Licensed under the MIT license: + * http://www.opensource.org/licenses/MIT + */ + +error_reporting(E_ALL | E_STRICT); +require "../bootstrap.php"; +session_name(SESSION); +session_start(); +$c = new cache(REDIS_CONNECT, REDIS_DB); +$c->bypassCache = true; +$db = new db(); +if ( ! isset($_SESSION["username"])) + $u = null; +else + $u = $_SESSION["username"]; + +$user = new jg($u); + +if ( ! isset($_SESSION["gallery"]) || is_null($_SESSION["gallery"]) || $_SESSION["gallery"] == "" ){ + $_SESSION["gallery"] = 1; +} + + +if ( isset($_GET["thumb"]) ){ + if( ! isset($_GET["file"]) || $_GET["file"] == "" ){ + header($_SERVER["SERVER_PROTOCOL"] . " 404 Not Found"); + redirect("404"); + exit; + } + + if ( is_file(IMAGE_PATH . $_SESSION["gallery"] . '/thumbnail/' . $_GET["file"]) ){ + header("X-Accel-Redirect: " . '/protected/' . $_SESSION["gallery"] . '/thumbnail/' . $_GET["file"]); + } + +} else { + require('UploadHandler.php'); + $upload_handler = new UploadHandler(); + $c->flush2(); +} @@ -5,9 +5,6 @@ ob_start('minify'); session_name(SESSION); session_start(); -if ( ! isset($cache) ) - $cache = true; - $c = new cache(REDIS_CONNECT, REDIS_DB); if ( isset($_SESSION["loggedin"]) && $_SESSION["loggedin"]){ @@ -16,11 +13,11 @@ if ( isset($_SESSION["loggedin"]) && $_SESSION["loggedin"]){ $a = "0_"; } -if ( $cache && $_SERVER["REQUEST_METHOD"] == "GET" && $_SERVER["REDIRECT_STATUS"] == 200 ) { +if ( ! $c->bypassCache && $_SERVER["REQUEST_METHOD"] == "GET" && $_SERVER["REDIRECT_STATUS"] == 200 ) { $token = $c->getToken($_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]. $_SERVER["QUERY_STRING"], $a); - if ( $c->exists($token)){ + if ( $c->existsPageCache($token)){ header("X-Cache: Hit"); - echo $c->getValue($token); + echo $c->getPageCache($token); ob_end_flush(); exit; } @@ -28,13 +25,16 @@ if ( $cache && $_SERVER["REQUEST_METHOD"] == "GET" && $_SERVER["REDIRECT_STATUS" header("X-Cache: Miss "); } +$moar = new Moar(); $db = new db(); + if ( ! isset($_SESSION["username"])) $u = null; else $u = $_SESSION["username"]; $user = new jg($u); + if( ! isset($_GET["page"]) || $_GET["page"] == "" ) $_GET["page"] = "index"; @@ -44,16 +44,19 @@ if( ! isset($_GET["page"]) || $_GET["page"] == "" ) <head> <meta charset="utf-8"> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> + <link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet"> <?php - //<link rel ="stylesheet" href="/static/style.css"> - echo "<style>" . file_get_contents('static/style.min.css'); ?> .dl-horizontal dt{white-space: normal;}.btn-info{background-color:#3083D6;border-color:#357ebd}.btn-primary{background-color:#3083D6;}.img-responsive{margin:0 auto;}@-moz-document url-prefix(){fieldset{display:table-cell;}}ul.nav li.dropdown:hover ul.dropdown-menu {display:block;}.video{max-width:720px;margin-right: auto;margin-left: auto;}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active{background-color:#3071a9}</style> + <!--%%placeholder-head%%--> <noscript><style>.navbar{margin-bottom:0;}</style></noscript> - <title>Junge Gemeinde Adlershof | <?php ucfirst($_GET["page"]); ?></title> + <title>Junge Gemeinde Adlershof | <?php echo htmlentities(ucfirst($_GET["page"])); ?></title> <link rel='shortcut icon' href='/favicon.ico' type='image/x-icon'> <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <?php + $moar->playHeader(); + ?> </head> <?php require_once 'static/header.php'; @@ -90,6 +93,12 @@ require_once 'static/header.php'; case("download"): print_download(); break; + case("foto"): + list_gallery(); + break; + case("gallery"): + show_gallery(); + break; case("action"): require_once 'action.php'; break; @@ -111,10 +120,17 @@ require_once 'static/header.php'; </div> <?php require_once 'static/footer.php'; - +$moar->playFooter(); +?> + </body> +</html> +<?php $html = ob_get_contents(); +ob_end_clean(); + +$html = $moar->magicHeader($html); +echo $html; -if ( $cache && $_SERVER["REQUEST_METHOD"] == "GET" && $_SERVER["REDIRECT_STATUS"] == 200 ) { - $c->setKey($token, $html, 3600); +if ( ! $c->bypassCache && $_SERVER["REQUEST_METHOD"] == "GET" && $_SERVER["REDIRECT_STATUS"] == 200 ) { + $c->setPageCache($token, $html, 3600); } -ob_end_flush(); diff --git a/js/gallery.min.js b/js/gallery.min.js new file mode 100644 index 0000000..73c595c --- /dev/null +++ b/js/gallery.min.js @@ -0,0 +1 @@ +!function(a){"use strict";var b=a.HTMLCanvasElement&&a.HTMLCanvasElement.prototype,c=a.Blob&&function(){try{return Boolean(new Blob)}catch(a){return!1}}(),d=c&&a.Uint8Array&&function(){try{return 100===new Blob([new Uint8Array(100)]).size}catch(a){return!1}}(),e=a.BlobBuilder||a.WebKitBlobBuilder||a.MozBlobBuilder||a.MSBlobBuilder,f=(c||e)&&a.atob&&a.ArrayBuffer&&a.Uint8Array&&function(a){var b,f,g,h,i,j;for(b=a.split(",")[0].indexOf("base64")>=0?atob(a.split(",")[1]):decodeURIComponent(a.split(",")[1]),f=new ArrayBuffer(b.length),g=new Uint8Array(f),h=0;h<b.length;h+=1)g[h]=b.charCodeAt(h);return i=a.split(",")[0].split(":")[1].split(";")[0],c?new Blob([d?g:f],{type:i}):(j=new e,j.append(f),j.getBlob(i))};a.HTMLCanvasElement&&!b.toBlob&&(b.mozGetAsFile?b.toBlob=function(a,c,d){d&&b.toDataURL&&f?a(f(this.toDataURL(c,d))):a(this.mozGetAsFile("blob",c))}:b.toDataURL&&f&&(b.toBlob=function(a,b,c){a(f(this.toDataURL(b,c)))})),"function"==typeof define&&define.amd?define(function(){return f}):a.dataURLtoBlob=f}(this);!function(a){"use strict";"function"==typeof define&&define.amd?define(["./blueimp-helper"],a):(window.blueimp=window.blueimp||{},window.blueimp.Gallery=a(window.blueimp.helper||window.jQuery))}(function(a){"use strict";function b(a,c){return void 0===document.body.style.maxHeight?null:this&&this.options===b.prototype.options?a&&a.length?(this.list=a,this.num=a.length,this.initOptions(c),void this.initialize()):void this.console.log("blueimp Gallery: No or empty list provided as first argument.",a):new b(a,c)}return a.extend(b.prototype,{options:{container:"#blueimp-gallery",slidesContainer:"div",titleElement:"h3",displayClass:"blueimp-gallery-display",controlsClass:"blueimp-gallery-controls",singleClass:"blueimp-gallery-single",leftEdgeClass:"blueimp-gallery-left",rightEdgeClass:"blueimp-gallery-right",playingClass:"blueimp-gallery-playing",slideClass:"slide",slideLoadingClass:"slide-loading",slideErrorClass:"slide-error",slideContentClass:"slide-content",toggleClass:"toggle",prevClass:"prev",nextClass:"next",closeClass:"close",playPauseClass:"play-pause",typeProperty:"type",titleProperty:"title",urlProperty:"href",displayTransition:!0,clearSlides:!0,stretchImages:!1,toggleControlsOnReturn:!0,toggleSlideshowOnSpace:!0,enableKeyboardNavigation:!0,closeOnEscape:!0,closeOnSlideClick:!0,closeOnSwipeUpOrDown:!0,emulateTouchEvents:!0,stopTouchEventsPropagation:!1,hidePageScrollbars:!0,disableScroll:!0,carousel:!1,continuous:!0,unloadElements:!0,startSlideshow:!1,slideshowInterval:5e3,index:0,preloadRange:2,transitionSpeed:400,slideshowTransitionSpeed:void 0,event:void 0,onopen:void 0,onopened:void 0,onslide:void 0,onslideend:void 0,onslidecomplete:void 0,onclose:void 0,onclosed:void 0},carouselOptions:{hidePageScrollbars:!1,toggleControlsOnReturn:!1,toggleSlideshowOnSpace:!1,enableKeyboardNavigation:!1,closeOnEscape:!1,closeOnSlideClick:!1,closeOnSwipeUpOrDown:!1,disableScroll:!1,startSlideshow:!0},console:window.console&&"function"==typeof window.console.log?window.console:{log:function(){}},support:function(b){var c={touch:void 0!==window.ontouchstart||window.DocumentTouch&&document instanceof DocumentTouch},d={webkitTransition:{end:"webkitTransitionEnd",prefix:"-webkit-"},MozTransition:{end:"transitionend",prefix:"-moz-"},OTransition:{end:"otransitionend",prefix:"-o-"},transition:{end:"transitionend",prefix:""}},e=function(){var a,d,e=c.transition;document.body.appendChild(b),e&&(a=e.name.slice(0,-9)+"ransform",void 0!==b.style[a]&&(b.style[a]="translateZ(0)",d=window.getComputedStyle(b).getPropertyValue(e.prefix+"transform"),c.transform={prefix:e.prefix,name:a,translate:!0,translateZ:!!d&&"none"!==d})),void 0!==b.style.backgroundSize&&(c.backgroundSize={},b.style.backgroundSize="contain",c.backgroundSize.contain="contain"===window.getComputedStyle(b).getPropertyValue("background-size"),b.style.backgroundSize="cover",c.backgroundSize.cover="cover"===window.getComputedStyle(b).getPropertyValue("background-size")),document.body.removeChild(b)};return function(a,c){var d;for(d in c)if(c.hasOwnProperty(d)&&void 0!==b.style[d]){a.transition=c[d],a.transition.name=d;break}}(c,d),document.body?e():a(document).on("DOMContentLoaded",e),c}(document.createElement("div")),requestAnimationFrame:window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame,initialize:function(){return this.initStartIndex(),this.initWidget()===!1?!1:(this.initEventListeners(),this.onslide(this.index),this.ontransitionend(),void(this.options.startSlideshow&&this.play()))},slide:function(a,b){window.clearTimeout(this.timeout);var c,d,e,f=this.index;if(f!==a&&1!==this.num){if(b||(b=this.options.transitionSpeed),this.support.transition){for(this.options.continuous||(a=this.circle(a)),c=Math.abs(f-a)/(f-a),this.options.continuous&&(d=c,c=-this.positions[this.circle(a)]/this.slideWidth,c!==d&&(a=-c*this.num+a)),e=Math.abs(f-a)-1;e;)e-=1,this.move(this.circle((a>f?a:f)-e-1),this.slideWidth*c,0);a=this.circle(a),this.move(f,this.slideWidth*c,b),this.move(a,0,b),this.options.continuous&&this.move(this.circle(a-c),-(this.slideWidth*c),0)}else a=this.circle(a),this.animate(f*-this.slideWidth,a*-this.slideWidth,b);this.onslide(a)}},getIndex:function(){return this.index},getNumber:function(){return this.num},prev:function(){(this.options.continuous||this.index)&&this.slide(this.index-1)},next:function(){(this.options.continuous||this.index<this.num-1)&&this.slide(this.index+1)},play:function(a){var b=this;window.clearTimeout(this.timeout),this.interval=a||this.options.slideshowInterval,this.elements[this.index]>1&&(this.timeout=this.setTimeout(!this.requestAnimationFrame&&this.slide||function(a,c){b.animationFrameId=b.requestAnimationFrame.call(window,function(){b.slide(a,c)})},[this.index+1,this.options.slideshowTransitionSpeed],this.interval)),this.container.addClass(this.options.playingClass)},pause:function(){window.clearTimeout(this.timeout),this.interval=null,this.container.removeClass(this.options.playingClass)},add:function(a){var b;for(a.concat||(a=Array.prototype.slice.call(a)),this.list.concat||(this.list=Array.prototype.slice.call(this.list)),this.list=this.list.concat(a),this.num=this.list.length,this.num>2&&null===this.options.continuous&&(this.options.continuous=!0,this.container.removeClass(this.options.leftEdgeClass)),this.container.removeClass(this.options.rightEdgeClass).removeClass(this.options.singleClass),b=this.num-a.length;b<this.num;b+=1)this.addSlide(b),this.positionSlide(b);this.positions.length=this.num,this.initSlides(!0)},resetSlides:function(){this.slidesContainer.empty(),this.slides=[]},handleClose:function(){var a=this.options;this.destroyEventListeners(),this.pause(),this.container[0].style.display="none",this.container.removeClass(a.displayClass).removeClass(a.singleClass).removeClass(a.leftEdgeClass).removeClass(a.rightEdgeClass),a.hidePageScrollbars&&(document.body.style.overflow=this.bodyOverflowStyle),this.options.clearSlides&&this.resetSlides(),this.options.onclosed&&this.options.onclosed.call(this)},close:function(){var a=this,b=function(c){c.target===a.container[0]&&(a.container.off(a.support.transition.end,b),a.handleClose())};this.options.onclose&&this.options.onclose.call(this),this.support.transition&&this.options.displayTransition?(this.container.on(this.support.transition.end,b),this.container.removeClass(this.options.displayClass)):this.handleClose()},circle:function(a){return(this.num+a%this.num)%this.num},move:function(a,b,c){this.translateX(a,b,c),this.positions[a]=b},translate:function(a,b,c,d){var e=this.slides[a].style,f=this.support.transition,g=this.support.transform;e[f.name+"Duration"]=d+"ms",e[g.name]="translate("+b+"px, "+c+"px)"+(g.translateZ?" translateZ(0)":"")},translateX:function(a,b,c){this.translate(a,b,0,c)},translateY:function(a,b,c){this.translate(a,0,b,c)},animate:function(a,b,c){if(!c)return void(this.slidesContainer[0].style.left=b+"px");var d=this,e=(new Date).getTime(),f=window.setInterval(function(){var g=(new Date).getTime()-e;return g>c?(d.slidesContainer[0].style.left=b+"px",d.ontransitionend(),void window.clearInterval(f)):void(d.slidesContainer[0].style.left=(b-a)*(Math.floor(g/c*100)/100)+a+"px")},4)},preventDefault:function(a){a.preventDefault?a.preventDefault():a.returnValue=!1},stopPropagation:function(a){a.stopPropagation?a.stopPropagation():a.cancelBubble=!0},onresize:function(){this.initSlides(!0)},onmousedown:function(a){a.which&&1===a.which&&"VIDEO"!==a.target.nodeName&&(a.preventDefault(),(a.originalEvent||a).touches=[{pageX:a.pageX,pageY:a.pageY}],this.ontouchstart(a))},onmousemove:function(a){this.touchStart&&((a.originalEvent||a).touches=[{pageX:a.pageX,pageY:a.pageY}],this.ontouchmove(a))},onmouseup:function(a){this.touchStart&&(this.ontouchend(a),delete this.touchStart)},onmouseout:function(b){if(this.touchStart){var c=b.target,d=b.relatedTarget;(!d||d!==c&&!a.contains(c,d))&&this.onmouseup(b)}},ontouchstart:function(a){this.options.stopTouchEventsPropagation&&this.stopPropagation(a);var b=(a.originalEvent||a).touches[0];this.touchStart={x:b.pageX,y:b.pageY,time:Date.now()},this.isScrolling=void 0,this.touchDelta={}},ontouchmove:function(a){this.options.stopTouchEventsPropagation&&this.stopPropagation(a);var b,c,d=(a.originalEvent||a).touches[0],e=(a.originalEvent||a).scale,f=this.index;if(!(d.length>1||e&&1!==e))if(this.options.disableScroll&&a.preventDefault(),this.touchDelta={x:d.pageX-this.touchStart.x,y:d.pageY-this.touchStart.y},b=this.touchDelta.x,void 0===this.isScrolling&&(this.isScrolling=this.isScrolling||Math.abs(b)<Math.abs(this.touchDelta.y)),this.isScrolling)this.options.closeOnSwipeUpOrDown&&this.translateY(f,this.touchDelta.y+this.positions[f],0);else for(a.preventDefault(),window.clearTimeout(this.timeout),this.options.continuous?c=[this.circle(f+1),f,this.circle(f-1)]:(this.touchDelta.x=b/=!f&&b>0||f===this.num-1&&0>b?Math.abs(b)/this.slideWidth+1:1,c=[f],f&&c.push(f-1),f<this.num-1&&c.unshift(f+1));c.length;)f=c.pop(),this.translateX(f,b+this.positions[f],0)},ontouchend:function(a){this.options.stopTouchEventsPropagation&&this.stopPropagation(a);var b,c,d,e,f,g=this.index,h=this.options.transitionSpeed,i=this.slideWidth,j=Number(Date.now()-this.touchStart.time)<250,k=j&&Math.abs(this.touchDelta.x)>20||Math.abs(this.touchDelta.x)>i/2,l=!g&&this.touchDelta.x>0||g===this.num-1&&this.touchDelta.x<0,m=!k&&this.options.closeOnSwipeUpOrDown&&(j&&Math.abs(this.touchDelta.y)>20||Math.abs(this.touchDelta.y)>this.slideHeight/2);this.options.continuous&&(l=!1),b=this.touchDelta.x<0?-1:1,this.isScrolling?m?this.close():this.translateY(g,0,h):k&&!l?(c=g+b,d=g-b,e=i*b,f=-i*b,this.options.continuous?(this.move(this.circle(c),e,0),this.move(this.circle(g-2*b),f,0)):c>=0&&c<this.num&&this.move(c,e,0),this.move(g,this.positions[g]+e,h),this.move(this.circle(d),this.positions[this.circle(d)]+e,h),g=this.circle(d),this.onslide(g)):this.options.continuous?(this.move(this.circle(g-1),-i,h),this.move(g,0,h),this.move(this.circle(g+1),i,h)):(g&&this.move(g-1,-i,h),this.move(g,0,h),g<this.num-1&&this.move(g+1,i,h))},ontouchcancel:function(a){this.touchStart&&(this.ontouchend(a),delete this.touchStart)},ontransitionend:function(a){var b=this.slides[this.index];a&&b!==a.target||(this.interval&&this.play(),this.setTimeout(this.options.onslideend,[this.index,b]))},oncomplete:function(b){var c,d=b.target||b.srcElement,e=d&&d.parentNode;d&&e&&(c=this.getNodeIndex(e),a(e).removeClass(this.options.slideLoadingClass),"error"===b.type?(a(e).addClass(this.options.slideErrorClass),this.elements[c]=3):this.elements[c]=2,d.clientHeight>this.container[0].clientHeight&&(d.style.maxHeight=this.container[0].clientHeight),this.interval&&this.slides[this.index]===e&&this.play(),this.setTimeout(this.options.onslidecomplete,[c,e]))},onload:function(a){this.oncomplete(a)},onerror:function(a){this.oncomplete(a)},onkeydown:function(a){switch(a.which||a.keyCode){case 13:this.options.toggleControlsOnReturn&&(this.preventDefault(a),this.toggleControls());break;case 27:this.options.closeOnEscape&&this.close();break;case 32:this.options.toggleSlideshowOnSpace&&(this.preventDefault(a),this.toggleSlideshow());break;case 37:this.options.enableKeyboardNavigation&&(this.preventDefault(a),this.prev());break;case 39:this.options.enableKeyboardNavigation&&(this.preventDefault(a),this.next())}},handleClick:function(b){var c=this.options,d=b.target||b.srcElement,e=d.parentNode,f=function(b){return a(d).hasClass(b)||a(e).hasClass(b)};f(c.toggleClass)?(this.preventDefault(b),this.toggleControls()):f(c.prevClass)?(this.preventDefault(b),this.prev()):f(c.nextClass)?(this.preventDefault(b),this.next()):f(c.closeClass)?(this.preventDefault(b),this.close()):f(c.playPauseClass)?(this.preventDefault(b),this.toggleSlideshow()):e===this.slidesContainer[0]?(this.preventDefault(b),c.closeOnSlideClick?this.close():this.toggleControls()):e.parentNode&&e.parentNode===this.slidesContainer[0]&&(this.preventDefault(b),this.toggleControls())},onclick:function(a){return this.options.emulateTouchEvents&&this.touchDelta&&(Math.abs(this.touchDelta.x)>20||Math.abs(this.touchDelta.y)>20)?void delete this.touchDelta:this.handleClick(a)},updateEdgeClasses:function(a){a?this.container.removeClass(this.options.leftEdgeClass):this.container.addClass(this.options.leftEdgeClass),a===this.num-1?this.container.addClass(this.options.rightEdgeClass):this.container.removeClass(this.options.rightEdgeClass)},handleSlide:function(a){this.options.continuous||this.updateEdgeClasses(a),this.loadElements(a),this.options.unloadElements&&this.unloadElements(a),this.setTitle(a)},onslide:function(a){this.index=a,this.handleSlide(a),this.setTimeout(this.options.onslide,[a,this.slides[a]])},setTitle:function(a){var b=this.slides[a].firstChild.title,c=this.titleElement;c.length&&(this.titleElement.empty(),b&&c[0].appendChild(document.createTextNode(b)))},setTimeout:function(a,b,c){var d=this;return a&&window.setTimeout(function(){a.apply(d,b||[])},c||0)},imageFactory:function(b,c){var d,e,f,g=this,h=this.imagePrototype.cloneNode(!1),i=b,j=this.options.stretchImages,k=function(b){if(!d){if(b={type:b.type,target:e},!e.parentNode)return g.setTimeout(k,[b]);d=!0,a(h).off("load error",k),j&&"load"===b.type&&(e.style.background='url("'+i+'") center no-repeat',e.style.backgroundSize=j),c(b)}};return"string"!=typeof i&&(i=this.getItemProperty(b,this.options.urlProperty),f=this.getItemProperty(b,this.options.titleProperty)),j===!0&&(j="contain"),j=this.support.backgroundSize&&this.support.backgroundSize[j]&&j,j?e=this.elementPrototype.cloneNode(!1):(e=h,h.draggable=!1),f&&(e.title=f),a(h).on("load error",k),h.src=i,e},createElement:function(b,c){var d=b&&this.getItemProperty(b,this.options.typeProperty),e=d&&this[d.split("/")[0]+"Factory"]||this.imageFactory,f=b&&e.call(this,b,c);return f||(f=this.elementPrototype.cloneNode(!1),this.setTimeout(c,[{type:"error",target:f}])),a(f).addClass(this.options.slideContentClass),f},loadElement:function(b){this.elements[b]||(this.slides[b].firstChild?this.elements[b]=a(this.slides[b]).hasClass(this.options.slideErrorClass)?3:2:(this.elements[b]=1,a(this.slides[b]).addClass(this.options.slideLoadingClass),this.slides[b].appendChild(this.createElement(this.list[b],this.proxyListener))))},loadElements:function(a){var b,c=Math.min(this.num,2*this.options.preloadRange+1),d=a;for(b=0;c>b;b+=1)d+=b*(b%2===0?-1:1),d=this.circle(d),this.loadElement(d)},unloadElements:function(a){var b,c,d;for(b in this.elements)this.elements.hasOwnProperty(b)&&(d=Math.abs(a-b),d>this.options.preloadRange&&d+this.options.preloadRange<this.num&&(c=this.slides[b],c.removeChild(c.firstChild),delete this.elements[b]))},addSlide:function(a){var b=this.slidePrototype.cloneNode(!1);b.setAttribute("data-index",a),this.slidesContainer[0].appendChild(b),this.slides.push(b)},positionSlide:function(a){var b=this.slides[a];b.style.width=this.slideWidth+"px",this.support.transition&&(b.style.left=a*-this.slideWidth+"px",this.move(a,this.index>a?-this.slideWidth:this.index<a?this.slideWidth:0,0))},initSlides:function(b){var c,d;for(b||(this.positions=[],this.positions.length=this.num,this.elements={},this.imagePrototype=document.createElement("img"),this.elementPrototype=document.createElement("div"),this.slidePrototype=document.createElement("div"),a(this.slidePrototype).addClass(this.options.slideClass),this.slides=this.slidesContainer[0].children,c=this.options.clearSlides||this.slides.length!==this.num),this.slideWidth=this.container[0].offsetWidth,this.slideHeight=this.container[0].offsetHeight,this.slidesContainer[0].style.width=this.num*this.slideWidth+"px",c&&this.resetSlides(),d=0;d<this.num;d+=1)c&&this.addSlide(d),this.positionSlide(d);this.options.continuous&&this.support.transition&&(this.move(this.circle(this.index-1),-this.slideWidth,0),this.move(this.circle(this.index+1),this.slideWidth,0)),this.support.transition||(this.slidesContainer[0].style.left=this.index*-this.slideWidth+"px")},toggleControls:function(){var a=this.options.controlsClass;this.container.hasClass(a)?this.container.removeClass(a):this.container.addClass(a)},toggleSlideshow:function(){this.interval?this.pause():this.play()},getNodeIndex:function(a){return parseInt(a.getAttribute("data-index"),10)},getNestedProperty:function(a,b){return b.replace(/\[(?:'([^']+)'|"([^"]+)"|(\d+))\]|(?:(?:^|\.)([^\.\[]+))/g,function(b,c,d,e,f){var g=f||c||d||e&&parseInt(e,10);b&&a&&(a=a[g])}),a},getDataProperty:function(b,c){if(b.getAttribute){var d=b.getAttribute("data-"+c.replace(/([A-Z])/g,"-$1").toLowerCase());if("string"==typeof d){if(/^(true|false|null|-?\d+(\.\d+)?|\{[\s\S]*\}|\[[\s\S]*\])$/.test(d))try{return a.parseJSON(d)}catch(e){}return d}}},getItemProperty:function(a,b){var c=a[b];return void 0===c&&(c=this.getDataProperty(a,b),void 0===c&&(c=this.getNestedProperty(a,b))),c},initStartIndex:function(){var a,b=this.options.index,c=this.options.urlProperty;if(b&&"number"!=typeof b)for(a=0;a<this.num;a+=1)if(this.list[a]===b||this.getItemProperty(this.list[a],c)===this.getItemProperty(b,c)){b=a;break}this.index=this.circle(parseInt(b,10)||0)},initEventListeners:function(){var b=this,c=this.slidesContainer,d=function(a){var c=b.support.transition&&b.support.transition.end===a.type?"transitionend":a.type;b["on"+c](a)};a(window).on("resize",d),a(document.body).on("keydown",d),this.container.on("click",d),this.support.touch?c.on("touchstart touchmove touchend touchcancel",d):this.options.emulateTouchEvents&&this.support.transition&&c.on("mousedown mousemove mouseup mouseout",d),this.support.transition&&c.on(this.support.transition.end,d),this.proxyListener=d},destroyEventListeners:function(){var b=this.slidesContainer,c=this.proxyListener;a(window).off("resize",c),a(document.body).off("keydown",c),this.container.off("click",c),this.support.touch?b.off("touchstart touchmove touchend touchcancel",c):this.options.emulateTouchEvents&&this.support.transition&&b.off("mousedown mousemove mouseup mouseout",c),this.support.transition&&b.off(this.support.transition.end,c)},handleOpen:function(){this.options.onopened&&this.options.onopened.call(this)},initWidget:function(){var b=this,c=function(a){a.target===b.container[0]&&(b.container.off(b.support.transition.end,c),b.handleOpen())};return this.container=a(this.options.container),this.container.length?(this.slidesContainer=this.container.find(this.options.slidesContainer).first(),this.slidesContainer.length?(this.titleElement=this.container.find(this.options.titleElement).first(),1===this.num&&this.container.addClass(this.options.singleClass),this.options.onopen&&this.options.onopen.call(this),this.support.transition&&this.options.displayTransition?this.container.on(this.support.transition.end,c):this.handleOpen(),this.options.hidePageScrollbars&&(this.bodyOverflowStyle=document.body.style.overflow,document.body.style.overflow="hidden"),this.container[0].style.display="block",this.initSlides(),void this.container.addClass(this.options.displayClass)):(this.console.log("blueimp Gallery: Slides container not found.",this.options.slidesContainer),!1)):(this.console.log("blueimp Gallery: Widget container not found.",this.options.container),!1)},initOptions:function(b){this.options=a.extend({},this.options),(b&&b.carousel||this.options.carousel&&(!b||b.carousel!==!1))&&a.extend(this.options,this.carouselOptions),a.extend(this.options,b),this.num<3&&(this.options.continuous=this.options.continuous?null:!1),this.support.transition||(this.options.emulateTouchEvents=!1),this.options.event&&this.preventDefault(this.options.event)}}),b}),function(a){"use strict";"function"==typeof define&&define.amd?define(["./blueimp-helper","./blueimp-gallery"],a):a(window.blueimp.helper||window.jQuery,window.blueimp.Gallery)}(function(a,b){"use strict";a.extend(b.prototype.options,{fullScreen:!1});var c=b.prototype.initialize,d=b.prototype.close;return a.extend(b.prototype,{getFullScreenElement:function(){return document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement},requestFullScreen:function(a){a.requestFullscreen?a.requestFullscreen():a.webkitRequestFullscreen?a.webkitRequestFullscreen():a.mozRequestFullScreen?a.mozRequestFullScreen():a.msRequestFullscreen&&a.msRequestFullscreen()},exitFullScreen:function(){document.exitFullscreen?document.exitFullscreen():document.webkitCancelFullScreen?document.webkitCancelFullScreen():document.mozCancelFullScreen?document.mozCancelFullScreen():document.msExitFullscreen&&document.msExitFullscreen()},initialize:function(){c.call(this),this.options.fullScreen&&!this.getFullScreenElement()&&this.requestFullScreen(this.container[0])},close:function(){this.getFullScreenElement()===this.container[0]&&this.exitFullScreen(),d.call(this)}}),b}),function(a){"use strict";"function"==typeof define&&define.amd?define(["./blueimp-helper","./blueimp-gallery"],a):a(window.blueimp.helper||window.jQuery,window.blueimp.Gallery)}(function(a,b){"use strict";a.extend(b.prototype.options,{indicatorContainer:"ol",activeIndicatorClass:"active",thumbnailProperty:"thumbnail",thumbnailIndicators:!0});var c=b.prototype.initSlides,d=b.prototype.addSlide,e=b.prototype.resetSlides,f=b.prototype.handleClick,g=b.prototype.handleSlide,h=b.prototype.handleClose;return a.extend(b.prototype,{createIndicator:function(b){var c,d,e=this.indicatorPrototype.cloneNode(!1),f=this.getItemProperty(b,this.options.titleProperty),g=this.options.thumbnailProperty;return this.options.thumbnailIndicators&&(d=b.getElementsByTagName&&a(b).find("img")[0],d?c=d.src:g&&(c=this.getItemProperty(b,g)),c&&(e.style.backgroundImage='url("'+c+'")')),f&&(e.title=f),e},addIndicator:function(a){if(this.indicatorContainer.length){var b=this.createIndicator(this.list[a]);b.setAttribute("data-index",a),this.indicatorContainer[0].appendChild(b),this.indicators.push(b)}},setActiveIndicator:function(b){this.indicators&&(this.activeIndicator&&this.activeIndicator.removeClass(this.options.activeIndicatorClass),this.activeIndicator=a(this.indicators[b]),this.activeIndicator.addClass(this.options.activeIndicatorClass))},initSlides:function(a){a||(this.indicatorContainer=this.container.find(this.options.indicatorContainer),this.indicatorContainer.length&&(this.indicatorPrototype=document.createElement("li"),this.indicators=this.indicatorContainer[0].children)),c.call(this,a)},addSlide:function(a){d.call(this,a),this.addIndicator(a)},resetSlides:function(){e.call(this),this.indicatorContainer.empty(),this.indicators=[]},handleClick:function(a){var b=a.target||a.srcElement,c=b.parentNode;if(c===this.indicatorContainer[0])this.preventDefault(a),this.slide(this.getNodeIndex(b));else{if(c.parentNode!==this.indicatorContainer[0])return f.call(this,a);this.preventDefault(a),this.slide(this.getNodeIndex(c))}},handleSlide:function(a){g.call(this,a),this.setActiveIndicator(a)},handleClose:function(){this.activeIndicator&&this.activeIndicator.removeClass(this.options.activeIndicatorClass),h.call(this)}}),b}),function(a){"use strict";"function"==typeof define&&define.amd?define(["./blueimp-helper","./blueimp-gallery"],a):a(window.blueimp.helper||window.jQuery,window.blueimp.Gallery)}(function(a,b){"use strict";a.extend(b.prototype.options,{videoContentClass:"video-content",videoLoadingClass:"video-loading",videoPlayingClass:"video-playing",videoPosterProperty:"poster",videoSourcesProperty:"sources"});var c=b.prototype.handleSlide;return a.extend(b.prototype,{handleSlide:function(a){c.call(this,a),this.playingVideo&&this.playingVideo.pause()},videoFactory:function(b,c,d){var e,f,g,h,i,j=this,k=this.options,l=this.elementPrototype.cloneNode(!1),m=a(l),n=[{type:"error",target:l}],o=d||document.createElement("video"),p=this.getItemProperty(b,k.urlProperty),q=this.getItemProperty(b,k.typeProperty),r=this.getItemProperty(b,k.titleProperty),s=this.getItemProperty(b,k.videoPosterProperty),t=this.getItemProperty(b,k.videoSourcesProperty);if(m.addClass(k.videoContentClass),r&&(l.title=r),o.canPlayType)if(p&&q&&o.canPlayType(q))o.src=p;else for(;t&&t.length;)if(f=t.shift(),p=this.getItemProperty(f,k.urlProperty),q=this.getItemProperty(f,k.typeProperty),p&&q&&o.canPlayType(q)){o.src=p;break}return s&&(o.poster=s,e=this.imagePrototype.cloneNode(!1),a(e).addClass(k.toggleClass),e.src=s,e.draggable=!1,l.appendChild(e)),g=document.createElement("a"),g.setAttribute("target","_blank"),d||g.setAttribute("download",r),g.href=p,o.src&&(o.controls=!0,(d||a(o)).on("error",function(){j.setTimeout(c,n)}).on("pause",function(){h=!1,m.removeClass(j.options.videoLoadingClass).removeClass(j.options.videoPlayingClass),i&&j.container.addClass(j.options.controlsClass),delete j.playingVideo,j.interval&&j.play()}).on("playing",function(){h=!1,m.removeClass(j.options.videoLoadingClass).addClass(j.options.videoPlayingClass),j.container.hasClass(j.options.controlsClass)?(i=!0,j.container.removeClass(j.options.controlsClass)):i=!1}).on("play",function(){window.clearTimeout(j.timeout),h=!0,m.addClass(j.options.videoLoadingClass),j.playingVideo=o}),a(g).on("click",function(a){j.preventDefault(a),h?o.pause():o.play()}),l.appendChild(d&&d.element||o)),l.appendChild(g),this.setTimeout(c,[{type:"load",target:l}]),l}}),b}),function(a){"use strict";"function"==typeof define&&define.amd?define(["./blueimp-helper","./blueimp-gallery-video"],a):a(window.blueimp.helper||window.jQuery,window.blueimp.Gallery)}(function(a,b){"use strict";if(!window.postMessage)return b;a.extend(b.prototype.options,{vimeoVideoIdProperty:"vimeo",vimeoPlayerUrl:"//player.vimeo.com/video/VIDEO_ID?api=1&player_id=PLAYER_ID",vimeoPlayerIdPrefix:"vimeo-player-",vimeoClickToPlay:!0});var c=b.prototype.textFactory||b.prototype.imageFactory,d=function(a,b,c,d){this.url=a,this.videoId=b,this.playerId=c,this.clickToPlay=d,this.element=document.createElement("div"),this.listeners={}},e=0;return a.extend(d.prototype,{canPlayType:function(){return!0},on:function(a,b){return this.listeners[a]=b,this},loadAPI:function(){for(var b,c,d=this,e="//"+("https"===location.protocol?"secure-":"")+"a.vimeocdn.com/js/froogaloop2.min.js",f=document.getElementsByTagName("script"),g=f.length,h=function(){!c&&d.playOnReady&&d.play(),c=!0};g;)if(g-=1,f[g].src===e){b=f[g];break}b||(b=document.createElement("script"),b.src=e),a(b).on("load",h),f[0].parentNode.insertBefore(b,f[0]),/loaded|complete/.test(b.readyState)&&h()},onReady:function(){var a=this;this.ready=!0,this.player.addEvent("play",function(){a.hasPlayed=!0,a.onPlaying()}),this.player.addEvent("pause",function(){a.onPause()}),this.player.addEvent("finish",function(){a.onPause()}),this.playOnReady&&this.play()},onPlaying:function(){this.playStatus<2&&(this.listeners.playing(),this.playStatus=2)},onPause:function(){this.listeners.pause(),delete this.playStatus},insertIframe:function(){var a=document.createElement("iframe");a.src=this.url.replace("VIDEO_ID",this.videoId).replace("PLAYER_ID",this.playerId),a.id=this.playerId,this.element.parentNode.replaceChild(a,this.element),this.element=a},play:function(){var a=this;this.playStatus||(this.listeners.play(),this.playStatus=1),this.ready?!this.hasPlayed&&(this.clickToPlay||window.navigator&&/iP(hone|od|ad)/.test(window.navigator.platform))?this.onPlaying():this.player.api("play"):(this.playOnReady=!0,window.$f?this.player||(this.insertIframe(),this.player=$f(this.element),this.player.addEvent("ready",function(){a.onReady()})):this.loadAPI())},pause:function(){this.ready?this.player.api("pause"):this.playStatus&&(delete this.playOnReady,this.listeners.pause(),delete this.playStatus)}}),a.extend(b.prototype,{VimeoPlayer:d,textFactory:function(a,b){var f=this.options,g=this.getItemProperty(a,f.vimeoVideoIdProperty);return g?(void 0===this.getItemProperty(a,f.urlProperty)&&(a[f.urlProperty]="//vimeo.com/"+g),e+=1,this.videoFactory(a,b,new d(f.vimeoPlayerUrl,g,f.vimeoPlayerIdPrefix+e,f.vimeoClickToPlay))):c.call(this,a,b)}}),b}),function(a){"use strict";"function"==typeof define&&define.amd?define(["./blueimp-helper","./blueimp-gallery-video"],a):a(window.blueimp.helper||window.jQuery,window.blueimp.Gallery)}(function(a,b){"use strict";if(!window.postMessage)return b;a.extend(b.prototype.options,{youTubeVideoIdProperty:"youtube",youTubePlayerVars:{wmode:"transparent"},youTubeClickToPlay:!0});var c=b.prototype.textFactory||b.prototype.imageFactory,d=function(a,b,c){this.videoId=a,this.playerVars=b,this.clickToPlay=c,this.element=document.createElement("div"),this.listeners={}};return a.extend(d.prototype,{canPlayType:function(){return!0},on:function(a,b){return this.listeners[a]=b,this},loadAPI:function(){var a,b=this,c=window.onYouTubeIframeAPIReady,d="//www.youtube.com/iframe_api",e=document.getElementsByTagName("script"),f=e.length;for(window.onYouTubeIframeAPIReady=function(){c&&c.apply(this),b.playOnReady&&b.play()};f;)if(f-=1,e[f].src===d)return;a=document.createElement("script"),a.src=d,e[0].parentNode.insertBefore(a,e[0])},onReady:function(){this.ready=!0,this.playOnReady&&this.play()},onPlaying:function(){this.playStatus<2&&(this.listeners.playing(),this.playStatus=2)},onPause:function(){b.prototype.setTimeout.call(this,this.checkSeek,null,2e3)},checkSeek:function(){(this.stateChange===YT.PlayerState.PAUSED||this.stateChange===YT.PlayerState.ENDED)&&(this.listeners.pause(),delete this.playStatus)},onStateChange:function(a){switch(a.data){case YT.PlayerState.PLAYING:this.hasPlayed=!0,this.onPlaying();break;case YT.PlayerState.PAUSED:case YT.PlayerState.ENDED:this.onPause()}this.stateChange=a.data},onError:function(a){this.listeners.error(a)},play:function(){var a=this;this.playStatus||(this.listeners.play(),this.playStatus=1),this.ready?!this.hasPlayed&&(this.clickToPlay||window.navigator&&/iP(hone|od|ad)/.test(window.navigator.platform))?this.onPlaying():this.player.playVideo():(this.playOnReady=!0,window.YT&&YT.Player?this.player||(this.player=new YT.Player(this.element,{videoId:this.videoId,playerVars:this.playerVars,events:{onReady:function(){a.onReady()},onStateChange:function(b){a.onStateChange(b)},onError:function(b){a.onError(b)}}})):this.loadAPI())},pause:function(){this.ready?this.player.pauseVideo():this.playStatus&&(delete this.playOnReady,this.listeners.pause(),delete this.playStatus)}}),a.extend(b.prototype,{YouTubePlayer:d,textFactory:function(a,b){var e=this.options,f=this.getItemProperty(a,e.youTubeVideoIdProperty);return f?(void 0===this.getItemProperty(a,e.urlProperty)&&(a[e.urlProperty]="//www.youtube.com/watch?v="+f),void 0===this.getItemProperty(a,e.videoPosterProperty)&&(a[e.videoPosterProperty]="//img.youtube.com/vi/"+f+"/maxresdefault.jpg"),this.videoFactory(a,b,new d(f,e.youTubePlayerVars,e.youTubeClickToPlay))):c.call(this,a,b)}}),b}),function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery","./blueimp-gallery"],a):a(window.jQuery,window.blueimp.Gallery)}(function(a,b){"use strict";a(document).on("click","[data-gallery]",function(c){var d=a(this).data("gallery"),e=a(d),f=e.length&&e||a(b.prototype.options.container),g={onopen:function(){f.data("gallery",this).trigger("open")},onopened:function(){f.trigger("opened")},onslide:function(){f.trigger("slide",arguments)},onslideend:function(){f.trigger("slideend",arguments)},onslidecomplete:function(){f.trigger("slidecomplete",arguments)},onclose:function(){f.trigger("close")},onclosed:function(){f.trigger("closed").removeData("gallery")}},h=a.extend(f.data(),{container:f[0],index:this,event:c},g),i=a('[data-gallery="'+d+'"]');return h.filter&&(i=i.filter(h.filter)),new b(i,h)})});!function(a){"use strict";var b=function(a,c,d){var e,f,g=document.createElement("img");if(g.onerror=c,g.onload=function(){!f||d&&d.noRevoke||b.revokeObjectURL(f),c&&c(b.scale(g,d))},b.isInstanceOf("Blob",a)||b.isInstanceOf("File",a))e=f=b.createObjectURL(a),g._type=a.type;else{if("string"!=typeof a)return!1;e=a,d&&d.crossOrigin&&(g.crossOrigin=d.crossOrigin)}return e?(g.src=e,g):b.readFile(a,function(a){var b=a.target;b&&b.result?g.src=b.result:c&&c(a)})},c=window.createObjectURL&&window||window.URL&&URL.revokeObjectURL&&URL||window.webkitURL&&webkitURL;b.isInstanceOf=function(a,b){return Object.prototype.toString.call(b)==="[object "+a+"]"},b.transformCoordinates=function(){},b.getTransformedOptions=function(a,b){var c,d,e,f,g=b.aspectRatio;if(!g)return b;c={};for(d in b)b.hasOwnProperty(d)&&(c[d]=b[d]);return c.crop=!0,e=a.naturalWidth||a.width,f=a.naturalHeight||a.height,e/f>g?(c.maxWidth=f*g,c.maxHeight=f):(c.maxWidth=e,c.maxHeight=e/g),c},b.renderImageToCanvas=function(a,b,c,d,e,f,g,h,i,j){return a.getContext("2d").drawImage(b,c,d,e,f,g,h,i,j),a},b.hasCanvasOption=function(a){return a.canvas||a.crop||a.aspectRatio},b.scale=function(a,c){c=c||{};var d,e,f,g,h,i,j,k,l,m=document.createElement("canvas"),n=a.getContext||b.hasCanvasOption(c)&&m.getContext,o=a.naturalWidth||a.width,p=a.naturalHeight||a.height,q=o,r=p,s=function(){var a=Math.max((f||q)/q,(g||r)/r);a>1&&(q*=a,r*=a)},t=function(){var a=Math.min((d||q)/q,(e||r)/r);1>a&&(q*=a,r*=a)};return n&&(c=b.getTransformedOptions(a,c),j=c.left||0,k=c.top||0,c.sourceWidth?(h=c.sourceWidth,void 0!==c.right&&void 0===c.left&&(j=o-h-c.right)):h=o-j-(c.right||0),c.sourceHeight?(i=c.sourceHeight,void 0!==c.bottom&&void 0===c.top&&(k=p-i-c.bottom)):i=p-k-(c.bottom||0),q=h,r=i),d=c.maxWidth,e=c.maxHeight,f=c.minWidth,g=c.minHeight,n&&d&&e&&c.crop?(q=d,r=e,l=h/i-d/e,0>l?(i=e*h/d,void 0===c.top&&void 0===c.bottom&&(k=(p-i)/2)):l>0&&(h=d*i/e,void 0===c.left&&void 0===c.right&&(j=(o-h)/2))):((c.contain||c.cover)&&(f=d=d||f,g=e=e||g),c.cover?(t(),s()):(s(),t())),n?(m.width=q,m.height=r,b.transformCoordinates(m,c),b.renderImageToCanvas(m,a,j,k,h,i,0,0,q,r)):(a.width=q,a.height=r,a)},b.createObjectURL=function(a){return c?c.createObjectURL(a):!1},b.revokeObjectURL=function(a){return c?c.revokeObjectURL(a):!1},b.readFile=function(a,b,c){if(window.FileReader){var d=new FileReader;if(d.onload=d.onerror=b,c=c||"readAsDataURL",d[c])return d[c](a),d}return!1},"function"==typeof define&&define.amd?define(function(){return b}):a.loadImage=b}(this),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image"],a):a(window.loadImage)}(function(a){"use strict";if(window.navigator&&window.navigator.platform&&/iP(hone|od|ad)/.test(window.navigator.platform)){var b=a.renderImageToCanvas;a.detectSubsampling=function(a){var b,c;return a.width*a.height>1048576?(b=document.createElement("canvas"),b.width=b.height=1,c=b.getContext("2d"),c.drawImage(a,-a.width+1,0),0===c.getImageData(0,0,1,1).data[3]):!1},a.detectVerticalSquash=function(a,b){var c,d,e,f,g,h=a.naturalHeight||a.height,i=document.createElement("canvas"),j=i.getContext("2d");for(b&&(h/=2),i.width=1,i.height=h,j.drawImage(a,0,0),c=j.getImageData(0,0,1,h).data,d=0,e=h,f=h;f>d;)g=c[4*(f-1)+3],0===g?e=f:d=f,f=e+d>>1;return f/h||1},a.renderImageToCanvas=function(c,d,e,f,g,h,i,j,k,l){if("image/jpeg"===d._type){var m,n,o,p,q=c.getContext("2d"),r=document.createElement("canvas"),s=1024,t=r.getContext("2d");if(r.width=s,r.height=s,q.save(),m=a.detectSubsampling(d),m&&(e/=2,f/=2,g/=2,h/=2),n=a.detectVerticalSquash(d,m),m||1!==n){for(f*=n,k=Math.ceil(s*k/g),l=Math.ceil(s*l/h/n),j=0,p=0;h>p;){for(i=0,o=0;g>o;)t.clearRect(0,0,s,s),t.drawImage(d,e,f,g,h,-o,-p,g,h),q.drawImage(r,0,0,s,s,i,j,k,l),o+=s,i+=k;p+=s,j+=l}return q.restore(),c}}return b(c,d,e,f,g,h,i,j,k,l)}}}),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image"],a):a(window.loadImage)}(function(a){"use strict";var b=a.hasCanvasOption,c=a.transformCoordinates,d=a.getTransformedOptions;a.hasCanvasOption=function(c){return b.call(a,c)||c.orientation},a.transformCoordinates=function(b,d){c.call(a,b,d);var e=b.getContext("2d"),f=b.width,g=b.height,h=d.orientation;if(h&&!(h>8))switch(h>4&&(b.width=g,b.height=f),h){case 2:e.translate(f,0),e.scale(-1,1);break;case 3:e.translate(f,g),e.rotate(Math.PI);break;case 4:e.translate(0,g),e.scale(1,-1);break;case 5:e.rotate(.5*Math.PI),e.scale(1,-1);break;case 6:e.rotate(.5*Math.PI),e.translate(0,-g);break;case 7:e.rotate(.5*Math.PI),e.translate(f,-g),e.scale(-1,1);break;case 8:e.rotate(-.5*Math.PI),e.translate(-f,0)}},a.getTransformedOptions=function(b,c){var e,f,g=d.call(a,b,c),h=g.orientation;if(!h||h>8||1===h)return g;e={};for(f in g)g.hasOwnProperty(f)&&(e[f]=g[f]);switch(g.orientation){case 2:e.left=g.right,e.right=g.left;break;case 3:e.left=g.right,e.top=g.bottom,e.right=g.left,e.bottom=g.top;break;case 4:e.top=g.bottom,e.bottom=g.top;break;case 5:e.left=g.top,e.top=g.left,e.right=g.bottom,e.bottom=g.right;break;case 6:e.left=g.top,e.top=g.right,e.right=g.bottom,e.bottom=g.left;break;case 7:e.left=g.bottom,e.top=g.right,e.right=g.top,e.bottom=g.left;break;case 8:e.left=g.bottom,e.top=g.left,e.right=g.top,e.bottom=g.right}return g.orientation>4&&(e.maxWidth=g.maxHeight,e.maxHeight=g.maxWidth,e.minWidth=g.minHeight,e.minHeight=g.minWidth,e.sourceWidth=g.sourceHeight,e.sourceHeight=g.sourceWidth),e}}),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image"],a):a(window.loadImage)}(function(a){"use strict";var b=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);a.blobSlice=b&&function(){var a=this.slice||this.webkitSlice||this.mozSlice;return a.apply(this,arguments)},a.metaDataParsers={jpeg:{65505:[]}},a.parseMetaData=function(b,c,d){d=d||{};var e=this,f=d.maxMetaDataSize||262144,g={},h=!(window.DataView&&b&&b.size>=12&&"image/jpeg"===b.type&&a.blobSlice);(h||!a.readFile(a.blobSlice.call(b,0,f),function(b){if(b.target.error)return console.log(b.target.error),void c(g);var f,h,i,j,k=b.target.result,l=new DataView(k),m=2,n=l.byteLength-4,o=m;if(65496===l.getUint16(0)){for(;n>m&&(f=l.getUint16(m),f>=65504&&65519>=f||65534===f);){if(h=l.getUint16(m+2)+2,m+h>l.byteLength){console.log("Invalid meta data: Invalid segment size.");break}if(i=a.metaDataParsers.jpeg[f])for(j=0;j<i.length;j+=1)i[j].call(e,l,m,h,g,d);m+=h,o=m}!d.disableImageHead&&o>6&&(g.imageHead=k.slice?k.slice(0,o):new Uint8Array(k).subarray(0,o))}else console.log("Invalid JPEG file: Missing JPEG marker.");c(g)},"readAsArrayBuffer"))&&c(g)}}),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-meta"],a):a(window.loadImage)}(function(a){"use strict";a.ExifMap=function(){return this},a.ExifMap.prototype.map={Orientation:274},a.ExifMap.prototype.get=function(a){return this[a]||this[this.map[a]]},a.getExifThumbnail=function(a,b,c){var d,e,f;if(!c||b+c>a.byteLength)return void console.log("Invalid Exif data: Invalid thumbnail data.");for(d=[],e=0;c>e;e+=1)f=a.getUint8(b+e),d.push((16>f?"0":"")+f.toString(16));return"data:image/jpeg,%"+d.join("%")},a.exifTagTypes={1:{getValue:function(a,b){return a.getUint8(b)},size:1},2:{getValue:function(a,b){return String.fromCharCode(a.getUint8(b))},size:1,ascii:!0},3:{getValue:function(a,b,c){return a.getUint16(b,c)},size:2},4:{getValue:function(a,b,c){return a.getUint32(b,c)},size:4},5:{getValue:function(a,b,c){return a.getUint32(b,c)/a.getUint32(b+4,c)},size:8},9:{getValue:function(a,b,c){return a.getInt32(b,c)},size:4},10:{getValue:function(a,b,c){return a.getInt32(b,c)/a.getInt32(b+4,c)},size:8}},a.exifTagTypes[7]=a.exifTagTypes[1],a.getExifValue=function(b,c,d,e,f,g){var h,i,j,k,l,m,n=a.exifTagTypes[e];if(!n)return void console.log("Invalid Exif data: Invalid tag type.");if(h=n.size*f,i=h>4?c+b.getUint32(d+8,g):d+8,i+h>b.byteLength)return void console.log("Invalid Exif data: Invalid data offset.");if(1===f)return n.getValue(b,i,g);for(j=[],k=0;f>k;k+=1)j[k]=n.getValue(b,i+k*n.size,g);if(n.ascii){for(l="",k=0;k<j.length&&(m=j[k],"\x00"!==m);k+=1)l+=m;return l}return j},a.parseExifTag=function(b,c,d,e,f){var g=b.getUint16(d,e);f.exif[g]=a.getExifValue(b,c,d,b.getUint16(d+2,e),b.getUint32(d+4,e),e)},a.parseExifTags=function(a,b,c,d,e){var f,g,h;if(c+6>a.byteLength)return void console.log("Invalid Exif data: Invalid directory offset.");if(f=a.getUint16(c,d),g=c+2+12*f,g+4>a.byteLength)return void console.log("Invalid Exif data: Invalid directory size.");for(h=0;f>h;h+=1)this.parseExifTag(a,b,c+2+12*h,d,e);return a.getUint32(g,d)},a.parseExifData=function(b,c,d,e,f){if(!f.disableExif){var g,h,i,j=c+10;if(1165519206===b.getUint32(c+4)){if(j+8>b.byteLength)return void console.log("Invalid Exif data: Invalid segment size.");if(0!==b.getUint16(c+8))return void console.log("Invalid Exif data: Missing byte alignment offset.");switch(b.getUint16(j)){case 18761:g=!0;break;case 19789:g=!1;break;default:return void console.log("Invalid Exif data: Invalid byte alignment marker.")}if(42!==b.getUint16(j+2,g))return void console.log("Invalid Exif data: Missing TIFF marker.");h=b.getUint32(j+4,g),e.exif=new a.ExifMap,h=a.parseExifTags(b,j,j+h,g,e),h&&!f.disableExifThumbnail&&(i={exif:{}},h=a.parseExifTags(b,j,j+h,g,i),i.exif[513]&&(e.exif.Thumbnail=a.getExifThumbnail(b,j+i.exif[513],i.exif[514]))),e.exif[34665]&&!f.disableExifSub&&a.parseExifTags(b,j,j+e.exif[34665],g,e),e.exif[34853]&&!f.disableExifGps&&a.parseExifTags(b,j,j+e.exif[34853],g,e)}}},a.metaDataParsers.jpeg[65505].push(a.parseExifData)}),function(a){"use strict";"function"==typeof define&&define.amd?define(["load-image","load-image-exif"],a):a(window.loadImage)}(function(a){"use strict";a.ExifMap.prototype.tags={256:"ImageWidth",257:"ImageHeight",34665:"ExifIFDPointer",34853:"GPSInfoIFDPointer",40965:"InteroperabilityIFDPointer",258:"BitsPerSample",259:"Compression",262:"PhotometricInterpretation",274:"Orientation",277:"SamplesPerPixel",284:"PlanarConfiguration",530:"YCbCrSubSampling",531:"YCbCrPositioning",282:"XResolution",283:"YResolution",296:"ResolutionUnit",273:"StripOffsets",278:"RowsPerStrip",279:"StripByteCounts",513:"JPEGInterchangeFormat",514:"JPEGInterchangeFormatLength",301:"TransferFunction",318:"WhitePoint",319:"PrimaryChromaticities",529:"YCbCrCoefficients",532:"ReferenceBlackWhite",306:"DateTime",270:"ImageDescription",271:"Make",272:"Model",305:"Software",315:"Artist",33432:"Copyright",36864:"ExifVersion",40960:"FlashpixVersion",40961:"ColorSpace",40962:"PixelXDimension",40963:"PixelYDimension",42240:"Gamma",37121:"ComponentsConfiguration",37122:"CompressedBitsPerPixel",37500:"MakerNote",37510:"UserComment",40964:"RelatedSoundFile",36867:"DateTimeOriginal",36868:"DateTimeDigitized",37520:"SubSecTime",37521:"SubSecTimeOriginal",37522:"SubSecTimeDigitized",33434:"ExposureTime",33437:"FNumber",34850:"ExposureProgram",34852:"SpectralSensitivity",34855:"PhotographicSensitivity",34856:"OECF",34864:"SensitivityType",34865:"StandardOutputSensitivity",34866:"RecommendedExposureIndex",34867:"ISOSpeed",34868:"ISOSpeedLatitudeyyy",34869:"ISOSpeedLatitudezzz",37377:"ShutterSpeedValue",37378:"ApertureValue",37379:"BrightnessValue",37380:"ExposureBias",37381:"MaxApertureValue",37382:"SubjectDistance",37383:"MeteringMode",37384:"LightSource",37385:"Flash",37396:"SubjectArea",37386:"FocalLength",41483:"FlashEnergy",41484:"SpatialFrequencyResponse",41486:"FocalPlaneXResolution",41487:"FocalPlaneYResolution",41488:"FocalPlaneResolutionUnit",41492:"SubjectLocation",41493:"ExposureIndex",41495:"SensingMethod",41728:"FileSource",41729:"SceneType",41730:"CFAPattern",41985:"CustomRendered",41986:"ExposureMode",41987:"WhiteBalance",41988:"DigitalZoomRatio",41989:"FocalLengthIn35mmFilm",41990:"SceneCaptureType",41991:"GainControl",41992:"Contrast",41993:"Saturation",41994:"Sharpness",41995:"DeviceSettingDescription",41996:"SubjectDistanceRange",42016:"ImageUniqueID",42032:"CameraOwnerName",42033:"BodySerialNumber",42034:"LensSpecification",42035:"LensMake",42036:"LensModel",42037:"LensSerialNumber",0:"GPSVersionID",1:"GPSLatitudeRef",2:"GPSLatitude",3:"GPSLongitudeRef",4:"GPSLongitude",5:"GPSAltitudeRef",6:"GPSAltitude",7:"GPSTimeStamp",8:"GPSSatellites",9:"GPSStatus",10:"GPSMeasureMode",11:"GPSDOP",12:"GPSSpeedRef",13:"GPSSpeed",14:"GPSTrackRef",15:"GPSTrack",16:"GPSImgDirectionRef",17:"GPSImgDirection",18:"GPSMapDatum",19:"GPSDestLatitudeRef",20:"GPSDestLatitude",21:"GPSDestLongitudeRef",22:"GPSDestLongitude",23:"GPSDestBearingRef",24:"GPSDestBearing",25:"GPSDestDistanceRef",26:"GPSDestDistance",27:"GPSProcessingMethod",28:"GPSAreaInformation",29:"GPSDateStamp",30:"GPSDifferential",31:"GPSHPositioningError"},a.ExifMap.prototype.stringValues={ExposureProgram:{0:"Undefined",1:"Manual",2:"Normal program",3:"Aperture priority",4:"Shutter priority",5:"Creative program",6:"Action program",7:"Portrait mode",8:"Landscape mode"},MeteringMode:{0:"Unknown",1:"Average",2:"CenterWeightedAverage",3:"Spot",4:"MultiSpot",5:"Pattern",6:"Partial",255:"Other"},LightSource:{0:"Unknown",1:"Daylight",2:"Fluorescent",3:"Tungsten (incandescent light)",4:"Flash",9:"Fine weather",10:"Cloudy weather",11:"Shade",12:"Daylight fluorescent (D 5700 - 7100K)",13:"Day white fluorescent (N 4600 - 5400K)",14:"Cool white fluorescent (W 3900 - 4500K)",15:"White fluorescent (WW 3200 - 3700K)",17:"Standard light A",18:"Standard light B",19:"Standard light C",20:"D55",21:"D65",22:"D75",23:"D50",24:"ISO studio tungsten",255:"Other"},Flash:{0:"Flash did not fire",1:"Flash fired",5:"Strobe return light not detected",7:"Strobe return light detected",9:"Flash fired, compulsory flash mode",13:"Flash fired, compulsory flash mode, return light not detected",15:"Flash fired, compulsory flash mode, return light detected",16:"Flash did not fire, compulsory flash mode",24:"Flash did not fire, auto mode",25:"Flash fired, auto mode",29:"Flash fired, auto mode, return light not detected",31:"Flash fired, auto mode, return light detected",32:"No flash function",65:"Flash fired, red-eye reduction mode",69:"Flash fired, red-eye reduction mode, return light not detected",71:"Flash fired, red-eye reduction mode, return light detected",73:"Flash fired, compulsory flash mode, red-eye reduction mode",77:"Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected",79:"Flash fired, compulsory flash mode, red-eye reduction mode, return light detected",89:"Flash fired, auto mode, red-eye reduction mode",93:"Flash fired, auto mode, return light not detected, red-eye reduction mode",95:"Flash fired, auto mode, return light detected, red-eye reduction mode"},SensingMethod:{1:"Undefined",2:"One-chip color area sensor",3:"Two-chip color area sensor",4:"Three-chip color area sensor",5:"Color sequential area sensor",7:"Trilinear sensor",8:"Color sequential linear sensor"},SceneCaptureType:{0:"Standard",1:"Landscape",2:"Portrait",3:"Night scene"},SceneType:{1:"Directly photographed"},CustomRendered:{0:"Normal process",1:"Custom process"},WhiteBalance:{0:"Auto white balance",1:"Manual white balance"},GainControl:{0:"None",1:"Low gain up",2:"High gain up",3:"Low gain down",4:"High gain down"},Contrast:{0:"Normal",1:"Soft",2:"Hard"},Saturation:{0:"Normal",1:"Low saturation",2:"High saturation"},Sharpness:{0:"Normal",1:"Soft",2:"Hard"},SubjectDistanceRange:{0:"Unknown",1:"Macro",2:"Close view",3:"Distant view"},FileSource:{3:"DSC"},ComponentsConfiguration:{0:"",1:"Y",2:"Cb",3:"Cr",4:"R",5:"G",6:"B"},Orientation:{1:"top-left",2:"top-right",3:"bottom-right",4:"bottom-left",5:"left-top",6:"right-top",7:"right-bottom",8:"left-bottom"}},a.ExifMap.prototype.getText=function(a){var b=this.get(a);switch(a){case"LightSource":case"Flash":case"MeteringMode":case"ExposureProgram":case"SensingMethod":case"SceneCaptureType":case"SceneType":case"CustomRendered":case"WhiteBalance":case"GainControl":case"Contrast":case"Saturation":case"Sharpness":case"SubjectDistanceRange":case"FileSource":case"Orientation":return this.stringValues[a][b];case"ExifVersion":case"FlashpixVersion":return String.fromCharCode(b[0],b[1],b[2],b[3]);case"ComponentsConfiguration":return this.stringValues[a][b[0]]+this.stringValues[a][b[1]]+this.stringValues[a][b[2]]+this.stringValues[a][b[3]];case"GPSVersionID":return b[0]+"."+b[1]+"."+b[2]+"."+b[3]}return String(b)},function(a){var b,c=a.tags,d=a.map;for(b in c)c.hasOwnProperty(b)&&(d[c[b]]=b)}(a.ExifMap.prototype),a.ExifMap.prototype.getAll=function(){var a,b,c={};for(a in this)this.hasOwnProperty(a)&&(b=this.tags[a],b&&(c[b]=this.getText(b)));return c}});!function(a){"use strict";var b=function(a,c){var d=/[^\w\-\.:]/.test(a)?new Function(b.arg+",tmpl","var _e=tmpl.encode"+b.helper+",_s='"+a.replace(b.regexp,b.func)+"';return _s;"):b.cache[a]=b.cache[a]||b(b.load(a));return c?d(c,b):function(a){return d(a,b)}};b.cache={},b.load=function(a){return document.getElementById(a).innerHTML},b.regexp=/([\s'\\])(?!(?:[^{]|\{(?!%))*%\})|(?:\{%(=|#)([\s\S]+?)%\})|(\{%)|(%\})/g,b.func=function(a,b,c,d,e,f){return b?{"\n":"\\n","\r":"\\r"," ":"\\t"," ":" "}[b]||"\\"+b:c?"="===c?"'+_e("+d+")+'":"'+("+d+"==null?'':"+d+")+'":e?"';":f?"_s+='":void 0},b.encReg=/[<>&"'\x00]/g,b.encMap={"<":"<",">":">","&":"&",'"':""","'":"'"},b.encode=function(a){return(null==a?"":""+a).replace(b.encReg,function(a){return b.encMap[a]||""})},b.arg="o",b.helper=",print=function(s,e){_s+=e?(s==null?'':s):_e(s);},include=function(s,d){_s+=tmpl(s,d);}","function"==typeof define&&define.amd?define(function(){return b}):a.tmpl=b}(this);
\ No newline at end of file diff --git a/js/upload.min.js b/js/upload.min.js new file mode 100644 index 0000000..59f90ab --- /dev/null +++ b/js/upload.min.js @@ -0,0 +1 @@ +(function(e){"use strict";if(typeof define==="function"&&define.amd){define(["jquery"],e)}else{e(window.jQuery)}})(function(e){"use strict";var t=0;e.ajaxTransport("iframe",function(n){if(n.async){var r=n.initialIframeSrc||"javascript:false;",i,s,o;return{send:function(u,a){i=e('<form style="display:none;"></form>');i.attr("accept-charset",n.formAcceptCharset);o=/\?/.test(n.url)?"&":"?";if(n.type==="DELETE"){n.url=n.url+o+"_method=DELETE";n.type="POST"}else if(n.type==="PUT"){n.url=n.url+o+"_method=PUT";n.type="POST"}else if(n.type==="PATCH"){n.url=n.url+o+"_method=PATCH";n.type="POST"}t+=1;s=e('<iframe src="'+r+'" name="iframe-transport-'+t+'"></iframe>').bind("load",function(){var t,o=e.isArray(n.paramName)?n.paramName:[n.paramName];s.unbind("load").bind("load",function(){var t;try{t=s.contents();if(!t.length||!t[0].firstChild){throw new Error}}catch(n){t=undefined}a(200,"success",{iframe:t});e('<iframe src="'+r+'"></iframe>').appendTo(i);window.setTimeout(function(){i.remove()},0)});i.prop("target",s.prop("name")).prop("action",n.url).prop("method",n.type);if(n.formData){e.each(n.formData,function(t,n){e('<input type="hidden"/>').prop("name",n.name).val(n.value).appendTo(i)})}if(n.fileInput&&n.fileInput.length&&n.type==="POST"){t=n.fileInput.clone();n.fileInput.after(function(e){return t[e]});if(n.paramName){n.fileInput.each(function(t){e(this).prop("name",o[t]||n.paramName)})}i.append(n.fileInput).prop("enctype","multipart/form-data").prop("encoding","multipart/form-data");n.fileInput.removeAttr("form")}i.submit();if(t&&t.length){n.fileInput.each(function(n,r){var i=e(t[n]);e(r).prop("name",i.prop("name")).attr("form",i.attr("form"));i.replaceWith(r)})}});i.append(s).appendTo(document.body)},abort:function(){if(s){s.unbind("load").prop("src",r)}if(i){i.remove()}}}}});e.ajaxSetup({converters:{"iframe text":function(t){return t&&e(t[0].body).text()},"iframe json":function(t){return t&&e.parseJSON(e(t[0].body).text())},"iframe html":function(t){return t&&e(t[0].body).html()},"iframe xml":function(t){var n=t&&t[0];return n&&e.isXMLDoc(n)?n:e.parseXML(n.XMLDocument&&n.XMLDocument.xml||e(n.body).html())},"iframe script":function(t){return t&&e.globalEval(e(t[0].body).text())}}})});(function(e){"use strict";if(typeof define==="function"&&define.amd){define(["jquery","jquery.ui.widget"],e)}else{e(window.jQuery)}})(function(e){"use strict";function t(t){var n=t==="dragover";return function(r){r.dataTransfer=r.originalEvent&&r.originalEvent.dataTransfer;var i=r.dataTransfer;if(i&&e.inArray("Files",i.types)!==-1&&this._trigger(t,e.Event(t,{delegatedEvent:r}))!==false){r.preventDefault();if(n){i.dropEffect="copy"}}}}e.support.fileInput=!((new RegExp("(Android (1\\.[0156]|2\\.[01]))"+"|(Windows Phone (OS 7|8\\.0))|(XBLWP)|(ZuneWP)|(WPDesktop)"+"|(w(eb)?OSBrowser)|(webOS)"+"|(Kindle/(1\\.0|2\\.[05]|3\\.0))")).test(window.navigator.userAgent)||e('<input type="file">').prop("disabled"));e.support.xhrFileUpload=!!(window.ProgressEvent&&window.FileReader);e.support.xhrFormDataFileUpload=!!window.FormData;e.support.blobSlice=window.Blob&&(Blob.prototype.slice||Blob.prototype.webkitSlice||Blob.prototype.mozSlice);e.widget("blueimp.fileupload",{options:{dropZone:e(document),pasteZone:undefined,fileInput:undefined,replaceFileInput:true,paramName:undefined,singleFileUploads:true,limitMultiFileUploads:undefined,limitMultiFileUploadSize:undefined,limitMultiFileUploadSizeOverhead:512,sequentialUploads:false,limitConcurrentUploads:undefined,forceIframeTransport:false,redirect:undefined,redirectParamName:undefined,postMessage:undefined,multipart:true,maxChunkSize:undefined,uploadedBytes:undefined,recalculateProgress:true,progressInterval:100,bitrateInterval:500,autoUpload:true,messages:{uploadedBytes:"Uploaded bytes exceed file size"},i18n:function(t,n){t=this.messages[t]||t.toString();if(n){e.each(n,function(e,n){t=t.replace("{"+e+"}",n)})}return t},formData:function(e){return e.serializeArray()},add:function(t,n){if(t.isDefaultPrevented()){return false}if(n.autoUpload||n.autoUpload!==false&&e(this).fileupload("option","autoUpload")){n.process().done(function(){n.submit()})}},processData:false,contentType:false,cache:false},_specialOptions:["fileInput","dropZone","pasteZone","multipart","forceIframeTransport"],_blobSlice:e.support.blobSlice&&function(){var e=this.slice||this.webkitSlice||this.mozSlice;return e.apply(this,arguments)},_BitrateTimer:function(){this.timestamp=Date.now?Date.now():(new Date).getTime();this.loaded=0;this.bitrate=0;this.getBitrate=function(e,t,n){var r=e-this.timestamp;if(!this.bitrate||!n||r>n){this.bitrate=(t-this.loaded)*(1e3/r)*8;this.loaded=t;this.timestamp=e}return this.bitrate}},_isXHRUpload:function(t){return!t.forceIframeTransport&&(!t.multipart&&e.support.xhrFileUpload||e.support.xhrFormDataFileUpload)},_getFormData:function(t){var n;if(e.type(t.formData)==="function"){return t.formData(t.form)}if(e.isArray(t.formData)){return t.formData}if(e.type(t.formData)==="object"){n=[];e.each(t.formData,function(e,t){n.push({name:e,value:t})});return n}return[]},_getTotal:function(t){var n=0;e.each(t,function(e,t){n+=t.size||1});return n},_initProgressObject:function(t){var n={loaded:0,total:0,bitrate:0};if(t._progress){e.extend(t._progress,n)}else{t._progress=n}},_initResponseObject:function(e){var t;if(e._response){for(t in e._response){if(e._response.hasOwnProperty(t)){delete e._response[t]}}}else{e._response={}}},_onProgress:function(t,n){if(t.lengthComputable){var r=Date.now?Date.now():(new Date).getTime(),i;if(n._time&&n.progressInterval&&r-n._time<n.progressInterval&&t.loaded!==t.total){return}n._time=r;i=Math.floor(t.loaded/t.total*(n.chunkSize||n._progress.total))+(n.uploadedBytes||0);this._progress.loaded+=i-n._progress.loaded;this._progress.bitrate=this._bitrateTimer.getBitrate(r,this._progress.loaded,n.bitrateInterval);n._progress.loaded=n.loaded=i;n._progress.bitrate=n.bitrate=n._bitrateTimer.getBitrate(r,i,n.bitrateInterval);this._trigger("progress",e.Event("progress",{delegatedEvent:t}),n);this._trigger("progressall",e.Event("progressall",{delegatedEvent:t}),this._progress)}},_initProgressListener:function(t){var n=this,r=t.xhr?t.xhr():e.ajaxSettings.xhr();if(r.upload){e(r.upload).bind("progress",function(e){var r=e.originalEvent;e.lengthComputable=r.lengthComputable;e.loaded=r.loaded;e.total=r.total;n._onProgress(e,t)});t.xhr=function(){return r}}},_isInstanceOf:function(e,t){return Object.prototype.toString.call(t)==="[object "+e+"]"},_initXHRData:function(t){var n=this,r,i=t.files[0],s=t.multipart||!e.support.xhrFileUpload,o=e.type(t.paramName)==="array"?t.paramName[0]:t.paramName;t.headers=e.extend({},t.headers);if(t.contentRange){t.headers["Content-Range"]=t.contentRange}if(!s||t.blob||!this._isInstanceOf("File",i)){t.headers["Content-Disposition"]='attachment; filename="'+encodeURI(i.name)+'"'}if(!s){t.contentType=i.type||"application/octet-stream";t.data=t.blob||i}else if(e.support.xhrFormDataFileUpload){if(t.postMessage){r=this._getFormData(t);if(t.blob){r.push({name:o,value:t.blob})}else{e.each(t.files,function(n,i){r.push({name:e.type(t.paramName)==="array"&&t.paramName[n]||o,value:i})})}}else{if(n._isInstanceOf("FormData",t.formData)){r=t.formData}else{r=new FormData;e.each(this._getFormData(t),function(e,t){r.append(t.name,t.value)})}if(t.blob){r.append(o,t.blob,i.name)}else{e.each(t.files,function(i,s){if(n._isInstanceOf("File",s)||n._isInstanceOf("Blob",s)){r.append(e.type(t.paramName)==="array"&&t.paramName[i]||o,s,s.uploadName||s.name)}})}}t.data=r}t.blob=null},_initIframeSettings:function(t){var n=e("<a></a>").prop("href",t.url).prop("host");t.dataType="iframe "+(t.dataType||"");t.formData=this._getFormData(t);if(t.redirect&&n&&n!==location.host){t.formData.push({name:t.redirectParamName||"redirect",value:t.redirect})}},_initDataSettings:function(e){if(this._isXHRUpload(e)){if(!this._chunkedUpload(e,true)){if(!e.data){this._initXHRData(e)}this._initProgressListener(e)}if(e.postMessage){e.dataType="postmessage "+(e.dataType||"")}}else{this._initIframeSettings(e)}},_getParamName:function(t){var n=e(t.fileInput),r=t.paramName;if(!r){r=[];n.each(function(){var t=e(this),n=t.prop("name")||"files[]",i=(t.prop("files")||[1]).length;while(i){r.push(n);i-=1}});if(!r.length){r=[n.prop("name")||"files[]"]}}else if(!e.isArray(r)){r=[r]}return r},_initFormSettings:function(t){if(!t.form||!t.form.length){t.form=e(t.fileInput.prop("form"));if(!t.form.length){t.form=e(this.options.fileInput.prop("form"))}}t.paramName=this._getParamName(t);if(!t.url){t.url=t.form.prop("action")||location.href}t.type=(t.type||e.type(t.form.prop("method"))==="string"&&t.form.prop("method")||"").toUpperCase();if(t.type!=="POST"&&t.type!=="PUT"&&t.type!=="PATCH"){t.type="POST"}if(!t.formAcceptCharset){t.formAcceptCharset=t.form.attr("accept-charset")}},_getAJAXSettings:function(t){var n=e.extend({},this.options,t);this._initFormSettings(n);this._initDataSettings(n);return n},_getDeferredState:function(e){if(e.state){return e.state()}if(e.isResolved()){return"resolved"}if(e.isRejected()){return"rejected"}return"pending"},_enhancePromise:function(e){e.success=e.done;e.error=e.fail;e.complete=e.always;return e},_getXHRPromise:function(t,n,r){var i=e.Deferred(),s=i.promise();n=n||this.options.context||s;if(t===true){i.resolveWith(n,r)}else if(t===false){i.rejectWith(n,r)}s.abort=i.promise;return this._enhancePromise(s)},_addConvenienceMethods:function(t,n){var r=this,i=function(t){return e.Deferred().resolveWith(r,t).promise()};n.process=function(t,s){if(t||s){n._processQueue=this._processQueue=(this._processQueue||i([this])).pipe(function(){if(n.errorThrown){return e.Deferred().rejectWith(r,[n]).promise()}return i(arguments)}).pipe(t,s)}return this._processQueue||i([this])};n.submit=function(){if(this.state()!=="pending"){n.jqXHR=this.jqXHR=r._trigger("submit",e.Event("submit",{delegatedEvent:t}),this)!==false&&r._onSend(t,this)}return this.jqXHR||r._getXHRPromise()};n.abort=function(){if(this.jqXHR){return this.jqXHR.abort()}this.errorThrown="abort";r._trigger("fail",null,this);return r._getXHRPromise(false)};n.state=function(){if(this.jqXHR){return r._getDeferredState(this.jqXHR)}if(this._processQueue){return r._getDeferredState(this._processQueue)}};n.processing=function(){return!this.jqXHR&&this._processQueue&&r._getDeferredState(this._processQueue)==="pending"};n.progress=function(){return this._progress};n.response=function(){return this._response}},_getUploadedBytes:function(e){var t=e.getResponseHeader("Range"),n=t&&t.split("-"),r=n&&n.length>1&&parseInt(n[1],10);return r&&r+1},_chunkedUpload:function(t,n){t.uploadedBytes=t.uploadedBytes||0;var r=this,i=t.files[0],s=i.size,o=t.uploadedBytes,u=t.maxChunkSize||s,a=this._blobSlice,f=e.Deferred(),l=f.promise(),c,h;if(!(this._isXHRUpload(t)&&a&&(o||u<s))||t.data){return false}if(n){return true}if(o>=s){i.error=t.i18n("uploadedBytes");return this._getXHRPromise(false,t.context,[null,"error",i.error])}h=function(){var n=e.extend({},t),l=n._progress.loaded;n.blob=a.call(i,o,o+u,i.type);n.chunkSize=n.blob.size;n.contentRange="bytes "+o+"-"+(o+n.chunkSize-1)+"/"+s;r._initXHRData(n);r._initProgressListener(n);c=(r._trigger("chunksend",null,n)!==false&&e.ajax(n)||r._getXHRPromise(false,n.context)).done(function(i,u,a){o=r._getUploadedBytes(a)||o+n.chunkSize;if(l+n.chunkSize-n._progress.loaded){r._onProgress(e.Event("progress",{lengthComputable:true,loaded:o-n.uploadedBytes,total:o-n.uploadedBytes}),n)}t.uploadedBytes=n.uploadedBytes=o;n.result=i;n.textStatus=u;n.jqXHR=a;r._trigger("chunkdone",null,n);r._trigger("chunkalways",null,n);if(o<s){h()}else{f.resolveWith(n.context,[i,u,a])}}).fail(function(e,t,i){n.jqXHR=e;n.textStatus=t;n.errorThrown=i;r._trigger("chunkfail",null,n);r._trigger("chunkalways",null,n);f.rejectWith(n.context,[e,t,i])})};this._enhancePromise(l);l.abort=function(){return c.abort()};h();return l},_beforeSend:function(e,t){if(this._active===0){this._trigger("start");this._bitrateTimer=new this._BitrateTimer;this._progress.loaded=this._progress.total=0;this._progress.bitrate=0}this._initResponseObject(t);this._initProgressObject(t);t._progress.loaded=t.loaded=t.uploadedBytes||0;t._progress.total=t.total=this._getTotal(t.files)||1;t._progress.bitrate=t.bitrate=0;this._active+=1;this._progress.loaded+=t.loaded;this._progress.total+=t.total},_onDone:function(t,n,r,i){var s=i._progress.total,o=i._response;if(i._progress.loaded<s){this._onProgress(e.Event("progress",{lengthComputable:true,loaded:s,total:s}),i)}o.result=i.result=t;o.textStatus=i.textStatus=n;o.jqXHR=i.jqXHR=r;this._trigger("done",null,i)},_onFail:function(e,t,n,r){var i=r._response;if(r.recalculateProgress){this._progress.loaded-=r._progress.loaded;this._progress.total-=r._progress.total}i.jqXHR=r.jqXHR=e;i.textStatus=r.textStatus=t;i.errorThrown=r.errorThrown=n;this._trigger("fail",null,r)},_onAlways:function(e,t,n,r){this._trigger("always",null,r)},_onSend:function(t,n){if(!n.submit){this._addConvenienceMethods(t,n)}var r=this,i,s,o,u,a=r._getAJAXSettings(n),f=function(){r._sending+=1;a._bitrateTimer=new r._BitrateTimer;i=i||((s||r._trigger("send",e.Event("send",{delegatedEvent:t}),a)===false)&&r._getXHRPromise(false,a.context,s)||r._chunkedUpload(a)||e.ajax(a)).done(function(e,t,n){r._onDone(e,t,n,a)}).fail(function(e,t,n){r._onFail(e,t,n,a)}).always(function(e,t,n){r._onAlways(e,t,n,a);r._sending-=1;r._active-=1;if(a.limitConcurrentUploads&&a.limitConcurrentUploads>r._sending){var i=r._slots.shift();while(i){if(r._getDeferredState(i)==="pending"){i.resolve();break}i=r._slots.shift()}}if(r._active===0){r._trigger("stop")}});return i};this._beforeSend(t,a);if(this.options.sequentialUploads||this.options.limitConcurrentUploads&&this.options.limitConcurrentUploads<=this._sending){if(this.options.limitConcurrentUploads>1){o=e.Deferred();this._slots.push(o);u=o.pipe(f)}else{this._sequence=this._sequence.pipe(f,f);u=this._sequence}u.abort=function(){s=[undefined,"abort","abort"];if(!i){if(o){o.rejectWith(a.context,s)}return f()}return i.abort()};return this._enhancePromise(u)}return f()},_onAdd:function(t,n){var r=this,i=true,s=e.extend({},this.options,n),o=n.files,u=o.length,a=s.limitMultiFileUploads,f=s.limitMultiFileUploadSize,l=s.limitMultiFileUploadSizeOverhead,c=0,h=this._getParamName(s),p,d,v,m,g=0;if(f&&(!u||o[0].size===undefined)){f=undefined}if(!(s.singleFileUploads||a||f)||!this._isXHRUpload(s)){v=[o];p=[h]}else if(!(s.singleFileUploads||f)&&a){v=[];p=[];for(m=0;m<u;m+=a){v.push(o.slice(m,m+a));d=h.slice(m,m+a);if(!d.length){d=h}p.push(d)}}else if(!s.singleFileUploads&&f){v=[];p=[];for(m=0;m<u;m=m+1){c+=o[m].size+l;if(m+1===u||c+o[m+1].size+l>f||a&&m+1-g>=a){v.push(o.slice(g,m+1));d=h.slice(g,m+1);if(!d.length){d=h}p.push(d);g=m+1;c=0}}}else{p=h}n.originalFiles=o;e.each(v||o,function(s,o){var u=e.extend({},n);u.files=v?o:[o];u.paramName=p[s];r._initResponseObject(u);r._initProgressObject(u);r._addConvenienceMethods(t,u);i=r._trigger("add",e.Event("add",{delegatedEvent:t}),u);return i});return i},_replaceFileInput:function(t){var n=t.fileInput,r=n.clone(true);t.fileInputClone=r;e("<form></form>").append(r)[0].reset();n.after(r).detach();e.cleanData(n.unbind("remove"));this.options.fileInput=this.options.fileInput.map(function(e,t){if(t===n[0]){return r[0]}return t});if(n[0]===this.element[0]){this.element=r}},_handleFileTreeEntry:function(t,n){var r=this,i=e.Deferred(),s=function(e){if(e&&!e.entry){e.entry=t}i.resolve([e])},o=function(e){r._handleFileTreeEntries(e,n+t.name+"/").done(function(e){i.resolve(e)}).fail(s)},u=function(){a.readEntries(function(e){if(!e.length){o(f)}else{f=f.concat(e);u()}},s)},a,f=[];n=n||"";if(t.isFile){if(t._file){t._file.relativePath=n;i.resolve(t._file)}else{t.file(function(e){e.relativePath=n;i.resolve(e)},s)}}else if(t.isDirectory){a=t.createReader();u()}else{i.resolve([])}return i.promise()},_handleFileTreeEntries:function(t,n){var r=this;return e.when.apply(e,e.map(t,function(e){return r._handleFileTreeEntry(e,n)})).pipe(function(){return Array.prototype.concat.apply([],arguments)})},_getDroppedFiles:function(t){t=t||{};var n=t.items;if(n&&n.length&&(n[0].webkitGetAsEntry||n[0].getAsEntry)){return this._handleFileTreeEntries(e.map(n,function(e){var t;if(e.webkitGetAsEntry){t=e.webkitGetAsEntry();if(t){t._file=e.getAsFile()}return t}return e.getAsEntry()}))}return e.Deferred().resolve(e.makeArray(t.files)).promise()},_getSingleFileInputFiles:function(t){t=e(t);var n=t.prop("webkitEntries")||t.prop("entries"),r,i;if(n&&n.length){return this._handleFileTreeEntries(n)}r=e.makeArray(t.prop("files"));if(!r.length){i=t.prop("value");if(!i){return e.Deferred().resolve([]).promise()}r=[{name:i.replace(/^.*\\/,"")}]}else if(r[0].name===undefined&&r[0].fileName){e.each(r,function(e,t){t.name=t.fileName;t.size=t.fileSize})}return e.Deferred().resolve(r).promise()},_getFileInputFiles:function(t){if(!(t instanceof e)||t.length===1){return this._getSingleFileInputFiles(t)}return e.when.apply(e,e.map(t,this._getSingleFileInputFiles)).pipe(function(){return Array.prototype.concat.apply([],arguments)})},_onChange:function(t){var n=this,r={fileInput:e(t.target),form:e(t.target.form)};this._getFileInputFiles(r.fileInput).always(function(i){r.files=i;if(n.options.replaceFileInput){n._replaceFileInput(r)}if(n._trigger("change",e.Event("change",{delegatedEvent:t}),r)!==false){n._onAdd(t,r)}})},_onPaste:function(t){var n=t.originalEvent&&t.originalEvent.clipboardData&&t.originalEvent.clipboardData.items,r={files:[]};if(n&&n.length){e.each(n,function(e,t){var n=t.getAsFile&&t.getAsFile();if(n){r.files.push(n)}});if(this._trigger("paste",e.Event("paste",{delegatedEvent:t}),r)!==false){this._onAdd(t,r)}}},_onDrop:function(t){t.dataTransfer=t.originalEvent&&t.originalEvent.dataTransfer;var n=this,r=t.dataTransfer,i={};if(r&&r.files&&r.files.length){t.preventDefault();this._getDroppedFiles(r).always(function(r){i.files=r;if(n._trigger("drop",e.Event("drop",{delegatedEvent:t}),i)!==false){n._onAdd(t,i)}})}},_onDragOver:t("dragover"),_onDragEnter:t("dragenter"),_onDragLeave:t("dragleave"),_initEventHandlers:function(){if(this._isXHRUpload(this.options)){this._on(this.options.dropZone,{dragover:this._onDragOver,drop:this._onDrop,dragenter:this._onDragEnter,dragleave:this._onDragLeave});this._on(this.options.pasteZone,{paste:this._onPaste})}if(e.support.fileInput){this._on(this.options.fileInput,{change:this._onChange})}},_destroyEventHandlers:function(){this._off(this.options.dropZone,"dragenter dragleave dragover drop");this._off(this.options.pasteZone,"paste");this._off(this.options.fileInput,"change")},_setOption:function(t,n){var r=e.inArray(t,this._specialOptions)!==-1;if(r){this._destroyEventHandlers()}this._super(t,n);if(r){this._initSpecialOptions();this._initEventHandlers()}},_initSpecialOptions:function(){var t=this.options;if(t.fileInput===undefined){t.fileInput=this.element.is('input[type="file"]')?this.element:this.element.find('input[type="file"]')}else if(!(t.fileInput instanceof e)){t.fileInput=e(t.fileInput)}if(!(t.dropZone instanceof e)){t.dropZone=e(t.dropZone)}if(!(t.pasteZone instanceof e)){t.pasteZone=e(t.pasteZone)}},_getRegExp:function(e){var t=e.split("/"),n=t.pop();t.shift();return new RegExp(t.join("/"),n)},_isRegExpOption:function(t,n){return t!=="url"&&e.type(n)==="string"&&/^\/.*\/[igm]{0,3}$/.test(n)},_initDataAttributes:function(){var t=this,n=this.options,r=e(this.element[0].cloneNode(false));e.each(r.data(),function(e,i){var s="data-"+e.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();if(r.attr(s)){if(t._isRegExpOption(e,i)){i=t._getRegExp(i)}n[e]=i}})},_create:function(){this._initDataAttributes();this._initSpecialOptions();this._slots=[];this._sequence=this._getXHRPromise(true);this._sending=this._active=0;this._initProgressObject(this);this._initEventHandlers()},active:function(){return this._active},progress:function(){return this._progress},add:function(t){var n=this;if(!t||this.options.disabled){return}if(t.fileInput&&!t.files){this._getFileInputFiles(t.fileInput).always(function(e){t.files=e;n._onAdd(null,t)})}else{t.files=e.makeArray(t.files);this._onAdd(null,t)}},send:function(t){if(t&&!this.options.disabled){if(t.fileInput&&!t.files){var n=this,r=e.Deferred(),i=r.promise(),s,o;i.abort=function(){o=true;if(s){return s.abort()}r.reject(null,"abort","abort");return i};this._getFileInputFiles(t.fileInput).always(function(e){if(o){return}if(!e.length){r.reject();return}t.files=e;s=n._onSend(null,t);s.then(function(e,t,n){r.resolve(e,t,n)},function(e,t,n){r.reject(e,t,n)})});return this._enhancePromise(i)}t.files=e.makeArray(t.files);if(t.files.length){return this._onSend(null,t)}}return this._getXHRPromise(false,t&&t.context)}})});(function(e){"use strict";if(typeof define==="function"&&define.amd){define(["jquery","./jquery.fileupload"],e)}else{e(window.jQuery)}})(function(e){"use strict";var t=e.blueimp.fileupload.prototype.options.add;e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{processQueue:[],add:function(n,r){var i=e(this);r.process(function(){return i.fileupload("process",r)});t.call(this,n,r)}},processActions:{},_processFile:function(t,n){var r=this,i=e.Deferred().resolveWith(r,[t]),s=i.promise();this._trigger("process",null,t);e.each(t.processQueue,function(t,i){var o=function(t){if(n.errorThrown){return e.Deferred().rejectWith(r,[n]).promise()}return r.processActions[i.action].call(r,t,i)};s=s.pipe(o,i.always&&o)});s.done(function(){r._trigger("processdone",null,t);r._trigger("processalways",null,t)}).fail(function(){r._trigger("processfail",null,t);r._trigger("processalways",null,t)});return s},_transformProcessQueue:function(t){var n=[];e.each(t.processQueue,function(){var r={},i=this.action,s=this.prefix===true?i:this.prefix;e.each(this,function(n,i){if(e.type(i)==="string"&&i.charAt(0)==="@"){r[n]=t[i.slice(1)||(s?s+n.charAt(0).toUpperCase()+n.slice(1):n)]}else{r[n]=i}});n.push(r)});t.processQueue=n},processing:function(){return this._processing},process:function(t){var n=this,r=e.extend({},this.options,t);if(r.processQueue&&r.processQueue.length){this._transformProcessQueue(r);if(this._processing===0){this._trigger("processstart")}e.each(t.files,function(i){var s=i?e.extend({},r):r,o=function(){if(t.errorThrown){return e.Deferred().rejectWith(n,[t]).promise()}return n._processFile(s,t)};s.index=i;n._processing+=1;n._processingQueue=n._processingQueue.pipe(o,o).always(function(){n._processing-=1;if(n._processing===0){n._trigger("processstop")}})})}return this._processingQueue},_create:function(){this._super();this._processing=0;this._processingQueue=e.Deferred().resolveWith(this).promise()}})});(function(e){"use strict";if(typeof define==="function"&&define.amd){define(["jquery","load-image","load-image-meta","load-image-exif","load-image-ios","canvas-to-blob","./jquery.fileupload-process"],e)}else{e(window.jQuery,window.loadImage)}})(function(e,t){"use strict";e.blueimp.fileupload.prototype.options.processQueue.unshift({action:"loadImageMetaData",disableImageHead:"@",disableExif:"@",disableExifThumbnail:"@",disableExifSub:"@",disableExifGps:"@",disabled:"@disableImageMetaDataLoad"},{action:"loadImage",prefix:true,fileTypes:"@",maxFileSize:"@",noRevoke:"@",disabled:"@disableImageLoad"},{action:"resizeImage",prefix:"image",maxWidth:"@",maxHeight:"@",minWidth:"@",minHeight:"@",crop:"@",orientation:"@",forceResize:"@",disabled:"@disableImageResize"},{action:"saveImage",quality:"@imageQuality",type:"@imageType",disabled:"@disableImageResize"},{action:"saveImageMetaData",disabled:"@disableImageMetaDataSave"},{action:"resizeImage",prefix:"preview",maxWidth:"@",maxHeight:"@",minWidth:"@",minHeight:"@",crop:"@",orientation:"@",thumbnail:"@",canvas:"@",disabled:"@disableImagePreview"},{action:"setImage",name:"@imagePreviewName",disabled:"@disableImagePreview"},{action:"deleteImageReferences",disabled:"@disableImageReferencesDeletion"});e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{loadImageFileTypes:/^image\/(gif|jpeg|png|svg\+xml)$/,loadImageMaxFileSize:1e7,imageMaxWidth:1920,imageMaxHeight:1080,imageOrientation:false,imageCrop:false,disableImageResize:true,previewMaxWidth:80,previewMaxHeight:80,previewOrientation:true,previewThumbnail:true,previewCrop:false,previewCanvas:true},processActions:{loadImage:function(n,r){if(r.disabled){return n}var i=this,s=n.files[n.index],o=e.Deferred();if(e.type(r.maxFileSize)==="number"&&s.size>r.maxFileSize||r.fileTypes&&!r.fileTypes.test(s.type)||!t(s,function(e){if(e.src){n.img=e}o.resolveWith(i,[n])},r)){return n}return o.promise()},resizeImage:function(n,r){if(r.disabled||!(n.canvas||n.img)){return n}r=e.extend({canvas:true},r);var i=this,s=e.Deferred(),o=r.canvas&&n.canvas||n.img,u=function(e){if(e&&(e.width!==o.width||e.height!==o.height||r.forceResize)){n[e.getContext?"canvas":"img"]=e}n.preview=e;s.resolveWith(i,[n])},a;if(n.exif){if(r.orientation===true){r.orientation=n.exif.get("Orientation")}if(r.thumbnail){a=n.exif.get("Thumbnail");if(a){t(a,u,r);return s.promise()}}if(n.orientation){delete r.orientation}else{n.orientation=r.orientation}}if(o){u(t.scale(o,r));return s.promise()}return n},saveImage:function(t,n){if(!t.canvas||n.disabled){return t}var r=this,i=t.files[t.index],s=e.Deferred();if(t.canvas.toBlob){t.canvas.toBlob(function(e){if(!e.name){if(i.type===e.type){e.name=i.name}else if(i.name){e.name=i.name.replace(/\..+$/,"."+e.type.substr(6))}}if(i.type!==e.type){delete t.imageHead}t.files[t.index]=e;s.resolveWith(r,[t])},n.type||i.type,n.quality)}else{return t}return s.promise()},loadImageMetaData:function(n,r){if(r.disabled){return n}var i=this,s=e.Deferred();t.parseMetaData(n.files[n.index],function(t){e.extend(n,t);s.resolveWith(i,[n])},r);return s.promise()},saveImageMetaData:function(e,t){if(!(e.imageHead&&e.canvas&&e.canvas.toBlob&&!t.disabled)){return e}var n=e.files[e.index],r=new Blob([e.imageHead,this._blobSlice.call(n,20)],{type:n.type});r.name=n.name;e.files[e.index]=r;return e},setImage:function(e,t){if(e.preview&&!t.disabled){e.files[e.index][t.name||"preview"]=e.preview}return e},deleteImageReferences:function(e,t){if(!t.disabled){delete e.img;delete e.canvas;delete e.preview;delete e.imageHead}return e}}})});(function(e){"use strict";if(typeof define==="function"&&define.amd){define(["jquery","load-image","./jquery.fileupload-process"],e)}else{e(window.jQuery,window.loadImage)}})(function(e,t){"use strict";e.blueimp.fileupload.prototype.options.processQueue.unshift({action:"loadAudio",prefix:true,fileTypes:"@",maxFileSize:"@",disabled:"@disableAudioPreview"},{action:"setAudio",name:"@audioPreviewName",disabled:"@disableAudioPreview"});e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{loadAudioFileTypes:/^audio\/.*$/},_audioElement:document.createElement("audio"),processActions:{loadAudio:function(n,r){if(r.disabled){return n}var i=n.files[n.index],s,o;if(this._audioElement.canPlayType&&this._audioElement.canPlayType(i.type)&&(e.type(r.maxFileSize)!=="number"||i.size<=r.maxFileSize)&&(!r.fileTypes||r.fileTypes.test(i.type))){s=t.createObjectURL(i);if(s){o=this._audioElement.cloneNode(false);o.src=s;o.controls=true;n.audio=o;return n}}return n},setAudio:function(e,t){if(e.audio&&!t.disabled){e.files[e.index][t.name||"preview"]=e.audio}return e}}})});(function(e){"use strict";if(typeof define==="function"&&define.amd){define(["jquery","load-image","./jquery.fileupload-process"],e)}else{e(window.jQuery,window.loadImage)}})(function(e,t){"use strict";e.blueimp.fileupload.prototype.options.processQueue.unshift({action:"loadVideo",prefix:true,fileTypes:"@",maxFileSize:"@",disabled:"@disableVideoPreview"},{action:"setVideo",name:"@videoPreviewName",disabled:"@disableVideoPreview"});e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{loadVideoFileTypes:/^video\/.*$/},_videoElement:document.createElement("video"),processActions:{loadVideo:function(n,r){if(r.disabled){return n}var i=n.files[n.index],s,o;if(this._videoElement.canPlayType&&this._videoElement.canPlayType(i.type)&&(e.type(r.maxFileSize)!=="number"||i.size<=r.maxFileSize)&&(!r.fileTypes||r.fileTypes.test(i.type))){s=t.createObjectURL(i);if(s){o=this._videoElement.cloneNode(false);o.src=s;o.controls=true;n.video=o;return n}}return n},setVideo:function(e,t){if(e.video&&!t.disabled){e.files[e.index][t.name||"preview"]=e.video}return e}}})});(function(e){"use strict";if(typeof define==="function"&&define.amd){define(["jquery","./jquery.fileupload-process"],e)}else{e(window.jQuery)}})(function(e){"use strict";e.blueimp.fileupload.prototype.options.processQueue.push({action:"validate",always:true,acceptFileTypes:"@",maxFileSize:"@",minFileSize:"@",maxNumberOfFiles:"@",disabled:"@disableValidation"});e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{getNumberOfFiles:e.noop,messages:{maxNumberOfFiles:"Maximum number of files exceeded",acceptFileTypes:"File type not allowed",maxFileSize:"File is too large",minFileSize:"File is too small"}},processActions:{validate:function(t,n){if(n.disabled){return t}var r=e.Deferred(),i=this.options,s=t.files[t.index],o;if(n.minFileSize||n.maxFileSize){o=s.size}if(e.type(n.maxNumberOfFiles)==="number"&&(i.getNumberOfFiles()||0)+t.files.length>n.maxNumberOfFiles){s.error=i.i18n("maxNumberOfFiles")}else if(n.acceptFileTypes&&!(n.acceptFileTypes.test(s.type)||n.acceptFileTypes.test(s.name))){s.error=i.i18n("acceptFileTypes")}else if(o>n.maxFileSize){s.error=i.i18n("maxFileSize")}else if(e.type(o)==="number"&&o<n.minFileSize){s.error=i.i18n("minFileSize")}else{delete s.error}if(s.error||t.files.error){t.files.error=true;r.rejectWith(this,[t])}else{r.resolveWith(this,[t])}return r.promise()}}})});(function(e){"use strict";if(typeof define==="function"&&define.amd){define(["jquery","tmpl","./jquery.fileupload-image","./jquery.fileupload-audio","./jquery.fileupload-video","./jquery.fileupload-validate"],e)}else{e(window.jQuery,window.tmpl)}})(function(e,t){"use strict";e.blueimp.fileupload.prototype._specialOptions.push("filesContainer","uploadTemplateId","downloadTemplateId");e.widget("blueimp.fileupload",e.blueimp.fileupload,{options:{autoUpload:false,uploadTemplateId:"template-upload",downloadTemplateId:"template-download",filesContainer:undefined,prependFiles:false,dataType:"json",messages:{unknownError:"Unknown error"},getNumberOfFiles:function(){return this.filesContainer.children().not(".processing").length},getFilesFromResponse:function(t){if(t.result&&e.isArray(t.result.files)){return t.result.files}return[]},add:function(t,n){if(t.isDefaultPrevented()){return false}var r=e(this),i=r.data("blueimp-fileupload")||r.data("fileupload"),s=i.options;n.context=i._renderUpload(n.files).data("data",n).addClass("processing");s.filesContainer[s.prependFiles?"prepend":"append"](n.context);i._forceReflow(n.context);i._transition(n.context);n.process(function(){return r.fileupload("process",n)}).always(function(){n.context.each(function(t){e(this).find(".size").text(i._formatFileSize(n.files[t].size))}).removeClass("processing");i._renderPreviews(n)}).done(function(){n.context.find(".start").prop("disabled",false);if(i._trigger("added",t,n)!==false&&(s.autoUpload||n.autoUpload)&&n.autoUpload!==false){n.submit()}}).fail(function(){if(n.files.error){n.context.each(function(t){var r=n.files[t].error;if(r){e(this).find(".error").text(r)}})}})},send:function(t,n){if(t.isDefaultPrevented()){return false}var r=e(this).data("blueimp-fileupload")||e(this).data("fileupload");if(n.context&&n.dataType&&n.dataType.substr(0,6)==="iframe"){n.context.find(".progress").addClass(!e.support.transition&&"progress-animated").attr("aria-valuenow",100).children().first().css("width","100%")}return r._trigger("sent",t,n)},done:function(t,n){if(t.isDefaultPrevented()){return false}var r=e(this).data("blueimp-fileupload")||e(this).data("fileupload"),i=n.getFilesFromResponse||r.options.getFilesFromResponse,s=i(n),o,u;if(n.context){n.context.each(function(i){var a=s[i]||{error:"Empty file upload result"};u=r._addFinishedDeferreds();r._transition(e(this)).done(function(){var i=e(this);o=r._renderDownload([a]).replaceAll(i);r._forceReflow(o);r._transition(o).done(function(){n.context=e(this);r._trigger("completed",t,n);r._trigger("finished",t,n);u.resolve()})})})}else{o=r._renderDownload(s)[r.options.prependFiles?"prependTo":"appendTo"](r.options.filesContainer);r._forceReflow(o);u=r._addFinishedDeferreds();r._transition(o).done(function(){n.context=e(this);r._trigger("completed",t,n);r._trigger("finished",t,n);u.resolve()})}},fail:function(t,n){if(t.isDefaultPrevented()){return false}var r=e(this).data("blueimp-fileupload")||e(this).data("fileupload"),i,s;if(n.context){n.context.each(function(o){if(n.errorThrown!=="abort"){var u=n.files[o];u.error=u.error||n.errorThrown||n.i18n("unknownError");s=r._addFinishedDeferreds();r._transition(e(this)).done(function(){var o=e(this);i=r._renderDownload([u]).replaceAll(o);r._forceReflow(i);r._transition(i).done(function(){n.context=e(this);r._trigger("failed",t,n);r._trigger("finished",t,n);s.resolve()})})}else{s=r._addFinishedDeferreds();r._transition(e(this)).done(function(){e(this).remove();r._trigger("failed",t,n);r._trigger("finished",t,n);s.resolve()})}})}else if(n.errorThrown!=="abort"){n.context=r._renderUpload(n.files)[r.options.prependFiles?"prependTo":"appendTo"](r.options.filesContainer).data("data",n);r._forceReflow(n.context);s=r._addFinishedDeferreds();r._transition(n.context).done(function(){n.context=e(this);r._trigger("failed",t,n);r._trigger("finished",t,n);s.resolve()})}else{r._trigger("failed",t,n);r._trigger("finished",t,n);r._addFinishedDeferreds().resolve()}},progress:function(t,n){if(t.isDefaultPrevented()){return false}var r=Math.floor(n.loaded/n.total*100);if(n.context){n.context.each(function(){e(this).find(".progress").attr("aria-valuenow",r).children().first().css("width",r+"%")})}},progressall:function(t,n){if(t.isDefaultPrevented()){return false}var r=e(this),i=Math.floor(n.loaded/n.total*100),s=r.find(".fileupload-progress"),o=s.find(".progress-extended");if(o.length){o.html((r.data("blueimp-fileupload")||r.data("fileupload"))._renderExtendedProgress(n))}s.find(".progress").attr("aria-valuenow",i).children().first().css("width",i+"%")},start:function(t){if(t.isDefaultPrevented()){return false}var n=e(this).data("blueimp-fileupload")||e(this).data("fileupload");n._resetFinishedDeferreds();n._transition(e(this).find(".fileupload-progress")).done(function(){n._trigger("started",t)})},stop:function(t){if(t.isDefaultPrevented()){return false}var n=e(this).data("blueimp-fileupload")||e(this).data("fileupload"),r=n._addFinishedDeferreds();e.when.apply(e,n._getFinishedDeferreds()).done(function(){n._trigger("stopped",t)});n._transition(e(this).find(".fileupload-progress")).done(function(){e(this).find(".progress").attr("aria-valuenow","0").children().first().css("width","0%");e(this).find(".progress-extended").html(" ");r.resolve()})},processstart:function(t){if(t.isDefaultPrevented()){return false}e(this).addClass("fileupload-processing")},processstop:function(t){if(t.isDefaultPrevented()){return false}e(this).removeClass("fileupload-processing")},destroy:function(t,n){if(t.isDefaultPrevented()){return false}var r=e(this).data("blueimp-fileupload")||e(this).data("fileupload"),i=function(){r._transition(n.context).done(function(){e(this).remove();r._trigger("destroyed",t,n)})};if(n.url){n.dataType=n.dataType||r.options.dataType;e.ajax(n).done(i).fail(function(){r._trigger("destroyfailed",t,n)})}else{i()}}},_resetFinishedDeferreds:function(){this._finishedUploads=[]},_addFinishedDeferreds:function(t){if(!t){t=e.Deferred()}this._finishedUploads.push(t);return t},_getFinishedDeferreds:function(){return this._finishedUploads},_enableDragToDesktop:function(){var t=e(this),n=t.prop("href"),r=t.prop("download"),i="application/octet-stream";t.bind("dragstart",function(e){try{e.originalEvent.dataTransfer.setData("DownloadURL",[i,r,n].join(":"))}catch(t){}})},_formatFileSize:function(e){if(typeof e!=="number"){return""}if(e>=1e9){return(e/1e9).toFixed(2)+" GB"}if(e>=1e6){return(e/1e6).toFixed(2)+" MB"}return(e/1e3).toFixed(2)+" KB"},_formatBitrate:function(e){if(typeof e!=="number"){return""}if(e>=1e9){return(e/1e9).toFixed(2)+" Gbit/s"}if(e>=1e6){return(e/1e6).toFixed(2)+" Mbit/s"}if(e>=1e3){return(e/1e3).toFixed(2)+" kbit/s"}return e.toFixed(2)+" bit/s"},_formatTime:function(e){var t=new Date(e*1e3),n=Math.floor(e/86400);n=n?n+"d ":"";return n+("0"+t.getUTCHours()).slice(-2)+":"+("0"+t.getUTCMinutes()).slice(-2)+":"+("0"+t.getUTCSeconds()).slice(-2)},_formatPercentage:function(e){return(e*100).toFixed(2)+" %"},_renderExtendedProgress:function(e){return this._formatBitrate(e.bitrate)+" | "+this._formatTime((e.total-e.loaded)*8/e.bitrate)+" | "+this._formatPercentage(e.loaded/e.total)+" | "+this._formatFileSize(e.loaded)+" / "+this._formatFileSize(e.total)},_renderTemplate:function(t,n){if(!t){return e()}var r=t({files:n,formatFileSize:this._formatFileSize,options:this.options});if(r instanceof e){return r}return e(this.options.templatesContainer).html(r).children()},_renderPreviews:function(t){t.context.find(".preview").each(function(n,r){e(r).append(t.files[n].preview)})},_renderUpload:function(e){return this._renderTemplate(this.options.uploadTemplate,e)},_renderDownload:function(e){return this._renderTemplate(this.options.downloadTemplate,e).find("a[download]").each(this._enableDragToDesktop).end()},_startHandler:function(t){t.preventDefault();var n=e(t.currentTarget),r=n.closest(".template-upload"),i=r.data("data");n.prop("disabled",true);if(i&&i.submit){i.submit()}},_cancelHandler:function(t){t.preventDefault();var n=e(t.currentTarget).closest(".template-upload,.template-download"),r=n.data("data")||{};r.context=r.context||n;if(r.abort){r.abort()}else{r.errorThrown="abort";this._trigger("fail",t,r)}},_deleteHandler:function(t){t.preventDefault();var n=e(t.currentTarget);this._trigger("destroy",t,e.extend({context:n.closest(".template-download"),type:"DELETE"},n.data()))},_forceReflow:function(t){return e.support.transition&&t.length&&t[0].offsetWidth},_transition:function(t){var n=e.Deferred();if(e.support.transition&&t.hasClass("fade")&&t.is(":visible")){t.bind(e.support.transition.end,function(r){if(r.target===t[0]){t.unbind(e.support.transition.end);n.resolveWith(t)}}).toggleClass("in")}else{t.toggleClass("in");n.resolveWith(t)}return n},_initButtonBarEventHandlers:function(){var t=this.element.find(".fileupload-buttonbar"),n=this.options.filesContainer;this._on(t.find(".start"),{click:function(e){e.preventDefault();n.find(".start").click()}});this._on(t.find(".cancel"),{click:function(e){e.preventDefault();n.find(".cancel").click()}});this._on(t.find(".delete"),{click:function(e){e.preventDefault();n.find(".toggle:checked").closest(".template-download").find(".delete").click();t.find(".toggle").prop("checked",false)}});this._on(t.find(".toggle"),{change:function(t){n.find(".toggle").prop("checked",e(t.currentTarget).is(":checked"))}})},_destroyButtonBarEventHandlers:function(){this._off(this.element.find(".fileupload-buttonbar").find(".start, .cancel, .delete"),"click");this._off(this.element.find(".fileupload-buttonbar .toggle"),"change.")},_initEventHandlers:function(){this._super();this._on(this.options.filesContainer,{"click .start":this._startHandler,"click .cancel":this._cancelHandler,"click .delete":this._deleteHandler});this._initButtonBarEventHandlers()},_destroyEventHandlers:function(){this._destroyButtonBarEventHandlers();this._off(this.options.filesContainer,"click");this._super()},_enableFileInputButton:function(){this.element.find(".fileinput-button input").prop("disabled",false).parent().removeClass("disabled")},_disableFileInputButton:function(){this.element.find(".fileinput-button input").prop("disabled",true).parent().addClass("disabled")},_initTemplates:function(){var e=this.options;e.templatesContainer=this.document[0].createElement(e.filesContainer.prop("nodeName"));if(t){if(e.uploadTemplateId){e.uploadTemplate=t(e.uploadTemplateId)}if(e.downloadTemplateId){e.downloadTemplate=t(e.downloadTemplateId)}}},_initFilesContainer:function(){var t=this.options;if(t.filesContainer===undefined){t.filesContainer=this.element.find(".files")}else if(!(t.filesContainer instanceof e)){t.filesContainer=e(t.filesContainer)}},_initSpecialOptions:function(){this._super();this._initFilesContainer();this._initTemplates()},_create:function(){this._super();this._resetFinishedDeferreds();if(!e.support.fileInput){this._disableFileInputButton()}},enable:function(){var e=false;if(this.options.disabled){e=true}this._super();if(e){this.element.find("input, button").prop("disabled",false);this._enableFileInputButton()}},disable:function(){if(!this.options.disabled){this.element.find("input, button").prop("disabled",true);this._disableFileInputButton()}this._super()}})});$(function(){"use strict";$("#fileupload").fileupload({url:"images/"});$("#fileupload").fileupload("option","redirect",window.location.href.replace(/\/[^\/]*$/,"/cors/result.html?%s"));if(window.location.hostname==="blueimp.github.io"){$("#fileupload").fileupload("option",{url:"//jquery-file-upload.appspot.com/",disableImageResize:/Android(?!.*Chrome)|Opera/.test(window.navigator.userAgent),maxFileSize:5e6,acceptFileTypes:/(\.|\/)(gif|jpe?g|png)$/i});if($.support.cors){$.ajax({url:"//jquery-file-upload.appspot.com/",type:"HEAD"}).fail(function(){$('<div class="alert alert-danger"/>').text("Upload server currently unavailable - "+new Date).appendTo("#fileupload")})}}else{$("#fileupload").addClass("fileupload-processing");$.ajax({url:$("#fileupload").fileupload("option","url"),dataType:"json",context:$("#fileupload")[0]}).always(function(){$(this).removeClass("fileupload-processing")}).done(function(e){$(this).fileupload("option","done").call(this,$.Event("done"),{result:e})})}}) diff --git a/loading.gif b/loading.gif Binary files differnew file mode 100644 index 0000000..90f28cb --- /dev/null +++ b/loading.gif diff --git a/play-pause.png b/play-pause.png Binary files differnew file mode 100644 index 0000000..ece6cfb --- /dev/null +++ b/play-pause.png diff --git a/play-pause.svg b/play-pause.svg new file mode 100644 index 0000000..a7f1f50 --- /dev/null +++ b/play-pause.svg @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="30" height="15"> + <polygon points="2,1 2,14 13,7" stroke="black" stroke-width="1" fill="white"/> + <rect x="17" y="2" width="4" height="11" stroke="black" stroke-width="1" fill="white"/> + <rect x="24" y="2" width="4" height="11" stroke="black" stroke-width="1" fill="white"/> +</svg> diff --git a/progressbar.gif b/progressbar.gif Binary files differnew file mode 100644 index 0000000..fbcce6b --- /dev/null +++ b/progressbar.gif diff --git a/protected/README b/protected/README new file mode 100644 index 0000000..4562dd5 --- /dev/null +++ b/protected/README @@ -0,0 +1,7 @@ +Placeholder for Git. +This directory is stored images protected by nginx 'X-Accel-Redirect' Header. +Needs write access for PHP. + +location /protected { + internal; +} diff --git a/static/footer.php b/static/footer.php index 82e3dd6..06d4295 100755 --- a/static/footer.php +++ b/static/footer.php @@ -1,14 +1,20 @@ </div> - <div class="footer text-right random-bg"> + <div class="footer random-bg"> <div class="container"> - <p class="effect"> Copyright 2014 <a id="copyright-text" href="//www.moehm.org/" target="_blank">Maximilian Möhring</a></p> + <div class="row"> + <div class="col-md-6"> + <p class="effect">v4.1 Built with <a href="http://getbootstrap.com" title="Twitter Bootstrap" class="footer-a">Bootstrap</a>, + <a href="http://redis.io" title="Redis.io" class="footer-a">Redis</a> and <a href="http://mariadb.org" title="MariaDB.org" class="footer-a">MariaDB</a>.</p> + </div> + <div class="col-md-6"> + <p class="effect"><span class="pull-right"><span class="fa fa-copyright"></span> Copyright 2014 <a class="footer-a" href="//www.moehm.org/" target="_blank">Maximilian Möhring</a></span></p> + </div> + </div> </div> </div> - <script src="//code.jquery.com/jquery-1.10.1.min.js" defer></script> - <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" defer></script> + <script src="//code.jquery.com/jquery-1.11.1.min.js"></script> <script src="//code.jquery.com/ui/1.11.1/jquery-ui.min.js" defer></script> - <!--script src="/static/eyecancer.js" defer></script--> - <?php //<script src='/boring.js' defer></script> ?> + <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js" defer></script> <?php include("static/piwik.html"); ?> <script>function loadFancy(){ document.getElementById("loader").style.visibility="visible"; @@ -21,6 +27,15 @@ return false; }</script> - </body> -</html> +<script> + $('#btn-send').click(function () { + var btn = $(this) + btn.button('loading') + $.ajax().always(function () { + }); + }); + $('.close').click(function () { + $('#btn-send').button('reset'); + }); +</script> diff --git a/static/gallery.min.css b/static/gallery.min.css new file mode 100644 index 0000000..fac687d --- /dev/null +++ b/static/gallery.min.css @@ -0,0 +1,2 @@ +@charset "UTF-8";.fileinput-button{position:relative;overflow:hidden}.fileinput-button input{position:absolute;top:0;right:0;margin:0;opacity:0;-ms-filter:'alpha(opacity=0)';font-size:200px;direction:ltr;cursor:pointer}@media screen\9{.fileinput-button input{filter:alpha(opacity=0);font-size:100%;height:100%}}.fileupload-buttonbar .btn,.fileupload-buttonbar .toggle{margin-bottom:5px}.progress-animated .bar,.progress-animated .progress-bar{background:url(../img/progressbar.gif)!important;filter:none}.fileupload-process{float:right;display:none}.files .processing .preview,.fileupload-processing .fileupload-process{display:block;width:32px;height:32px;background:url(../img/loading.gif) center no-repeat;background-size:contain}.files audio,.files video{max-width:300px}@media (max-width:767px){.files .btn span,.files .toggle,.fileupload-buttonbar .toggle{display:none}.files .name{width:80px;word-wrap:break-word}.files audio,.files video{max-width:80px}.files canvas,.files img{max-width:100%}} +@charset "UTF-8";.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{position:absolute;top:0;right:0;bottom:0;left:0;-moz-backface-visibility:hidden}.blueimp-gallery>.slides>.slide>.slide-content{margin:auto;width:auto;height:auto;max-width:100%;max-height:100%;opacity:1}.blueimp-gallery{position:fixed;z-index:999999;overflow:hidden;background:#000;background:rgba(0,0,0,.9);opacity:0;display:none;direction:ltr;-ms-touch-action:none;touch-action:none}.blueimp-gallery-carousel{position:relative;z-index:auto;margin:1em auto;padding-bottom:56.25%;box-shadow:0 0 10px #000;-ms-touch-action:pan-y;touch-action:pan-y}.blueimp-gallery-display{display:block;opacity:1}.blueimp-gallery>.slides{position:relative;height:100%;overflow:hidden}.blueimp-gallery-carousel>.slides{position:absolute}.blueimp-gallery>.slides>.slide{position:relative;float:left;height:100%;text-align:center;-webkit-transition-timing-function:cubic-bezier(0.645,.045,.355,1);-moz-transition-timing-function:cubic-bezier(0.645,.045,.355,1);-ms-transition-timing-function:cubic-bezier(0.645,.045,.355,1);-o-transition-timing-function:cubic-bezier(0.645,.045,.355,1);transition-timing-function:cubic-bezier(0.645,.045,.355,1)}.blueimp-gallery,.blueimp-gallery>.slides>.slide>.slide-content{-webkit-transition:opacity .5s linear;-moz-transition:opacity .5s linear;-ms-transition:opacity .5s linear;-o-transition:opacity .5s linear;transition:opacity .5s linear}.blueimp-gallery>.slides>.slide-loading{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}.blueimp-gallery>.slides>.slide-loading>.slide-content{opacity:0}.blueimp-gallery>.slides>.slide-error{background:url(../img/error.png) center no-repeat}.blueimp-gallery>.slides>.slide-error>.slide-content{display:none}.blueimp-gallery>.prev,.blueimp-gallery>.next{position:absolute;top:50%;left:15px;width:40px;height:40px;margin-top:-23px;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-decoration:none;text-shadow:0 0 2px #000;text-align:center;background:#222;background:rgba(0,0,0,.5);-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;cursor:pointer;display:none}.blueimp-gallery>.next{left:auto;right:15px}.blueimp-gallery>.close,.blueimp-gallery>.title{position:absolute;top:15px;left:15px;margin:0 40px 0 0;font-size:20px;line-height:30px;color:#fff;text-shadow:0 0 2px #000;opacity:.8;display:none}.blueimp-gallery>.close{padding:15px;right:15px;left:auto;margin:-15px;font-size:30px;text-decoration:none;cursor:pointer}.blueimp-gallery>.play-pause{position:absolute;right:15px;bottom:15px;width:15px;height:15px;background:url(../img/play-pause.png) 0 0 no-repeat;cursor:pointer;opacity:.5;display:none}.blueimp-gallery-playing>.play-pause{background-position:-15px 0}.blueimp-gallery>.prev:hover,.blueimp-gallery>.next:hover,.blueimp-gallery>.close:hover,.blueimp-gallery>.title:hover,.blueimp-gallery>.play-pause:hover{color:#fff;opacity:1}.blueimp-gallery-controls>.prev,.blueimp-gallery-controls>.next,.blueimp-gallery-controls>.close,.blueimp-gallery-controls>.title,.blueimp-gallery-controls>.play-pause{display:block;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.blueimp-gallery-single>.prev,.blueimp-gallery-left>.prev,.blueimp-gallery-single>.next,.blueimp-gallery-right>.next,.blueimp-gallery-single>.play-pause{display:none}.blueimp-gallery>.slides>.slide>.slide-content,.blueimp-gallery>.prev,.blueimp-gallery>.next,.blueimp-gallery>.close,.blueimp-gallery>.play-pause{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}body:last-child .blueimp-gallery>.slides>.slide-error{background-image:url(../img/error.svg)}body:last-child .blueimp-gallery>.play-pause{width:20px;height:20px;background-size:40px 20px;background-image:url(../img/play-pause.svg)}body:last-child .blueimp-gallery-playing>.play-pause{background-position:-20px 0}*+html .blueimp-gallery>.slides>.slide{min-height:300px}*+html .blueimp-gallery>.slides>.slide>.slide-content{position:relative}@charset "UTF-8";.blueimp-gallery>.indicator{position:absolute;top:auto;right:15px;bottom:15px;left:15px;margin:0 40px;padding:0;list-style:none;text-align:center;line-height:10px;display:none}.blueimp-gallery>.indicator>li{display:inline-block;width:9px;height:9px;margin:6px 3px 0;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;border:1px solid transparent;background:#ccc;background:rgba(255,255,255,.25)center no-repeat;border-radius:5px;box-shadow:0 0 2px #000;opacity:.5;cursor:pointer}.blueimp-gallery>.indicator>li:hover,.blueimp-gallery>.indicator>.active{background-color:#fff;border-color:#fff;opacity:1}.blueimp-gallery-controls>.indicator{display:block;-webkit-transform:translateZ(0);-moz-transform:translateZ(0);-ms-transform:translateZ(0);-o-transform:translateZ(0);transform:translateZ(0)}.blueimp-gallery-single>.indicator{display:none}.blueimp-gallery>.indicator{-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}*+html .blueimp-gallery>.indicator>li{display:inline}@charset "UTF-8";.blueimp-gallery>.slides>.slide>.video-content>img{position:absolute;top:0;right:0;bottom:0;left:0;margin:auto;width:auto;height:auto;max-width:100%;max-height:100%;-moz-backface-visibility:hidden}.blueimp-gallery>.slides>.slide>.video-content>video{position:absolute;top:0;left:0;width:100%;height:100%}.blueimp-gallery>.slides>.slide>.video-content>iframe{position:absolute;top:100%;left:0;width:100%;height:100%;border:none}.blueimp-gallery>.slides>.slide>.video-playing>iframe{top:0}.blueimp-gallery>.slides>.slide>.video-content>a{position:absolute;top:50%;right:0;left:0;margin:-64px auto 0;width:128px;height:128px;background:url(../img/video-play.png) center no-repeat;opacity:.8;cursor:pointer}.blueimp-gallery>.slides>.slide>.video-content>a:hover{opacity:1}.blueimp-gallery>.slides>.slide>.video-playing>a,.blueimp-gallery>.slides>.slide>.video-playing>img{display:none}.blueimp-gallery>.slides>.slide>.video-content>video{display:none}.blueimp-gallery>.slides>.slide>.video-playing>video{display:block}.blueimp-gallery>.slides>.slide>.video-loading>a{background:url(../img/loading.gif) center no-repeat;background-size:64px 64px}body:last-child .blueimp-gallery>.slides>.slide>.video-content:not(.video-loading)>a{background-image:url(../img/video-play.svg)}*+html .blueimp-gallery>.slides>.slide>.video-content{height:100%}*+html .blueimp-gallery>.slides>.slide>.video-content>a{left:50%;margin-left:-64px}
\ No newline at end of file diff --git a/static/header.php b/static/header.php index f6ecfd9..1fabb3f 100644 --- a/static/header.php +++ b/static/header.php @@ -8,20 +8,23 @@ <span class="icon-bar"></span> </button> <a class="navbar-brand effect" href="/?page=index" title="Startseite"><span class="glyphicon glyphicon-home"></span> Home</a> - <!--a class="navbar-brand" href="/?page=index" title="Startseite">Home</a--> </div> <div class="collapse navbar-collapse" id="navbarCollapse"> <ul class="nav navbar-nav navbar-left effect"> + <li> + <!--a href="/?page=foto" title="Übersicht über alle Fotogalerien"><span class="fa fa-camera"></span> Bilder</a--> + <a href="/?page=foto" title="Übersicht über alle Fotogalerien"><span class="glyphicon glyphicon-picture"></span> Bilder</a> + </li> <li class="dropdown"> - <a href="/?page=liste" title="Liste aller JG-Mitglieder"><span class="glyphicon glyphicon-th-list"></span> Adressliste <span class="caret"></span></a> + <a href="/?page=liste" title="Liste aller JG-Mitglieder"><span class="glyphicon glyphicon-th-list"></span> Adressen <span class="caret"></span></a> <ul class="dropdown-menu" role="menu"> <li><a href="/?page=download&task=download&type=plain" title="Download: text/plain"><span class="glyphicon glyphicon-download"></span> Download als Text</a></li> <li><a href="/?page=download&task=download&type=csv" title="Download: text/csv"><span class="glyphicon glyphicon-arrow-down"></span> Download als CSV</a></li> </ul> </li> - <li> - <a href="https://lists.iamfabulous.de/mailman/listinfo/jungegemeinde" target="_blank" title="JG E-Mail Verteiler"><span class="glyphicon glyphicon-envelope"></span> E-Mail Verteiler</a> - </li> + <li> + <a href="https://lists.iamfabulous.de/mailman/listinfo/jungegemeinde" target="_blank" title="JG E-Mail Verteiler"><span class="glyphicon glyphicon-envelope"></span> E-Mail Verteiler</a> + </li> <li> <a href="https://lists.iamfabulous.de/mailman/private/jungegemeinde/" target="_blank" title="Archiv der Mailing Liste "><span class="glyphicon glyphicon-send"></span> Mail Archiv</a> </li> @@ -48,6 +51,7 @@ ?> <a href="/?page=account" title="Ändere dein Passwort"><span class="glyphicon glyphicon-user"></span> Profil</a> </li> + <li class="divider"></li> <li> <a href="/?page=logout" title="Beende die Session"><span class="glyphicon glyphicon-off"></span> Logout</a> <?php @@ -55,8 +59,9 @@ ?> <a href="/?page=register&goto=index" title="Registriere dich für unbeschränkten Zugang"><span class="glyphicon glyphicon-share-alt"></span> Register</a> </li> + <li class="divider"></li> <li> - <a href="/?page=login&goto=index" title="Login"><span class="glyphicon glyphicon-off"></span> Login</a> + <a href="/?page=login&goto=index" title="Login"><span class="glyphicon glyphicon-log-in"></span> Login</a> <?php } ?> diff --git a/static/modal-delete-gallery.php b/static/modal-delete-gallery.php new file mode 100644 index 0000000..74471ac --- /dev/null +++ b/static/modal-delete-gallery.php @@ -0,0 +1,24 @@ +<!-- Modal --> +<form class="form-horizontal" method="POST" action="/?page=action&task=deleteGallery&gallery=<?php echo htmlentities($_SESSION['gallery']); ?>"> +<div class="modal fade" id="modal-delete-gallery" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> + <h4 class="modal-title" id="myModalLabel">Löschen</h4> + </div> + <div class="modal-body"> +<fieldset> + <h4>Bist du dir ganz sicher '<?php echo htmlentities($row["name"]); ?>' komplett zu löschen?</h4> + <p>Nachdem die Bilder gelöscht sind können sie nicht wieder hergestellt werden!</p> + +</fieldset> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Nee, dann doch nicht...</button> + <button id="btn-send" type="submit" class="btn btn-danger" data-loading-text="Lade..."><span class="glyphicon glyphicon-trash"></span> Ja, ganz sicher!</button> + </div> + </div> + </div> +</div> +</form> diff --git a/static/modal-edit-gallery.php b/static/modal-edit-gallery.php new file mode 100644 index 0000000..e5a2c48 --- /dev/null +++ b/static/modal-edit-gallery.php @@ -0,0 +1,40 @@ +<!-- Modal --> +<form class="form-horizontal" method="POST" action="/?page=action&task=editGallery&gallery=<?php echo htmlentities($_SESSION['gallery']); ?>"> +<div class="modal fade" id="modal-edit-gallery" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> + <h4 class="modal-title" id="myModalLabel">Ändern</h4> + </div> + <div class="modal-body"> +<fieldset> + +<!-- Text input--> +<div class="form-group"> + <label class="col-md-4 control-label" for="name">Galerie Name</label> + <div class="col-md-6"> + <input id="name" name="name" value="<?php echo htmlentities($row["name"]); ?>" placeholder="Wie heißt die neue Foto Galerie? (Pflicht)" class="form-control input-md" required="" type="text"> + + </div> +</div> + +<!-- Text input--> +<div class="form-group"> + <label class="col-md-4 control-label" for="desc">Beschreibung</label> + <div class="col-md-6"> + <input id="desc" name="desc" value="<?php echo htmlentities($row["description"]); ?>" placeholder="Kurze Zusammenfassung. (Pflicht)" class="form-control input-md" required="" type="text"> + + </div> +</div> + +</fieldset> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Schließen</button> + <button id="btn-send" type="submit" class="btn btn-primary" data-loading-text="Lade...">Änderung speichern</button> + </div> + </div> + </div> +</div> +</form> diff --git a/static/modal-new-gallery.html b/static/modal-new-gallery.html new file mode 100644 index 0000000..88e0f18 --- /dev/null +++ b/static/modal-new-gallery.html @@ -0,0 +1,40 @@ +<!-- Modal --> +<form class="form-horizontal" method="POST" action="/?page=action&task=gallery"> +<div class="modal fade" id="modal-new-gallery" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> + <div class="modal-dialog"> + <div class="modal-content"> + <div class="modal-header"> + <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button> + <h4 class="modal-title" id="myModalLabel">Erstelle eine neue Galerie</h4> + </div> + <div class="modal-body"> +<fieldset> + +<!-- Text input--> +<div class="form-group"> + <label class="col-md-4 control-label" for="name">Galerie Name</label> + <div class="col-md-6"> + <input id="name" name="name" placeholder="Wie heißt die neue Foto Galerie? (Pflicht)" class="form-control input-md" required="" type="text"> + + </div> +</div> + +<!-- Text input--> +<div class="form-group"> + <label class="col-md-4 control-label" for="desc">Beschreibung</label> + <div class="col-md-6"> + <input id="desc" name="desc" placeholder="Kurze Zusammenfassung. (Pflicht)" class="form-control input-md" required="" type="text"> + + </div> +</div> + +</fieldset> + </div> + <div class="modal-footer"> + <button type="button" class="btn btn-default" data-dismiss="modal">Schließen</button> + <button id="btn-send" type="submit" class="btn btn-primary" data-loading-text="Lade...">Erstellen</button> + </div> + </div> + </div> +</div> +</form> diff --git a/static/style.css b/static/style.css index 8d19477..62f0c50 100644 --- a/static/style.css +++ b/static/style.css @@ -44,9 +44,13 @@ a { width: 100%; } -#copyright-text { +.footer-a { color: white; } +.footer-a:hover { + color: white; + text-decoration: underline; +} /* noscript */ @@ -103,3 +107,21 @@ a { margin: -20px 0 0 -20px; visibility: hidden; } +.fa-external-link { + font-size: .5em; +} +.a-black{ + color: black; +} +.a-restore:hover{ + text-decoration: none; +} +.desc{ + color: #666666; +} +.font-small{ + font-size: .8em; +} +.nav-tabs{ + margin: 20px; +} diff --git a/static/style.min.css b/static/style.min.css index f593c04..9fca366 100644 --- a/static/style.min.css +++ b/static/style.min.css @@ -1 +1 @@ -html{position:relative;min-height:100%}body{margin-bottom:60px}a{color:#3083D6}.navbar-default{border-color:#3083D6;background:#3083D6}.navbar-default .navbar-brand{color:#fff}.navbar-default .navbar-nav>li>a{color:#fff}.footer{border-color:#3083D6;background:#3083D6;color:#fff;position:absolute;bottom:0;width:100%}#copyright-text{color:#fff}.noscript{background-color:#dd5148;color:#fff}.table-center{margin:0 auto!important;float:none!important}.disabled{color:#5E5E5E;text-decoration:line-through}.random-bg,.random-font{transition:all 1500ms}.wrapper{overflow:hidden}#loader-bg{position:fixed;background-color:#fefefe;z-index:99999;height:100%;width:100%;overflow:hidden!important;visibility:hidden}#loader{width:40px;height:40px;position:absolute;left:50%;top:50%;background-image:url(/static/img/loading.gif);background-repeat:no-repeat;background-position:center;-webkit-background-size:cover;background-size:cover;margin:-20px 0 0 -20px;visibility:hidden} +html{position:relative;min-height:100%}body{margin-bottom:60px}a{color:#3083D6}.navbar-default{border-color:#3083D6;background:#3083D6}.navbar-default .navbar-brand{color:#fff}.navbar-default .navbar-nav>li>a{color:#fff}.footer{border-color:#3083D6;background:#3083D6;color:#fff;position:absolute;bottom:0;width:100%}.footer-a{color:#fff}.footer-a:hover{color:#fff;text-decoration:underline}.noscript{background-color:#dd5148;color:#fff}.table-center{margin:0 auto!important;float:none!important}.disabled{color:#5E5E5E;text-decoration:line-through}.random-bg,.random-font{transition:all 1500ms}.wrapper{overflow:hidden}#loader-bg{position:fixed;background-color:#fefefe;z-index:99999;height:100%;width:100%;overflow:hidden!important;visibility:hidden}#loader{width:40px;height:40px;position:absolute;left:50%;top:50%;background-image:url(/static/img/loading.gif);background-repeat:no-repeat;background-position:center;-webkit-background-size:cover;background-size:cover;margin:-20px 0 0 -20px;visibility:hidden}.fa-external-link{font-size:.5em}.a-black{color:#000}.a-restore:hover{text-decoration:none}.desc{color:#666}.font-small{font-size:.8em}.nav-tabs{margin:20px} diff --git a/video-play.png b/video-play.png Binary files differnew file mode 100644 index 0000000..353e3a5 --- /dev/null +++ b/video-play.png diff --git a/video-play.svg b/video-play.svg new file mode 100644 index 0000000..b5ea206 --- /dev/null +++ b/video-play.svg @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="64" height="64"> + <circle cx="32" cy="32" r="25" stroke="white" stroke-width="7" fill="black" fill-opacity="0.2"/> + <polygon points="26,22 26,42 43,32" fill="white"/> +</svg> |
