Merge pull request #663 from sanmadjack/bugfixes

Bugfixes and small changes
This commit is contained in:
Shish 2019-06-21 09:11:52 +01:00 committed by GitHub
commit 42a502953b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
88 changed files with 693 additions and 570 deletions

View file

@ -99,21 +99,21 @@ For example, one can override the default anonymous "allow nothing"
permissions like so:
```php
new UserClass("anonymous", "base", array(
new UserClass("anonymous", "base", [
"create_comment" => True,
"edit_image_tag" => True,
"edit_image_source" => True,
"create_image_report" => True,
));
]);
```
For a moderator class, being a regular user who can delete images and comments:
```php
new UserClass("moderator", "user", array(
new UserClass("moderator", "user", [
"delete_image" => True,
"delete_comment" => True,
));
]);
```
For a list of permissions, see `core/userclass.php`

View file

@ -110,7 +110,7 @@ function do_install()
{ // {{{
if (file_exists("data/config/auto_install.conf.php")) {
require_once "data/config/auto_install.conf.php";
} elseif (@$_POST["database_type"] == "sqlite") {
} elseif (@$_POST["database_type"] == DatabaseDriver::SQLITE) {
$id = bin2hex(random_bytes(5));
define('DATABASE_DSN', "sqlite:data/shimmie.{$id}.sqlite");
} elseif (isset($_POST['database_type']) && isset($_POST['database_host']) && isset($_POST['database_user']) && isset($_POST['database_name'])) {
@ -153,9 +153,9 @@ function ask_questions()
$drivers = PDO::getAvailableDrivers();
if (
!in_array("mysql", $drivers) &&
!in_array("pgsql", $drivers) &&
!in_array("sqlite", $drivers)
!in_array(DatabaseDriver::MYSQL, $drivers) &&
!in_array(DatabaseDriver::PGSQL, $drivers) &&
!in_array(DatabaseDriver::SQLITE, $drivers)
) {
$errors[] = "
No database connection library could be found; shimmie needs
@ -163,9 +163,9 @@ function ask_questions()
";
}
$db_m = in_array("mysql", $drivers) ? '<option value="mysql">MySQL</option>' : "";
$db_p = in_array("pgsql", $drivers) ? '<option value="pgsql">PostgreSQL</option>' : "";
$db_s = in_array("sqlite", $drivers) ? '<option value="sqlite">SQLite</option>' : "";
$db_m = in_array(DatabaseDriver::MYSQL, $drivers) ? '<option value="'. DatabaseDriver::MYSQL .'">MySQL</option>' : "";
$db_p = in_array(DatabaseDriver::PGSQL, $drivers) ? '<option value="'. DatabaseDriver::PGSQL .'">PostgreSQL</option>' : "";
$db_s = in_array(DatabaseDriver::SQLITE, $drivers) ? '<option value="'. DatabaseDriver::SQLITE .'">SQLite</option>' : "";
$warn_msg = $warnings ? "<h3>Warnings</h3>".implode("\n<p>", $warnings) : "";
$err_msg = $errors ? "<h3>Errors</h3>".implode("\n<p>", $errors) : "";

View file

@ -144,6 +144,13 @@ abstract class BaseConfig implements Config
}
}
public function set_default_float(string $name, float $value): void
{
if (is_null($this->get($name))) {
$this->values[$name] = $value;
}
}
public function set_default_string(string $name, string $value): void
{
if (is_null($this->get($name))) {
@ -170,6 +177,11 @@ abstract class BaseConfig implements Config
return (int)($this->get($name, $default));
}
public function get_float(string $name, ?float $default=null): ?float
{
return (float)($this->get($name, $default));
}
public function get_string(string $name, ?string $default=null): ?string
{
return $this->get($name, $default);

View file

@ -1,9 +1,17 @@
<?php
abstract class DatabaseDriver
{
public const MYSQL = "mysql";
public const PGSQL = "pgsql";
public const SQLITE = "sqlite";
}
/**
* A class for controlled database access
*/
class Database
{
/**
* The PDO database connection object, for anyone who wants direct access.
* @var null|PDO
@ -72,7 +80,7 @@ class Database
// https://bugs.php.net/bug.php?id=70221
$ka = DATABASE_KA;
if (version_compare(PHP_VERSION, "6.9.9") == 1 && $this->get_driver_name() == "sqlite") {
if (version_compare(PHP_VERSION, "6.9.9") == 1 && $this->get_driver_name() == DatabaseDriver::SQLITE) {
$ka = false;
}
@ -96,11 +104,11 @@ class Database
throw new SCoreException("Can't figure out database engine");
}
if ($db_proto === "mysql") {
if ($db_proto === DatabaseDriver::MYSQL) {
$this->engine = new MySQL();
} elseif ($db_proto === "pgsql") {
} elseif ($db_proto === DatabaseDriver::PGSQL) {
$this->engine = new PostgreSQL();
} elseif ($db_proto === "sqlite") {
} elseif ($db_proto === DatabaseDriver::SQLITE) {
$this->engine = new SQLite();
} else {
die('Unknown PDO driver: '.$db_proto);
@ -296,7 +304,7 @@ class Database
*/
public function get_last_insert_id(string $seq): int
{
if ($this->engine->name == "pgsql") {
if ($this->engine->name == DatabaseDriver::PGSQL) {
return $this->db->lastInsertId($seq);
} else {
return $this->db->lastInsertId();
@ -326,15 +334,15 @@ class Database
$this->connect_db();
}
if ($this->engine->name === "mysql") {
if ($this->engine->name === DatabaseDriver::MYSQL) {
return count(
$this->get_all("SHOW TABLES")
);
} elseif ($this->engine->name === "pgsql") {
} elseif ($this->engine->name === DatabaseDriver::PGSQL) {
return count(
$this->get_all("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'")
);
} elseif ($this->engine->name === "sqlite") {
} elseif ($this->engine->name === DatabaseDriver::SQLITE) {
return count(
$this->get_all("SELECT name FROM sqlite_master WHERE type = 'table'")
);

View file

@ -22,7 +22,7 @@ class DBEngine
class MySQL extends DBEngine
{
/** @var string */
public $name = "mysql";
public $name = DatabaseDriver::MYSQL;
public function init(PDO $db)
{
@ -54,7 +54,7 @@ class MySQL extends DBEngine
class PostgreSQL extends DBEngine
{
/** @var string */
public $name = "pgsql";
public $name = DatabaseDriver::PGSQL;
public function init(PDO $db)
{
@ -136,7 +136,7 @@ function _ln($n)
class SQLite extends DBEngine
{
/** @var string */
public $name = "sqlite";
public $name = DatabaseDriver::SQLITE;
public function init(PDO $db)
{

View file

@ -182,7 +182,7 @@ abstract class DataHandlerExtension extends Extension
// even more hax..
$event->metadata['tags'] = $existing->get_tag_list();
$image = $this->create_image_from_data(warehouse_path("images", $event->metadata['hash']), $event->metadata);
$image = $this->create_image_from_data(warehouse_path(Image::IMAGE_DIR, $event->metadata['hash']), $event->metadata);
if (is_null($image)) {
throw new UploadException("Data handler failed to create image object from data");
@ -192,13 +192,14 @@ abstract class DataHandlerExtension extends Extension
send_event($ire);
$event->image_id = $image_id;
} else {
$image = $this->create_image_from_data(warehouse_path("images", $event->hash), $event->metadata);
$image = $this->create_image_from_data(warehouse_path(Image::IMAGE_DIR, $event->hash), $event->metadata);
if (is_null($image)) {
throw new UploadException("Data handler failed to create image object from data");
}
$iae = new ImageAdditionEvent($image);
send_event($iae);
$event->image_id = $iae->image->id;
$event->merged = $iae->merged;
// Rating Stuff.
if (!empty($event->metadata['rating'])) {
@ -222,13 +223,13 @@ abstract class DataHandlerExtension extends Extension
$result = false;
if ($this->supported_ext($event->type)) {
if ($event->force) {
$result = $this->create_thumb($event->hash);
$result = $this->create_thumb($event->hash, $event->type);
} else {
$outname = warehouse_path("thumbs", $event->hash);
$outname = warehouse_path(Image::THUMBNAIL_DIR, $event->hash);
if (file_exists($outname)) {
return;
}
$result = $this->create_thumb($event->hash);
$result = $this->create_thumb($event->hash, $event->type);
}
}
if ($result) {
@ -256,5 +257,5 @@ abstract class DataHandlerExtension extends Extension
abstract protected function supported_ext(string $ext): bool;
abstract protected function check_contents(string $tmpname): bool;
abstract protected function create_image_from_data(string $filename, array $metadata);
abstract protected function create_thumb(string $hash): bool;
abstract protected function create_thumb(string $hash, string $type): bool;
}

View file

@ -11,6 +11,8 @@ class ImageAdditionEvent extends Event
/** @var Image */
public $image;
public $merged = false;
/**
* Inserts a new image into the database with its associated
* information. Also calls TagSetEvent to set the tags for

View file

@ -10,6 +10,10 @@
*/
class Image
{
public const DATA_DIR = "data";
public const IMAGE_DIR = "images";
public const THUMBNAIL_DIR = "thumbs";
private static $tag_n = 0; // temp hack
public static $order_sql = null; // this feels ugly
@ -552,7 +556,7 @@ class Image
*/
public function get_image_filename(): string
{
return warehouse_path("images", $this->hash);
return warehouse_path(self::IMAGE_DIR, $this->hash);
}
/**
@ -560,7 +564,7 @@ class Image
*/
public function get_thumb_filename(): string
{
return warehouse_path("thumbs", $this->hash);
return warehouse_path(self::THUMBNAIL_DIR, $this->hash);
}
/**
@ -640,7 +644,7 @@ class Image
public function delete_tags_from_image(): void
{
global $database;
if ($database->get_driver_name() == "mysql") {
if ($database->get_driver_name() == DatabaseDriver::MYSQL) {
//mysql < 5.6 has terrible subquery optimization, using EXISTS / JOIN fixes this
$database->execute(
"
@ -917,7 +921,7 @@ class Image
// more than one positive tag, or more than zero negative tags
else {
if ($database->get_driver_name() === "mysql") {
if ($database->get_driver_name() === DatabaseDriver::MYSQL) {
$query = Image::build_ugly_search_querylet($tag_conditions);
} else {
$query = Image::build_accurate_search_querylet($tag_conditions);

View file

@ -7,11 +7,12 @@
* Move a file from PHP's temporary area into shimmie's image storage
* hierarchy, or throw an exception trying.
*
* @param DataUploadEvent $event
* @throws UploadException
*/
function move_upload_to_archive(DataUploadEvent $event): void
{
$target = warehouse_path("images", $event->hash);
$target = warehouse_path(Image::IMAGE_DIR, $event->hash);
if (!@copy($event->tmpname, $target)) {
$errors = error_get_last();
throw new UploadException(
@ -24,7 +25,8 @@ function move_upload_to_archive(DataUploadEvent $event): void
/**
* Add a directory full of images
*
* #return string[]
* @param string $base
* @return array
*/
function add_dir(string $base): array
{
@ -48,6 +50,14 @@ function add_dir(string $base): array
return $results;
}
/**
* Sends a DataUploadEvent for a file.
*
* @param string $tmpname
* @param string $filename
* @param string $tags
* @throws UploadException
*/
function add_image(string $tmpname, string $filename, string $tags): void
{
assert(file_exists($tmpname));
@ -65,10 +75,15 @@ function add_image(string $tmpname, string $filename, string $tags): void
send_event($event);
}
function get_extension_from_mime(String $file_path): ?String
/**
* Gets an the extension defined in MIME_TYPE_MAP for a file.
*
* @param String $file_path
* @return String The extension that was found.
* @throws UploadException if the mimetype could not be determined, or if an extension for hte mimetype could not be found.
*/
function get_extension_from_mime(String $file_path): String
{
global $config;
$mime = mime_content_type($file_path);
if (!empty($mime)) {
$ext = get_extension($mime);
@ -83,11 +98,15 @@ function get_extension_from_mime(String $file_path): ?String
/**
* Given a full size pair of dimensions, return a pair scaled down to fit
* into the configured thumbnail square, with ratio intact
* into the configured thumbnail square, with ratio intact.
* Optionally uses the High-DPI scaling setting to adjust the final resolution.
*
* #return int[]
* @param int $orig_width
* @param int $orig_height
* @param bool $use_dpi_scaling Enables the High-DPI scaling.
* @return array
*/
function get_thumbnail_size(int $orig_width, int $orig_height): array
function get_thumbnail_size(int $orig_width, int $orig_height, bool $use_dpi_scaling = false): array
{
global $config;
@ -105,8 +124,15 @@ function get_thumbnail_size(int $orig_width, int $orig_height): array
$orig_height = $orig_width * 5;
}
$max_width = $config->get_int('thumb_width');
$max_height = $config->get_int('thumb_height');
if($use_dpi_scaling) {
$max_size = get_thumbnail_max_size_scaled();
$max_width = $max_size[0];
$max_height = $max_size[1];
} else {
$max_width = $config->get_int('thumb_width');
$max_height = $config->get_int('thumb_height');
}
$xscale = ($max_height / $orig_height);
$yscale = ($max_width / $orig_width);
@ -120,44 +146,10 @@ function get_thumbnail_size(int $orig_width, int $orig_height): array
}
/**
* Given a full size pair of dimensions, return a pair scaled down to fit
* into the configured thumbnail square, with ratio intact, using thumb_scaling
* Fetches the thumbnails height and width settings and applies the High-DPI scaling setting before returning the dimensions.
*
* #return int[]
* @return array [width, height]
*/
function get_thumbnail_size_scaled(int $orig_width, int $orig_height): array
{
global $config;
if ($orig_width === 0) {
$orig_width = 192;
}
if ($orig_height === 0) {
$orig_height = 192;
}
if ($orig_width > $orig_height * 5) {
$orig_width = $orig_height * 5;
}
if ($orig_height > $orig_width * 5) {
$orig_height = $orig_width * 5;
}
$max_size = get_thumbnail_max_size_scaled();
$max_width = $max_size[0];
$max_height = $max_size[1];
$xscale = ($max_height / $orig_height);
$yscale = ($max_width / $orig_width);
$scale = ($xscale < $yscale) ? $xscale : $yscale;
if ($scale > 1 && $config->get_bool('thumb_upscale')) {
return [(int)$orig_width, (int)$orig_height];
} else {
return [(int)($orig_width*$scale), (int)($orig_height*$scale)];
}
}
function get_thumbnail_max_size_scaled(): array
{
global $config;
@ -168,12 +160,19 @@ function get_thumbnail_max_size_scaled(): array
return [$max_width, $max_height];
}
function create_thumbnail_convert($hash): bool
/**
* Creates a thumbnail file using ImageMagick's convert command.
*
* @param $hash
* @param string $input_type Optional, allows specifying the input format. Usually not necessary.
* @return bool true is successful, false if not.
*/
function create_thumbnail_convert($hash, $input_type = ""): bool
{
global $config;
$inname = warehouse_path("images", $hash);
$outname = warehouse_path("thumbs", $hash);
$inname = warehouse_path(Image::IMAGE_DIR, $hash);
$outname = warehouse_path(Image::THUMBNAIL_DIR, $hash);
$q = $config->get_int("thumb_quality");
$convert = $config->get_string("thumb_convert_path");
@ -187,9 +186,7 @@ function create_thumbnail_convert($hash): bool
//$cmd = sprintf($format, $convert, $inname);
//$size = shell_exec($cmd);
//$size = explode(" ", trim($size));
$tsize = get_thumbnail_max_size_scaled();
$w = $tsize[0];
$h = $tsize[1];
list($w, $h) = get_thumbnail_max_size_scaled();
// running the call with cmd.exe requires quoting for our paths
@ -204,13 +201,18 @@ function create_thumbnail_convert($hash): bool
if ($type=="webp") {
$bg = "none";
}
$format = '"%s" -flatten -strip -thumbnail %ux%u%s -quality %u -background %s "%s[0]" %s:"%s"';
$cmd = sprintf($format, $convert, $w, $h, $options, $q, $bg, $inname, $type, $outname);
if(!empty($input_type)) {
$input_type = $input_type.":";
}
$format = '"%s" -flatten -strip -thumbnail %ux%u%s -quality %u -background %s %s"%s[0]" %s:"%s" 2>&1';
$cmd = sprintf($format, $convert, $w, $h, $options, $q, $bg,$input_type, $inname, $type, $outname);
$cmd = str_replace("\"convert\"", "convert", $cmd); // quotes are only needed if the path to convert contains a space; some other times, quotes break things, see github bug #27
exec($cmd, $output, $ret);
log_debug('handle_pixel', "Generating thumbnail with command `$cmd`, returns $ret");
if ($ret!=0) {
log_warning('imageboard/misc', "Generating thumbnail with command `$cmd`, returns $ret, outputting ".implode("\r\n",$output));
} else {
log_debug('imageboard/misc', "Generating thumbnail with command `$cmd`, returns $ret");
}
if ($config->get_bool("thumb_optim", false)) {
exec("jpegoptim $outname", $output, $ret);
@ -219,6 +221,12 @@ function create_thumbnail_convert($hash): bool
return true;
}
/**
* Creates a thumbnail using ffmpeg.
*
* @param $hash
* @return bool true if successful, false if not.
*/
function create_thumbnail_ffmpeg($hash): bool
{
global $config;
@ -228,11 +236,11 @@ function create_thumbnail_ffmpeg($hash): bool
return false;
}
$inname = warehouse_path("images", $hash);
$outname = warehouse_path("thumbs", $hash);
$inname = warehouse_path(Image::IMAGE_DIR, $hash);
$outname = warehouse_path(Image::THUMBNAIL_DIR, $hash);
$orig_size = video_size($inname);
$scaled_size = get_thumbnail_size_scaled($orig_size[0], $orig_size[1]);
$scaled_size = get_thumbnail_size($orig_size[0], $orig_size[1], true);
$codec = "mjpeg";
$quality = $config->get_int("thumb_quality");
@ -270,6 +278,12 @@ function create_thumbnail_ffmpeg($hash): bool
}
}
/**
* Determines the dimensions of a video file using ffmpeg.
*
* @param string $filename
* @return array [width, height]
*/
function video_size(string $filename): array
{
global $config;
@ -307,6 +321,9 @@ function video_size(string $filename): array
*
* The factor of 2.5 is simply a rough guideline.
* http://stackoverflow.com/questions/527532/reasonable-php-memory-limit-for-image-resize
*
* @param array $info The output of getimagesize() for the source file in question.
* @return int The number of bytes an image resize operation is estimated to use.
*/
function calc_memory_use(array $info): int
{
@ -320,12 +337,25 @@ function calc_memory_use(array $info): int
return (int)$memory_use;
}
/**
* Performs a resize operation on an image file using GD.
*
* @param String $image_filename The source file to be resized.
* @param array $info The output of getimagesize() for the source file.
* @param int $new_width
* @param int $new_height
* @param string $output_filename
* @param string|null $output_type If set to null, the output file type will be automatically determined via the $info parameter. Otherwise an exception will be thrown.
* @param int $output_quality Defaults to 80.
* @throws ImageResizeException
* @throws InsufficientMemoryException if the estimated memory usage exceeds the memory limit.
*/
function image_resize_gd(
String $image_filename,
array $info,
int $new_width,
int $new_height,
string $output_filename=null,
string $output_filename,
string $output_type=null,
int $output_quality = 80
) {
@ -423,7 +453,7 @@ function image_resize_gd(
throw new ImageResizeException("Unable to copy resized image data to new image");
}
$result = false;
switch ($output_type) {
case "bmp":
$result = imagebmp($image_resized, $output_filename, true);
@ -453,15 +483,20 @@ function image_resize_gd(
}
}
function is_animated_gif(String $image_filename)
{
$isanigif = 0;
/**
* Determines if a file is an animated gif.
*
* @param String $image_filename The path of the file to check.
* @return bool true if the file is an animated gif, false if it is not.
*/
function is_animated_gif(String $image_filename) {
$is_anim_gif = 0;
if (($fh = @fopen($image_filename, 'rb'))) {
//check if gif is animated (via http://www.php.net/manual/en/function.imagecreatefromgif.php#104473)
while (!feof($fh) && $isanigif < 2) {
while (!feof($fh) && $is_anim_gif < 2) {
$chunk = fread($fh, 1024 * 100);
$isanigif += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches);
$is_anim_gif += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $chunk, $matches);
}
}
return ($isanigif == 0);
}
return ($is_anim_gif == 0);
}

View file

@ -26,6 +26,11 @@
* Various other common functions are available as part of the Themelet class.
*/
abstract class PageMode {
const REDIRECT = 'redirect';
const DATA = 'data';
const PAGE = 'page';
}
/**
* Class Page
@ -40,7 +45,7 @@ class Page
/** @name Overall */
//@{
/** @var string */
public $mode = "page";
public $mode = PageMode::PAGE;
/** @var string */
public $type = "text/html; charset=utf-8";
@ -261,7 +266,7 @@ class Page
}
switch ($this->mode) {
case "page":
case PageMode::PAGE:
if (CACHE_HTTP) {
header("Vary: Cookie, Accept-Encoding");
if ($user->is_anonymous() && $_SERVER["REQUEST_METHOD"] == "GET") {
@ -285,14 +290,14 @@ class Page
$layout = new Layout();
$layout->display_page($page);
break;
case "data":
case PageMode::DATA:
header("Content-Length: ".strlen($this->data));
if (!is_null($this->filename)) {
header('Content-Disposition: attachment; filename='.$this->filename);
}
print $this->data;
break;
case "redirect":
case PageMode::REDIRECT:
header('Location: '.$this->redirect);
print 'You should be redirected to <a href="'.$this->redirect.'">'.$this->redirect.'</a>';
break;

View file

@ -69,7 +69,7 @@ class User
global $config, $database;
$row = $database->cache->get("user-session:$name-$session");
if (!$row) {
if ($database->get_driver_name() === "mysql") {
if ($database->get_driver_name() === DatabaseDriver::MYSQL) {
$query = "SELECT * FROM users WHERE name = :name AND md5(concat(pass, :ip)) = :sess";
} else {
$query = "SELECT * FROM users WHERE name = :name AND md5(pass || :ip) = :sess";

View file

@ -163,10 +163,13 @@ function warehouse_path(string $base, string $hash, bool $create=true): string
{
$ab = substr($hash, 0, 2);
$cd = substr($hash, 2, 2);
$pa = Image::DATA_DIR.'/'.$base.'/';
if (WH_SPLITS == 2) {
$pa = 'data/'.$base.'/'.$ab.'/'.$cd.'/'.$hash;
$pa .= $ab.'/'.$cd.'/'.$hash;
} else {
$pa = 'data/'.$base.'/'.$ab.'/'.$hash;
$pa .= $ab.'/'.$hash;
}
if ($create && !file_exists(dirname($pa))) {
mkdir(dirname($pa), 0755, true);

View file

@ -70,7 +70,7 @@ class AdminPage extends Extension
}
if ($aae->redirect) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
}
}
@ -149,7 +149,7 @@ class AdminPage extends Extension
send_event(new ImageDeletionEvent($image));
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list"));
return false;
}
@ -201,14 +201,14 @@ class AdminPage extends Extension
$database = $matches['dbname'];
switch ($software) {
case 'mysql':
case DatabaseDriver::MYSQL:
$cmd = "mysqldump -h$hostname -u$username -p$password $database";
break;
case 'pgsql':
case DatabaseDriver::PGSQL:
putenv("PGPASSWORD=$password");
$cmd = "pg_dump -h $hostname -U $username $database";
break;
case 'sqlite':
case DatabaseDriver::SQLITE:
$cmd = "sqlite3 $database .dump";
break;
default:
@ -218,7 +218,7 @@ class AdminPage extends Extension
//FIXME: .SQL dump is empty if cmd doesn't exist
if ($cmd) {
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("application/x-unknown");
$page->set_filename('shimmie-'.date('Ymd').'.sql');
$page->set_data(shell_exec($cmd));
@ -237,13 +237,13 @@ class AdminPage extends Extension
$zip = new ZipArchive;
if ($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) === true) {
foreach ($images as $img) {
$img_loc = warehouse_path("images", $img["hash"], false);
$img_loc = warehouse_path(Image::IMAGE_DIR, $img["hash"], false);
$zip->addFile($img_loc, $img["hash"].".".$img["ext"]);
}
$zip->close();
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link($filename)); //TODO: Delete file after downloaded?
return false; // we do want a redirect, but a manual one
@ -257,7 +257,7 @@ class AdminPage extends Extension
//TODO: Update score_log (Having an optional ID column for score_log would be nice..)
preg_match("#^(?P<proto>\w+)\:(?:user=(?P<user>\w+)(?:;|$)|password=(?P<password>\w*)(?:;|$)|host=(?P<host>[\w\.\-]+)(?:;|$)|dbname=(?P<dbname>[\w_]+)(?:;|$))+#", DATABASE_DSN, $matches);
if ($matches['proto'] == "mysql") {
if ($matches['proto'] == DatabaseDriver::MYSQL) {
$tables = $database->get_col("SELECT TABLE_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = :db
@ -280,9 +280,9 @@ class AdminPage extends Extension
$i++;
}
$database->execute("ALTER TABLE images AUTO_INCREMENT=".(count($ids) + 1));
} elseif ($matches['proto'] == "pgsql") {
} elseif ($matches['proto'] == DatabaseDriver::PGSQL) {
//TODO: Make this work with PostgreSQL
} elseif ($matches['proto'] == "sqlite") {
} elseif ($matches['proto'] == DatabaseDriver::SQLITE) {
//TODO: Make this work with SQLite
}
return true;

View file

@ -45,7 +45,7 @@ class AdminPageTheme extends Themelet
$html .= $this->button("Download all images", "download_all_images", false);
}
$html .= $this->button("Download database contents", "database_dump", false);
if ($database->get_driver_name() == "mysql") {
if ($database->get_driver_name() == DatabaseDriver::MYSQL) {
$html .= $this->button("Reset image IDs", "reset_image_ids", true);
}
$page->add_block(new Block("Misc Admin Tools", $html));

View file

@ -41,7 +41,7 @@ class AliasEditor extends Extension
try {
$aae = new AddAliasEvent($_POST['oldtag'], $_POST['newtag']);
send_event($aae);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
} catch (AddAliasException $ex) {
$this->theme->display_error(500, "Error adding alias", $ex->getMessage());
@ -54,7 +54,7 @@ class AliasEditor extends Extension
$database->execute("DELETE FROM aliases WHERE oldtag=:oldtag", ["oldtag" => $_POST['oldtag']]);
log_info("alias_editor", "Deleted alias for ".$_POST['oldtag'], "Deleted alias");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
}
}
@ -80,7 +80,7 @@ class AliasEditor extends Extension
$this->theme->display_aliases($alias, $page_number + 1, $total_pages);
} elseif ($event->get_arg(0) == "export") {
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("text/csv");
$page->set_filename("aliases.csv");
$page->set_data($this->get_alias_csv($database));
@ -91,7 +91,7 @@ class AliasEditor extends Extension
$contents = file_get_contents($tmp);
$this->add_alias_csv($database, $contents);
log_info("alias_editor", "Imported aliases from file", "Imported aliases"); # FIXME: how many?
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("alias/list"));
} else {
$this->theme->display_error(400, "No File Specified", "You have to upload a file");

View file

@ -172,7 +172,7 @@ class Artists extends Extension
}
case "new_artist":
{
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/new"));
break;
}
@ -183,7 +183,7 @@ class Artists extends Extension
if ($newArtistID == -1) {
$this->theme->display_error(400, "Error", "Error when entering artist data.");
} else {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$newArtistID));
}
} else {
@ -238,7 +238,7 @@ class Artists extends Extension
case "edit_artist":
{
$artistID = $_POST['artist_id'];
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/edit/".$artistID));
break;
}
@ -246,14 +246,14 @@ class Artists extends Extension
{
$artistID = int_escape($_POST['id']);
$this->update_artist();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}
case "nuke_artist":
{
$artistID = $_POST['artist_id'];
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/nuke/".$artistID));
break;
}
@ -261,7 +261,7 @@ class Artists extends Extension
{
$artistID = $event->get_arg(1);
$this->delete_artist($artistID); // this will delete the artist, its alias, its urls and its members
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/list"));
break;
}
@ -291,7 +291,7 @@ class Artists extends Extension
{
$artistID = $_POST['artistID'];
$this->add_alias();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}
@ -300,7 +300,7 @@ class Artists extends Extension
$aliasID = $event->get_arg(2);
$artistID = $this->get_artistID_by_aliasID($aliasID);
$this->delete_alias($aliasID);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}
@ -316,7 +316,7 @@ class Artists extends Extension
$this->update_alias();
$aliasID = int_escape($_POST['aliasID']);
$artistID = $this->get_artistID_by_aliasID($aliasID);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}
@ -332,7 +332,7 @@ class Artists extends Extension
{
$artistID = $_POST['artistID'];
$this->add_urls();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}
@ -341,7 +341,7 @@ class Artists extends Extension
$urlID = $event->get_arg(2);
$artistID = $this->get_artistID_by_urlID($urlID);
$this->delete_url($urlID);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}
@ -357,7 +357,7 @@ class Artists extends Extension
$this->update_url();
$urlID = int_escape($_POST['urlID']);
$artistID = $this->get_artistID_by_urlID($urlID);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}
@ -372,7 +372,7 @@ class Artists extends Extension
{
$artistID = $_POST['artistID'];
$this->add_members();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}
@ -381,7 +381,7 @@ class Artists extends Extension
$memberID = int_escape($event->get_arg(2));
$artistID = $this->get_artistID_by_memberID($memberID);
$this->delete_member($memberID);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}
@ -397,7 +397,7 @@ class Artists extends Extension
$this->update_member();
$memberID = int_escape($_POST['memberID']);
$artistID = $this->get_artistID_by_memberID($memberID);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("artist/view/".$artistID));
break;
}

View file

@ -21,7 +21,7 @@ class AutoComplete extends Extension
return;
}
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("application/json");
$s = strtolower($_GET["s"]);

View file

@ -61,7 +61,7 @@ class Blocks extends Extension
", [$_POST['pages'], $_POST['title'], $_POST['area'], (int)$_POST['priority'], $_POST['content']]);
log_info("blocks", "Added Block #".($database->get_last_insert_id('blocks_id_seq'))." (".$_POST['title'].")");
$database->cache->delete("blocks");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blocks/list"));
}
}
@ -81,7 +81,7 @@ class Blocks extends Extension
log_info("blocks", "Updated Block #".$_POST['id']." (".$_POST['title'].")");
}
$database->cache->delete("blocks");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blocks/list"));
}
} elseif ($event->get_arg(0) == "list") {

View file

@ -102,7 +102,7 @@ class Blotter extends Extension
[$entry_text, $important]
);
log_info("blotter", "Added Message: $entry_text");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blotter/editor"));
}
break;
@ -119,7 +119,7 @@ class Blotter extends Extension
}
$database->Execute("DELETE FROM blotter WHERE id=:id", ["id"=>$id]);
log_info("blotter", "Removed Entry #$id");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("blotter/editor"));
}
break;

View file

@ -54,7 +54,7 @@ class BrowserSearch extends Extension
";
// And now to send it to the browser
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("text/xml");
$page->set_data($xml);
} elseif (
@ -85,7 +85,7 @@ class BrowserSearch extends Extension
// And now for the final output
$json_string = "[\"$tag_search\",[\"$json_tag_list\"],[],[]]";
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_data($json_string);
}
}

View file

@ -171,7 +171,7 @@ class BulkActions extends Extension
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
if (!isset($_SERVER['HTTP_REFERER'])) {
$_SERVER['HTTP_REFERER'] = make_link();
}

View file

@ -81,7 +81,7 @@ class BulkAddCSV extends Extension
send_event($ratingevent);
}
if (file_exists($thumbfile)) {
copy($thumbfile, warehouse_path("thumbs", $event->hash));
copy($thumbfile, warehouse_path(Image::THUMBNAIL_DIR, $event->hash));
}
}
}

View file

@ -178,7 +178,7 @@ class CommentList extends Extension
$i_iid = int_escape($_POST['image_id']);
$cpe = new CommentPostingEvent($_POST['image_id'], $user, $_POST['comment']);
send_event($cpe);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$i_iid#comment_on_$i_iid"));
} catch (CommentPostingException $ex) {
$this->theme->display_error(403, "Comment Blocked", $ex->getMessage());
@ -194,7 +194,7 @@ class CommentList extends Extension
if ($event->count_args() === 3) {
send_event(new CommentDeletionEvent($event->get_arg(1)));
flash_message("Deleted comment");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
if (!empty($_SERVER['HTTP_REFERER'])) {
$page->set_redirect($_SERVER['HTTP_REFERER']);
} else {
@ -224,7 +224,7 @@ class CommentList extends Extension
}
flash_message("Deleted $num comments");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
} else {
$this->theme->display_permission_denied();
@ -480,14 +480,14 @@ class CommentList extends Extension
global $config, $database;
// sqlite fails at intervals
if ($database->get_driver_name() === "sqlite") {
if ($database->get_driver_name() === DatabaseDriver::SQLITE) {
return false;
}
$window = int_escape($config->get_int('comment_window'));
$max = int_escape($config->get_int('comment_limit'));
if ($database->get_driver_name() == "mysql") {
if ($database->get_driver_name() == DatabaseDriver::MYSQL) {
$window_sql = "interval $window minute";
} else {
$window_sql = "interval '$window minute'";

View file

@ -1,42 +1,52 @@
<?php
/*
* Name: Cron Uploader
* Author: YaoiFox <admin@yaoifox.com>
* Authors: YaoiFox <admin@yaoifox.com>, Matthew Barbour <matthew@darkholme.net>
* Link: http://www.yaoifox.com/
* License: GPLv2
* Description: Uploads images automatically using Cron Jobs
* Documentation: Installation guide: activate this extension and navigate to www.yoursite.com/cron_upload
*/
class CronUploader extends Extension
{
// TODO: Checkbox option to only allow localhost + a list of additional IP adresses that can be set in /cron_upload
// TODO: Change logging to MySQL + display log at /cron_upload
// TODO: Move stuff to theme.php
const QUEUE_DIR = "queue";
const UPLOADED_DIR = "uploaded";
const FAILED_DIR = "failed_to_upload";
const CONFIG_KEY = "cron_uploader_key";
const CONFIG_COUNT = "cron_uploader_count";
const CONFIG_DIR = "cron_uploader_dir";
/**
* Lists all log events this session
* @var string
*/
private $upload_info = "";
/**
* Lists all files & info required to upload.
* @var array
*/
private $image_queue = [];
/**
* Cron Uploader root directory
* @var string
*/
private $root_dir = "";
/**
* Key used to identify uploader
* @var string
*/
private $upload_key = "";
/**
* Checks if the cron upload page has been accessed
* and initializes the upload.
@ -44,39 +54,50 @@ class CronUploader extends Extension
public function onPageRequest(PageRequestEvent $event)
{
global $config, $user;
if ($event->page_matches("cron_upload")) {
$this->upload_key = $config->get_string("cron_uploader_key", "");
$this->upload_key = $config->get_string(self::CONFIG_KEY, "");
// If the key is in the url, upload
if ($this->upload_key != "" && $event->get_arg(0) == $this->upload_key) {
// log in as admin
$this->process_upload(); // Start upload
$this->set_dir();
$lockfile = fopen($this->root_dir . "/.lock", "w");
if (!flock($lockfile, LOCK_EX | LOCK_NB)) {
throw new Exception("Cron upload process is already running");
}
try {
$this->process_upload(); // Start upload
} finally {
flock($lockfile, LOCK_UN);
fclose($lockfile);
}
} elseif ($user->is_admin()) {
$this->set_dir();
$this->display_documentation();
}
}
}
private function display_documentation()
{
global $page;
$this->set_dir(); // Determines path to cron_uploader_dir
$queue_dir = $this->root_dir . "/queue";
$uploaded_dir = $this->root_dir . "/uploaded";
$failed_dir = $this->root_dir . "/failed_to_upload";
$queue_dir = $this->root_dir . "/" . self::QUEUE_DIR;
$uploaded_dir = $this->root_dir . "/" . self::UPLOADED_DIR;
$failed_dir = $this->root_dir . "/" . self::FAILED_DIR;
$queue_dirinfo = $this->scan_dir($queue_dir);
$uploaded_dirinfo = $this->scan_dir($uploaded_dir);
$failed_dirinfo = $this->scan_dir($failed_dir);
$cron_url = make_http(make_link("/cron_upload/" . $this->upload_key));
$cron_cmd = "curl --silent $cron_url";
$log_path = $this->root_dir . "/uploads.log";
$info_html = "<b>Information</b>
<br>
<table style='width:470px;'>
@ -105,7 +126,7 @@ class CronUploader extends Extension
<br>Cron Command: <input type='text' size='60' value='$cron_cmd'><br>
Create a cron job with the command above.<br/>
Read the documentation if you're not sure what to do.<br>";
$install_html = "
This cron uploader is fairly easy to use but has to be configured first.
<br />1. Install & activate this plugin.
@ -130,8 +151,10 @@ class CronUploader extends Extension
<br />So when you want to manually upload an image, all you have to do is open the link once.
<br />This link can be found under 'Cron Command' in the board config, just remove the 'wget ' part and only the url remains.
<br />(<b>$cron_url</b>)";
$page->set_title("Cron Uploader");
$page->set_heading("Cron Uploader");
$block = new Block("Cron Uploader", $info_html, "main", 10);
$block_install = new Block("Installation Guide", $install_html, "main", 20);
$page->add_block($block);
@ -142,36 +165,37 @@ class CronUploader extends Extension
{
global $config;
// Set default values
$this->upload_key = $config->get_string("cron_uploader_key", "");
if (strlen($this->upload_key)<=0) {
$config->set_default_int(self::CONFIG_COUNT, 1);
$this->set_dir();
$this->upload_key = $config->get_string(self::CONFIG_KEY, "");
if (empty($this->upload_key)) {
$this->upload_key = $this->generate_key();
$config->set_default_int('cron_uploader_count', 1);
$config->set_default_string('cron_uploader_key', $this->upload_key);
$this->set_dir();
$config->set_string(self::CONFIG_KEY, $this->upload_key);
}
}
public function onSetupBuilding(SetupBuildingEvent $event)
{
$this->set_dir();
$cron_url = make_http(make_link("/cron_upload/" . $this->upload_key));
$cron_cmd = "curl --silent $cron_url";
$documentation_link = make_http(make_link("cron_upload"));
$sb = new SetupBlock("Cron Uploader");
$sb->add_label("<b>Settings</b><br>");
$sb->add_int_option("cron_uploader_count", "How many to upload each time");
$sb->add_text_option("cron_uploader_dir", "<br>Set Cron Uploader root directory<br>");
$sb->add_label("<br>Cron Command: <input type='text' size='60' value='$cron_cmd'><br>
$sb->add_int_option(self::CONFIG_COUNT, "How many to upload each time");
$sb->add_text_option(self::CONFIG_DIR, "<br>Set Cron Uploader root directory<br>");
$sb->add_label("<br>Cron Command: <input type='text' size='60' readonly='readonly' value='" . html_escape($cron_cmd) . "'><br>
Create a cron job with the command above.<br/>
<a href='$documentation_link'>Read the documentation</a> if you're not sure what to do.");
$event->panel->add_block($sb);
}
/*
* Generates a unique key for the website to prevent unauthorized access.
*/
@ -180,14 +204,14 @@ class CronUploader extends Extension
$length = 20;
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for ($i = 0; $i < $length; $i ++) {
for ($i = 0; $i < $length; $i++) {
$randomString .= $characters [rand(0, strlen($characters) - 1)];
}
return $randomString;
}
/*
* Set the directory for the image queue. If no directory was given, set it to the default directory.
*/
@ -195,50 +219,50 @@ class CronUploader extends Extension
{
global $config;
// Determine directory (none = default)
$dir = $config->get_string("cron_uploader_dir", "");
$dir = $config->get_string(self::CONFIG_DIR, "");
// Sets new default dir if not in config yet/anymore
if ($dir == "") {
$dir = data_path("cron_uploader");
$config->set_string('cron_uploader_dir', $dir);
$config->set_string(self::CONFIG_DIR, $dir);
}
// Make the directory if it doesn't exist yet
if (!is_dir($dir . "/queue/")) {
mkdir($dir . "/queue/", 0775, true);
if (!is_dir($dir . "/" . self::QUEUE_DIR . "/")) {
mkdir($dir . "/" . self::QUEUE_DIR . "/", 0775, true);
}
if (!is_dir($dir . "/uploaded/")) {
mkdir($dir . "/uploaded/", 0775, true);
if (!is_dir($dir . "/" . self::UPLOADED_DIR . "/")) {
mkdir($dir . "/" . self::UPLOADED_DIR . "/", 0775, true);
}
if (!is_dir($dir . "/failed_to_upload/")) {
mkdir($dir . "/failed_to_upload/", 0775, true);
if (!is_dir($dir . "/" . self::FAILED_DIR . "/")) {
mkdir($dir . "/" . self::FAILED_DIR . "/", 0775, true);
}
$this->root_dir = $dir;
return $dir;
}
/**
* Returns amount of files & total size of dir.
*/
public function scan_dir(string $path): array
{
$bytestotal=0;
$nbfiles=0;
$bytestotal = 0;
$nbfiles = 0;
$ite=new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
foreach (new RecursiveIteratorIterator($ite) as $filename=>$cur) {
$ite = new RecursiveDirectoryIterator($path, FilesystemIterator::SKIP_DOTS);
foreach (new RecursiveIteratorIterator($ite) as $filename => $cur) {
$filesize = $cur->getSize();
$bytestotal += $filesize;
$nbfiles++;
}
$size_mb = $bytestotal / 1048576; // to mb
$size_mb = number_format($size_mb, 2, '.', '');
return ['total_files'=>$nbfiles,'total_mb'=>$size_mb];
return ['total_files' => $nbfiles, 'total_mb' => $size_mb];
}
/**
* Uploads the image & handles everything
*/
@ -246,24 +270,24 @@ class CronUploader extends Extension
{
global $config, $database;
set_time_limit(0);
//set_time_limit(0);
$output_subdir = date('Ymd-His', time())."/";
$this->set_dir();
$output_subdir = date('Ymd-His', time()) . "/";
$this->generate_image_queue();
// Gets amount of imgs to upload
if ($upload_count == 0) {
$upload_count = $config->get_int("cron_uploader_count", 1);
$upload_count = $config->get_int(self::CONFIG_COUNT, 1);
}
// Throw exception if there's nothing in the queue
if (count($this->image_queue) == 0) {
$this->add_upload_info("Your queue is empty so nothing could be uploaded.");
$this->handle_log();
return false;
}
// Randomize Images
//shuffle($this->image_queue);
@ -271,18 +295,17 @@ class CronUploader extends Extension
$added = 0;
$failed = 0;
$failedItems = [];
// Upload the file(s)
for ($i = 0; $i < $upload_count && sizeof($this->image_queue)>0; $i++) {
for ($i = 0; $i < $upload_count && sizeof($this->image_queue) > 0; $i++) {
$img = array_pop($this->image_queue);
try {
$database->beginTransaction();
$this->add_upload_info("Adding file: {$img[1]} - tags: {$img[2]}");
$result = $this->add_image($img[0], $img[1], $img[2]);
$database->commit();
$this->move_uploaded($img[0], $img[1], $output_subdir, false);
if ($result==null) {
if ($result->merged) {
$merged++;
} else {
$added++;
@ -290,13 +313,9 @@ class CronUploader extends Extension
} catch (Exception $e) {
$failed++;
$this->move_uploaded($img[0], $img[1], $output_subdir, true);
$msgNumber = $this->add_upload_info("(".gettype($e).") ".$e->getMessage());
$msgNumber = $this->add_upload_info("(" . gettype($e) . ") " . $e->getMessage());
$msgNumber = $this->add_upload_info($e->getTraceAsString());
if (strpos($e->getMessage(), 'SQLSTATE') !== false) {
// Postgres invalidates the transaction if there is an SQL error,
// so all subsequence transactions will fail.
break;
}
try {
$database->rollback();
} catch (Exception $e) {
@ -310,85 +329,95 @@ class CronUploader extends Extension
$msgNumber = $this->add_upload_info("Items failed: $failed");
// Display & save upload log
$this->handle_log();
return true;
}
private function move_uploaded($path, $filename, $output_subdir, $corrupt = false)
{
global $config;
// Create
$newDir = $this->root_dir;
$relativeDir = dirname(substr($path, strlen($this->root_dir) + 7));
// Determine which dir to move to
if ($corrupt) {
// Move to corrupt dir
$newDir .= "/failed_to_upload/".$output_subdir.$relativeDir;
$newDir .= "/" . self::FAILED_DIR . "/" . $output_subdir . $relativeDir;
$info = "ERROR: Image was not uploaded.";
} else {
$newDir .= "/uploaded/".$output_subdir.$relativeDir;
$newDir .= "/" . self::UPLOADED_DIR . "/" . $output_subdir . $relativeDir;
$info = "Image successfully uploaded. ";
}
$newDir = str_replace("//", "/", $newDir."/");
$newDir = str_replace("//", "/", $newDir . "/");
if (!is_dir($newDir)) {
mkdir($newDir, 0775, true);
}
// move file to correct dir
rename($path, $newDir.$filename);
rename($path, $newDir . $filename);
$this->add_upload_info($info . "Image \"$filename\" moved from queue to \"$newDir\".");
}
/**
* Generate the necessary DataUploadEvent for a given image and tags.
*/
private function add_image(string $tmpname, string $filename, string $tags)
private function add_image(string $tmpname, string $filename, string $tags): DataUploadEvent
{
assert(file_exists($tmpname));
$tagArray = Tag::explode($tags);
if(count($tagArray)==0) {
$tagArray[] = "tagme";
}
$pathinfo = pathinfo($filename);
$metadata = [];
$metadata ['filename'] = $pathinfo ['basename'];
if (array_key_exists('extension', $pathinfo)) {
$metadata ['extension'] = $pathinfo ['extension'];
}
$metadata ['tags'] = Tag::explode($tags);
$metadata ['tags'] = $tagArray; // doesn't work when not logged in here, handled below
$metadata ['source'] = null;
$event = new DataUploadEvent($tmpname, $metadata);
send_event($event);
// Generate info message
$infomsg = ""; // Will contain info message
if ($event->image_id == -1) {
throw new Exception("File type not recognised. Filename: {$filename}");
} elseif ($event->image_id == null) {
$infomsg = "Image merged. Filename: {$filename}";
} elseif ($event->merged === true) {
$infomsg = "Image merged. ID: {$event->image_id} Filename: {$filename}";
} else {
$infomsg = "Image uploaded. ID: {$event->image_id} - Filename: {$filename}";
}
$msgNumber = $this->add_upload_info($infomsg);
return $event->image_id;
// Set tags
$img = Image::by_id($event->image_id);
$img->set_tags(array_merge($tagArray, $img->get_tag_array()));
return $event;
}
private function generate_image_queue(): void
{
$base = $this->root_dir . "/queue";
if (! is_dir($base)) {
$base = $this->root_dir . "/" . self::QUEUE_DIR;
if (!is_dir($base)) {
$this->add_upload_info("Image Queue Directory could not be found at \"$base\".");
return;
}
$ite=new RecursiveDirectoryIterator($base, FilesystemIterator::SKIP_DOTS);
foreach (new RecursiveIteratorIterator($ite) as $fullpath=>$cur) {
$ite = new RecursiveDirectoryIterator($base, FilesystemIterator::SKIP_DOTS);
foreach (new RecursiveIteratorIterator($ite) as $fullpath => $cur) {
if (!is_link($fullpath) && !is_dir($fullpath)) {
$pathinfo = pathinfo($fullpath);
@ -396,62 +425,62 @@ class CronUploader extends Extension
$tags = path_to_tags($relativePath);
$img = [
0 => $fullpath,
1 => $pathinfo ["basename"],
2 => $tags
0 => $fullpath,
1 => $pathinfo ["basename"],
2 => $tags
];
array_push($this->image_queue, $img);
}
}
}
/**
* Adds a message to the info being published at the end
*/
private function add_upload_info(string $text, int $addon = 0): int
{
$info = $this->upload_info;
$time = "[" .date('Y-m-d H:i:s'). "]";
$time = "[" . date('Y-m-d H:i:s') . "]";
// If addon function is not used
if ($addon == 0) {
$this->upload_info .= "$time $text\r\n";
$this->upload_info .= "$time $text\r\n";
// Returns the number of the current line
$currentLine = substr_count($this->upload_info, "\n") -1;
$currentLine = substr_count($this->upload_info, "\n") - 1;
return $currentLine;
}
// else if addon function is used, select the line & modify it
$lines = substr($info, "\n"); // Seperate the string to array in lines
$lines[$addon] = "$lines[$addon] $text"; // Add the content to the line
$this->upload_info = implode("\n", $lines); // Put string back together & update
return $addon; // Return line number
}
/**
* This is run at the end to display & save the log.
*/
private function handle_log()
{
global $page;
// Display message
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("text/plain");
$page->set_data($this->upload_info);
// Save log
$log_path = $this->root_dir . "/uploads.log";
if (file_exists($log_path)) {
$prev_content = file_get_contents($log_path);
} else {
$prev_content = "";
}
$content = $prev_content ."\r\n".$this->upload_info;
$content = $prev_content . "\r\n" . $this->upload_info;
file_put_contents($log_path, $content);
}
}

View file

@ -60,7 +60,7 @@ class DanbooruApi extends Extension
private function api_danbooru(PageRequestEvent $event)
{
global $page;
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
if (($event->get_arg(1) == 'add_post') || (($event->get_arg(1) == 'post') && ($event->get_arg(2) == 'create.xml'))) {
// No XML data is returned from this function
@ -80,7 +80,7 @@ class DanbooruApi extends Extension
// This redirects that to http://shimmie/post/view/123
elseif (($event->get_arg(1) == 'post') && ($event->get_arg(2) == 'show')) {
$fixedlocation = make_link("post/view/" . $event->get_arg(3));
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect($fixedlocation);
}
}

View file

@ -26,7 +26,7 @@ class DowntimeTheme extends Themelet
$login_link = make_link("user_admin/login");
$auth = $user->get_auth_html();
$page->set_mode('data');
$page->set_mode(PageMode::DATA);
$page->set_code(503);
$page->set_data(
<<<EOD

View file

@ -18,7 +18,7 @@ class EmoticonListTheme extends Themelet
}
$html .= "</tr></table>";
$html .= "</body></html>";
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_data($html);
}
}

View file

@ -22,8 +22,7 @@ class ExtensionInfo
public $ext_name;
public $name;
public $link;
public $author;
public $email;
public $authors;
public $description;
public $documentation;
public $version;
@ -39,8 +38,9 @@ class ExtensionInfo
$this->ext_name = $matches[1];
$this->name = $this->ext_name;
$this->enabled = $this->is_enabled($this->ext_name);
$this->authors = [];
for ($i=0; $i<$number_of_lines; $i++) {
for ($i = 0; $i < $number_of_lines; $i++) {
$line = $lines[$i];
if (preg_match("/Name: (.*)/", $line, $matches)) {
$this->name = $matches[1];
@ -53,25 +53,31 @@ class ExtensionInfo
}
} elseif (preg_match("/Version: (.*)/", $line, $matches)) {
$this->version = $matches[1];
} elseif (preg_match("/Author: (.*) [<\(](.*@.*)[>\)]/", $line, $matches)) {
$this->author = $matches[1];
$this->email = $matches[2];
} elseif (preg_match("/Author: (.*)/", $line, $matches)) {
$this->author = $matches[1];
} elseif (preg_match("/Authors?: (.*)/", $line, $matches)) {
$author_list = explode(',', $matches[1]);
foreach ($author_list as $author) {
if (preg_match("/(.*) [<\(](.*@.*)[>\)]/", $author, $matches)) {
$this->authors[] = new ExtensionAuthor($matches[1], $matches[2]);
} else {
$this->authors[] = new ExtensionAuthor($author, null);
}
}
} elseif (preg_match("/(.*)Description: ?(.*)/", $line, $matches)) {
$this->description = $matches[2];
$start = $matches[1]." ";
$start = $matches[1] . " ";
$start_len = strlen($start);
while (substr($lines[$i+1], 0, $start_len) == $start) {
$this->description .= " ".substr($lines[$i+1], $start_len);
while (substr($lines[$i + 1], 0, $start_len) == $start) {
$this->description .= " " . substr($lines[$i + 1], $start_len);
$i++;
}
} elseif (preg_match("/(.*)Documentation: ?(.*)/", $line, $matches)) {
$this->documentation = $matches[2];
$start = $matches[1]." ";
$start = $matches[1] . " ";
$start_len = strlen($start);
while (substr($lines[$i+1], 0, $start_len) == $start) {
$this->documentation .= " ".substr($lines[$i+1], $start_len);
while (substr($lines[$i + 1], 0, $start_len) == $start) {
$this->documentation .= " " . substr($lines[$i + 1], $start_len);
$i++;
}
$this->documentation = str_replace('$site', make_http(get_base_href()), $this->documentation);
@ -96,6 +102,18 @@ class ExtensionInfo
}
}
class ExtensionAuthor
{
public $name;
public $email;
public function __construct(string $name, ?string $email)
{
$this->name = $name;
$this->email = $email;
}
}
class ExtManager extends Extension
{
public function onPageRequest(PageRequestEvent $event)
@ -107,7 +125,7 @@ class ExtManager extends Extension
if (is_writable("data/config")) {
$this->set_things($_POST);
log_warning("ext_manager", "Active extensions changed", "Active extensions changed");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ext_manager"));
} else {
$this->theme->display_error(
@ -166,7 +184,7 @@ class ExtManager extends Extension
if ($all) {
$exts = zglob("ext/*/main.php");
} else {
$exts = zglob("ext/{".ENABLED_EXTS."}/main.php");
$exts = zglob("ext/{" . ENABLED_EXTS . "}/main.php");
}
foreach ($exts as $main) {
$extensions[] = new ExtensionInfo($main);
@ -200,9 +218,9 @@ class ExtManager extends Extension
{
file_put_contents(
"data/config/extensions.conf.php",
'<'.'?php'."\n".
'define("EXTRA_EXTS", "'.implode(",", $extras).'");'."\n".
'?'.">"
'<' . '?php' . "\n" .
'define("EXTRA_EXTS", "' . implode(",", $extras) . '");' . "\n" .
'?' . ">"
);
// when the list of active extensions changes, we can be

View file

@ -9,7 +9,7 @@ class ExtManagerTheme extends Themelet
{
$h_en = $editable ? "<th>Enabled</th>" : "";
$html = "
".make_form(make_link("ext_manager/set"))."
" . make_form(make_link("ext_manager/set")) . "
<table id='extensions' class='zebra sortable'>
<thead>
<tr>
@ -26,17 +26,17 @@ class ExtManagerTheme extends Themelet
continue;
}
$h_name = html_escape(empty($extension->name) ? $extension->ext_name : $extension->name);
$h_name = html_escape(empty($extension->name) ? $extension->ext_name : $extension->name);
$h_description = html_escape($extension->description);
$h_link = make_link("ext_doc/".url_escape($extension->ext_name));
$h_enabled = ($extension->enabled === true ? " checked='checked'" : ($extension->enabled === false ? "" : " disabled checked='checked'"));
$h_enabled_box = $editable ? "<td><input type='checkbox' name='ext_".html_escape($extension->ext_name)."' id='ext_".html_escape($extension->ext_name)."'$h_enabled></td>" : "";
$h_docs = ($extension->documentation ? "<a href='$h_link'>■</a>" : ""); //TODO: A proper "docs" symbol would be preferred here.
$h_link = make_link("ext_doc/" . url_escape($extension->ext_name));
$h_enabled = ($extension->enabled === true ? " checked='checked'" : ($extension->enabled === false ? "" : " disabled checked='checked'"));
$h_enabled_box = $editable ? "<td><input type='checkbox' name='ext_" . html_escape($extension->ext_name) . "' id='ext_" . html_escape($extension->ext_name) . "'$h_enabled></td>" : "";
$h_docs = ($extension->documentation ? "<a href='$h_link'>■</a>" : ""); //TODO: A proper "docs" symbol would be preferred here.
$html .= "
<tr data-ext='{$extension->ext_name}'>
{$h_enabled_box}
<td><label for='ext_".html_escape($extension->ext_name)."'>{$h_name}</label></td>
<td><label for='ext_" . html_escape($extension->ext_name) . "'>{$h_name}</label></td>
<td>{$h_docs}</td>
<td style='text-align: left;'>{$h_description}</td>
</tr>";
@ -116,15 +116,24 @@ class ExtManagerTheme extends Themelet
public function display_doc(Page $page, ExtensionInfo $info)
{
$author = "";
if ($info->author) {
if ($info->email) {
$author = "<br><b>Author:</b> <a href=\"mailto:".html_escape($info->email)."\">".html_escape($info->author)."</a>";
} else {
$author = "<br><b>Author:</b> ".html_escape($info->author);
if (count($info->authors) > 0) {
$author = "<br /><b>Author";
if (count($info->authors) > 1) {
$author .= "s";
}
$author .= ":</b>";
foreach ($info->authors as $auth) {
if (!empty($auth->email)) {
$author .= "<a href=\"mailto:" . html_escape($auth->email) . "\">" . html_escape($auth->name) . "</a>";
} else {
$author .= html_escape($auth->name);
}
}
}
$version = ($info->version) ? "<br><b>Version:</b> ".html_escape($info->version) : "";
$link = ($info->link) ? "<br><b>Home Page:</b> <a href=\"".html_escape($info->link)."\">Link</a>" : "";
$version = ($info->version) ? "<br><b>Version:</b> " . html_escape($info->version) : "";
$link = ($info->link) ? "<br><b>Home Page:</b> <a href=\"" . html_escape($info->link) . "\">Link</a>" : "";
$doc = $info->documentation;
$html = "
<div style='margin: auto; text-align: left; width: 512px;'>
@ -133,10 +142,10 @@ class ExtManagerTheme extends Themelet
$link
<p>$doc
<hr>
<p><a href='".make_link("ext_manager")."'>Back to the list</a>
<p><a href='" . make_link("ext_manager") . "'>Back to the list</a>
</div>";
$page->set_title("Documentation for ".html_escape($info->name));
$page->set_title("Documentation for " . html_escape($info->name));
$page->set_heading(html_escape($info->name));
$page->add_block(new NavBlock());
$page->add_block(new Block("Documentation", $html));

View file

@ -81,7 +81,7 @@ class Favorites extends Extension
log_debug("favourite", "Favourite removed for $image_id", "Favourite removed");
}
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
}

View file

@ -37,7 +37,7 @@ class Featured extends Extension
if ($id > 0) {
$config->set_int("featured_id", $id);
log_info("featured", "Featured image set to $id", "Featured image set");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$id"));
}
}
@ -45,7 +45,7 @@ class Featured extends Extension
if ($event->get_arg(0) == "download") {
$image = Image::by_id($config->get_int("featured_id"));
if (!is_null($image)) {
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type($image->get_mime_type());
$page->set_data(file_get_contents($image->get_image_filename()));
}

View file

@ -139,7 +139,7 @@ class Forum extends Extension
$redirectTo = "forum/view/".$newThreadID."/1";
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link($redirectTo));
break;
@ -151,7 +151,7 @@ class Forum extends Extension
$this->delete_post($postID);
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/view/".$threadID));
break;
case "nuke":
@ -161,7 +161,7 @@ class Forum extends Extension
$this->delete_thread($threadID);
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/index"));
break;
case "answer":
@ -176,11 +176,11 @@ class Forum extends Extension
}
$this->save_new_post($threadID, $user);
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/view/".$threadID."/".$total_pages));
break;
default:
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("forum/index"));
//$this->theme->display_error(400, "Invalid action", "You should check forum/index.");
break;

View file

@ -14,7 +14,7 @@ class Handle404 extends Extension
{
global $config, $page;
// hax.
if ($page->mode == "page" && (!isset($page->blocks) || $this->count_main($page->blocks) == 0)) {
if ($page->mode == PageMode::PAGE && (!isset($page->blocks) || $this->count_main($page->blocks) == 0)) {
$h_pagename = html_escape(implode('/', $event->args));
log_debug("handle_404", "Hit 404: $h_pagename");
$page->set_code(404);

View file

@ -8,12 +8,12 @@
class FlashFileHandler extends DataHandlerExtension
{
protected function create_thumb(string $hash): bool
protected function create_thumb(string $hash, string $type): bool
{
global $config;
if (!create_thumbnail_ffmpeg($hash)) {
copy("ext/handle_flash/thumb.jpg", warehouse_path("thumbs", $hash));
copy("ext/handle_flash/thumb.jpg", warehouse_path(Image::THUMBNAIL_DIR, $hash));
}
return true;
}

View file

@ -5,65 +5,45 @@
* Description: Handle windows icons
*/
class IcoFileHandler extends Extension
class IcoFileHandler extends DataHandlerExtension
{
public function onDataUpload(DataUploadEvent $event)
const SUPPORTED_EXTENSIONS = ["ico", "ani", "cur"];
protected function supported_ext(string $ext): bool
{
if ($this->supported_ext($event->type) && $this->check_contents($event->tmpname)) {
$hash = $event->hash;
$ha = substr($hash, 0, 2);
move_upload_to_archive($event);
send_event(new ThumbnailGenerationEvent($event->hash, $event->type));
$image = $this->create_image_from_data("images/$ha/$hash", $event->metadata);
if (is_null($image)) {
throw new UploadException("Icon handler failed to create image object from data");
}
$iae = new ImageAdditionEvent($image);
send_event($iae);
$event->image_id = $iae->image->id;
}
return in_array(strtolower($ext), self::SUPPORTED_EXTENSIONS);
}
public function onDisplayingImage(DisplayingImageEvent $event)
{
global $page;
if ($this->supported_ext($event->image->ext)) {
$this->theme->display_image($page, $event->image);
}
}
private function supported_ext(string $ext): bool
{
$exts = ["ico", "ani", "cur"];
return in_array(strtolower($ext), $exts);
}
private function create_image_from_data(string $filename, array $metadata)
protected function create_image_from_data(string $filename, array $metadata)
{
$image = new Image();
$fp = fopen($filename, "r");
$header = unpack("Snull/Stype/Scount", fread($fp, 6));
$subheader = unpack("Cwidth/Cheight/Ccolours/Cnull/Splanes/Sbpp/Lsize/loffset", fread($fp, 16));
fclose($fp);
$fp = fopen($filename, "r");
try {
unpack("Snull/Stype/Scount", fread($fp, 6));
$subheader = unpack("Cwidth/Cheight/Ccolours/Cnull/Splanes/Sbpp/Lsize/loffset", fread($fp, 16));
} finally {
fclose($fp);
}
$width = $subheader['width'];
$height = $subheader['height'];
$image->width = $width == 0 ? 256 : $width;
$image->height = $height == 0 ? 256 : $height;
$image->filesize = $metadata['size'];
$image->hash = $metadata['hash'];
$image->filename = $metadata['filename'];
$image->ext = $metadata['extension'];
$image->filesize = $metadata['size'];
$image->hash = $metadata['hash'];
$image->filename = $metadata['filename'];
$image->ext = $metadata['extension'];
$image->tag_array = is_array($metadata['tags']) ? $metadata['tags'] : Tag::explode($metadata['tags']);
$image->source = $metadata['source'];
$image->source = $metadata['source'];
return $image;
}
private function check_contents(string $file): bool
protected function check_contents(string $file): bool
{
if (!file_exists($file)) {
return false;
@ -74,27 +54,8 @@ class IcoFileHandler extends Extension
return ($header['null'] == 0 && ($header['type'] == 0 || $header['type'] == 1));
}
private function create_thumb(string $hash): bool
protected function create_thumb(string $hash, string $type): bool
{
global $config;
$inname = warehouse_path("images", $hash);
$outname = warehouse_path("thumbs", $hash);
$tsize = get_thumbnail_size_scaled($width, $height);
$w = $tsize[0];
$h = $tsise[1];
$q = $config->get_int("thumb_quality");
$mem = $config->get_int("thumb_mem_limit") / 1024 / 1024; // IM takes memory in MB
if ($config->get_bool("ico_convert")) {
// "-limit memory $mem" broken?
exec("convert {$inname}[0] -geometry {$w}x{$h} -quality {$q} jpg:$outname");
} else {
copy($inname, $outname);
}
return true;
return create_thumbnail_convert($hash, $type);
}
}

View file

@ -7,9 +7,9 @@
class MP3FileHandler extends DataHandlerExtension
{
protected function create_thumb(string $hash): bool
protected function create_thumb(string $hash, string $type): bool
{
copy("ext/handle_mp3/thumb.jpg", warehouse_path("thumbs", $hash));
copy("ext/handle_mp3/thumb.jpg", warehouse_path(Image::THUMBNAIL_DIR, $hash));
return true;
}

View file

@ -8,11 +8,12 @@
class PixelFileHandler extends DataHandlerExtension
{
const SUPPORTED_EXTENSIONS = ["jpg", "jpeg", "gif", "png", "webp"];
protected function supported_ext(string $ext): bool
{
$exts = ["jpg", "jpeg", "gif", "png", "webp"];
$ext = (($pos = strpos($ext, '?')) !== false) ? substr($ext, 0, $pos) : $ext;
return in_array(strtolower($ext), $exts);
return in_array(strtolower($ext), self::SUPPORTED_EXTENSIONS);
}
protected function create_image_from_data(string $filename, array $metadata)
@ -53,12 +54,12 @@ class PixelFileHandler extends DataHandlerExtension
return false;
}
protected function create_thumb(string $hash): bool
protected function create_thumb(string $hash, string $type): bool
{
global $config;
$inname = warehouse_path("images", $hash);
$outname = warehouse_path("thumbs", $hash);
$inname = warehouse_path(Image::IMAGE_DIR, $hash);
$outname = warehouse_path(Image::THUMBNAIL_DIR, $hash);
$ok = false;
@ -96,7 +97,7 @@ class PixelFileHandler extends DataHandlerExtension
try {
$info = getimagesize($inname);
$tsize = get_thumbnail_size_scaled($info[0], $info[1]);
$tsize = get_thumbnail_size($info[0], $info[1], true);
$image = image_resize_gd(
$inname,
$info,

View file

@ -14,7 +14,7 @@ class HandleStatic extends Extension
{
global $config, $page;
// hax.
if ($page->mode == "page" && (!isset($page->blocks) || $this->count_main($page->blocks) == 0)) {
if ($page->mode == PageMode::PAGE && (!isset($page->blocks) || $this->count_main($page->blocks) == 0)) {
$h_pagename = html_escape(implode('/', $event->args));
$f_pagename = preg_replace("/[^a-z_\-\.]+/", "_", $h_pagename);
$theme_name = $config->get_string("theme", "default");
@ -27,7 +27,7 @@ class HandleStatic extends Extension
$page->add_http_header("Cache-control: public, max-age=600");
$page->add_http_header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 600) . ' GMT');
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_data(file_get_contents($filename));
if (endsWith($filename, ".ico")) {
$page->set_type("image/x-icon");

View file

@ -19,23 +19,24 @@ class SVGFileHandler extends DataHandlerExtension
$sanitizer->removeRemoteReferences(true);
$dirtySVG = file_get_contents($event->tmpname);
$cleanSVG = $sanitizer->sanitize($dirtySVG);
file_put_contents(warehouse_path("images", $hash), $cleanSVG);
file_put_contents(warehouse_path(Image::IMAGE_DIR, $hash), $cleanSVG);
send_event(new ThumbnailGenerationEvent($event->hash, $event->type));
$image = $this->create_image_from_data(warehouse_path("images", $hash), $event->metadata);
$image = $this->create_image_from_data(warehouse_path(Image::IMAGE_DIR, $hash), $event->metadata);
if (is_null($image)) {
throw new UploadException("SVG handler failed to create image object from data");
}
$iae = new ImageAdditionEvent($image);
send_event($iae);
$event->image_id = $iae->image->id;
$event->merged = $iae->merged;
}
}
protected function create_thumb(string $hash): bool
protected function create_thumb(string $hash, string $type): bool
{
if (!create_thumbnail_convert($hash)) {
copy("ext/handle_svg/thumb.jpg", warehouse_path("thumbs", $hash));
copy("ext/handle_svg/thumb.jpg", warehouse_path(Image::THUMBNAIL_DIR, $hash));
}
return true;
}
@ -57,11 +58,11 @@ class SVGFileHandler extends DataHandlerExtension
$hash = $image->hash;
$page->set_type("image/svg+xml");
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$sanitizer = new Sanitizer();
$sanitizer->removeRemoteReferences(true);
$dirtySVG = file_get_contents(warehouse_path("images", $hash));
$dirtySVG = file_get_contents(warehouse_path(Image::IMAGE_DIR, $hash));
$cleanSVG = $sanitizer->sanitize($dirtySVG);
$page->set_data($cleanSVG);
}

View file

@ -53,7 +53,7 @@ class VideoFileHandler extends DataHandlerExtension
/**
* Generate the Thumbnail image for particular file.
*/
protected function create_thumb(string $hash): bool
protected function create_thumb(string $hash, string $type): bool
{
return create_thumbnail_ffmpeg($hash);
}

View file

@ -4,7 +4,7 @@ class HomeTheme extends Themelet
{
public function display_page(Page $page, $sitename, $base_href, $theme_name, $body)
{
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->add_auto_html_headers();
$hh = $page->get_all_html_headers();
$page->set_data(

View file

@ -43,7 +43,7 @@ class ImageIO extends Extension
$image = Image::by_id($_POST['image_id']);
if ($image) {
send_event(new ImageDeletionEvent($image));
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
if (isset($_SERVER['HTTP_REFERER']) && !strstr($_SERVER['HTTP_REFERER'], 'post/view')) {
$page->set_redirect($_SERVER['HTTP_REFERER']);
} else {
@ -56,7 +56,7 @@ class ImageIO extends Extension
if ($user->can("replace_image") && isset($_POST['image_id']) && $user->check_auth_token()) {
$image = Image::by_id($_POST['image_id']);
if ($image) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link('upload/replace/'.$image->id));
} else {
/* Invalid image ID */
@ -88,7 +88,7 @@ class ImageIO extends Extension
public function onImageAddition(ImageAdditionEvent $event)
{
try {
$this->add_image($event->image);
$this->add_image($event);
} catch (ImageAdditionException $e) {
throw new UploadException($e->error);
}
@ -141,7 +141,7 @@ class ImageIO extends Extension
$thumb_types = [];
$thumb_types['JPEG'] = "jpg";
$thumb_types['WEBP'] = "webp";
$thumb_types['WEBP (Not IE/Safari compatible)'] = "webp";
$sb = new SetupBlock("Thumbnailing");
@ -175,10 +175,12 @@ class ImageIO extends Extension
// add image {{{
private function add_image(Image $image)
private function add_image(ImageAdditionEvent $event)
{
global $user, $database, $config;
$image = $event->image;
/*
* Validate things
*/
@ -201,7 +203,9 @@ class ImageIO extends Extension
if (isset($_GET['source']) && isset($_GET['update'])) {
send_event(new SourceSetEvent($existing, $_GET['source']));
}
return null;
$event->merged = true;
$event->image = Image::by_id($existing->id);
return;
} else {
$error = "Image <a href='".make_link("post/view/{$existing->id}")."'>{$existing->id}</a> ".
"already has hash {$image->hash}:<p>".$this->theme->build_thumb_html($existing);
@ -251,7 +255,7 @@ class ImageIO extends Extension
global $page;
if (!is_null($image)) {
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
if ($type == "thumb") {
$ext = $config->get_string("thumb_type");
if (array_key_exists($ext, MIME_TYPE_MAP)) {

View file

@ -79,7 +79,7 @@ class ImageBan extends Extension
flash_message("Image deleted");
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect($_SERVER['HTTP_REFERER']);
}
} elseif ($event->get_arg(0) == "remove") {
@ -87,7 +87,7 @@ class ImageBan extends Extension
send_event(new RemoveImageHashBanEvent($_POST['hash']));
flash_message("Image ban removed");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect($_SERVER['HTTP_REFERER']);
}
} elseif ($event->get_arg(0) == "list") {

View file

@ -239,10 +239,10 @@ class Index extends Extension
// implode(explode()) to resolve aliases and sanitise
$search = url_escape(Tag::implode(Tag::explode($_GET['search'], false)));
if (empty($search)) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list/1"));
} else {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link('post/list/'.$search.'/1'));
}
return;
@ -278,7 +278,7 @@ class Index extends Extension
$this->theme->display_intro($page);
send_event(new PostListBuildingEvent($search_terms));
} elseif ($count_search_terms > 0 && $count_images === 1 && $page_number === 1) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link('post/view/'.$images[0]->id));
} else {
$plbe = new PostListBuildingEvent($search_terms);

View file

@ -157,7 +157,7 @@ class IndexTest extends ShimmiePHPUnitTestCase
global $database;
$db = $database->get_driver_name();
if ($db == "pgsql" || $db == "sqlite") {
if ($db == DatabaseDriver::PGSQL || $db == DatabaseDriver::SQLITE) {
$this->markTestIncomplete();
}

View file

@ -77,7 +77,7 @@ class IPBan extends Extension
send_event(new AddIPBanEvent($_POST['ip'], $_POST['reason'], $end));
flash_message("Ban for {$_POST['ip']} added");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list"));
}
} elseif ($event->get_arg(0) == "remove" && $user->check_auth_token()) {
@ -85,7 +85,7 @@ class IPBan extends Extension
send_event(new RemoveIPBanEvent($_POST['id']));
flash_message("Ban removed");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ip_ban/list"));
}
} elseif ($event->get_arg(0) == "list") {
@ -235,7 +235,7 @@ class IPBan extends Extension
{
global $config, $database;
$prefix = ($database->get_driver_name() == "sqlite" ? "bans." : "");
$prefix = ($database->get_driver_name() == DatabaseDriver::SQLITE ? "bans." : "");
$bans = $this->get_active_bans();

View file

@ -16,7 +16,7 @@ class IPBanTheme extends Themelet
{
global $database, $user;
$h_bans = "";
$prefix = ($database->get_driver_name() == "sqlite" ? "bans." : "");
$prefix = ($database->get_driver_name() == DatabaseDriver::SQLITE ? "bans." : "");
foreach ($bans as $ban) {
$end_human = date('Y-m-d', $ban[$prefix.'end_timestamp']);
$h_bans .= "

View file

@ -68,7 +68,7 @@ class LogDatabase extends Extension
$args["module"] = $_GET["module"];
}
if (!empty($_GET["user"])) {
if ($database->get_driver_name() == "pgsql") {
if ($database->get_driver_name() == DatabaseDriver::PGSQL) {
if (preg_match("#\d+\.\d+\.\d+\.\d+(/\d+)?#", $_GET["user"])) {
$wheres[] = "(username = :user1 OR text(address) = :user2)";
$args["user1"] = $_GET["user"];

View file

@ -35,7 +35,7 @@ class MailTest extends Extension
{
if ($event->page_matches("mail/test")) {
global $page;
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
echo "Alert: uncomment this page's code on /ext/mail/main.php starting on line 33, and change the email address. Make sure you're using a server with a domain, not localhost.";
/*
echo "Preparing to send message:<br>";

View file

@ -64,7 +64,7 @@ class MassTagger extends Extension
}
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
if (!isset($_SERVER['HTTP_REFERER'])) {
$_SERVER['HTTP_REFERER'] = make_link();
}

View file

@ -81,14 +81,14 @@ class NotATag extends Extension
[$tag, $redirect]
);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect($_SERVER['HTTP_REFERER']);
} elseif ($event->get_arg(0) == "remove") {
if (isset($_POST['tag'])) {
$database->Execute("DELETE FROM untags WHERE tag = ?", [$_POST['tag']]);
flash_message("Image ban removed");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect($_SERVER['HTTP_REFERER']);
}
} elseif ($event->get_arg(0) == "list") {

View file

@ -100,7 +100,7 @@ class Notes extends Extension
$this->revert_history($noteID, $reviewID);
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("note/updated"));
break;
case "add_note":
@ -108,7 +108,7 @@ class Notes extends Extension
$this->add_new_note();
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
break;
case "add_request":
@ -116,7 +116,7 @@ class Notes extends Extension
$this->add_note_request();
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
break;
case "nuke_notes":
@ -124,7 +124,7 @@ class Notes extends Extension
$this->nuke_notes();
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
break;
case "nuke_requests":
@ -132,25 +132,25 @@ class Notes extends Extension
$this->nuke_requests();
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
break;
case "edit_note":
if (!$user->is_anonymous()) {
$this->update_note();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/" . $_POST["image_id"]));
}
break;
case "delete_note":
if ($user->is_admin()) {
$this->delete_note();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$_POST["image_id"]));
}
break;
default:
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("note/list"));
break;
}

View file

@ -94,7 +94,7 @@ class NumericScore extends Extension
if (!is_null($score) && $image_id>0) {
send_event(new NumericScoreSetEvent($image_id, $user, $score));
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
} elseif ($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) {
@ -108,13 +108,13 @@ class NumericScore extends Extension
"UPDATE images SET numeric_score=0 WHERE id=?",
[$image_id]
);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
}
} elseif ($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) {
if ($user->can("edit_other_vote")) {
$this->delete_votes_by(int_escape($_POST['user_id']));
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
}
} elseif ($event->page_matches("popular_by_day") || $event->page_matches("popular_by_month") || $event->page_matches("popular_by_year")) {

View file

@ -41,7 +41,7 @@ class Oekaki extends Extension
throw new UploadException("File type not recognised");
} else {
unlink($tmpname);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$duev->image_id));
}
}

View file

@ -404,7 +404,7 @@ class OuroborosAPI extends Extension
} elseif ($this->type == 'xml') {
$page->set_type('text/xml; charset=utf-8');
}
$page->set_mode('data');
$page->set_mode(PageMode::DATA);
$this->tryAuth();
if ($event->page_matches('post')) {
@ -464,7 +464,7 @@ class OuroborosAPI extends Extension
}
}
} elseif ($event->page_matches('post/show')) {
$page->set_mode('redirect');
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link(str_replace('post/show', 'post/view', implode('/', $event->args))));
$page->display();
die();

View file

@ -149,7 +149,7 @@ class PrivMsg extends Extension
$database->execute("DELETE FROM private_message WHERE id = :id", ["id" => $pm_id]);
$database->cache->delete("pm-count-{$user->id}");
log_info("pm", "Deleted PM #$pm_id", "PM deleted");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect($_SERVER["HTTP_REFERER"]);
}
}
@ -162,7 +162,7 @@ class PrivMsg extends Extension
$message = $_POST["message"];
send_event(new SendPMEvent(new PM($from_id, $_SERVER["REMOTE_ADDR"], $to_id, $subject, $message)));
flash_message("PM sent");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect($_SERVER["HTTP_REFERER"]);
}
break;

View file

@ -130,7 +130,7 @@ class Pools extends Extension
case "create": // ADD _POST
try {
$newPoolID = $this->add_pool();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/".$newPoolID));
} catch (PoolCreationException $e) {
$this->theme->display_error(400, "Error", $e->error);
@ -150,7 +150,7 @@ class Pools extends Extension
if (!$user->is_anonymous()) {
$historyID = int_escape($event->get_arg(1));
$this->revert_history($historyID);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/updated"));
}
break;
@ -159,7 +159,7 @@ class Pools extends Extension
if ($this->have_permission($user, $pool)) {
$this->theme->edit_pool($page, $this->get_pool($pool_id), $this->edit_posts($pool_id));
} else {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/".$pool_id));
}
break;
@ -169,13 +169,13 @@ class Pools extends Extension
if ($this->have_permission($user, $pool)) {
$this->theme->edit_order($page, $this->get_pool($pool_id), $this->edit_order($pool_id));
} else {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/".$pool_id));
}
} else {
if ($this->have_permission($user, $pool)) {
$this->order_posts();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/".$pool_id));
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
@ -194,7 +194,7 @@ class Pools extends Extension
case "add_posts":
if ($this->have_permission($user, $pool)) {
$this->add_posts();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/".$pool_id));
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
@ -204,7 +204,7 @@ class Pools extends Extension
case "remove_posts":
if ($this->have_permission($user, $pool)) {
$this->remove_posts();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/".$pool_id));
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
@ -215,7 +215,7 @@ class Pools extends Extension
case "edit_description":
if ($this->have_permission($user, $pool)) {
$this->edit_description();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/view/".$pool_id));
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
@ -228,7 +228,7 @@ class Pools extends Extension
// -> Only admins and owners may do this
if ($user->is_admin() || $user->id == $pool['user_id']) {
$this->nuke_pool($pool_id);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/list"));
} else {
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
@ -236,7 +236,7 @@ class Pools extends Extension
break;
default:
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("pool/list"));
break;
}

View file

@ -40,7 +40,7 @@ class RandomImage extends Extension
if ($action === "download") {
if (!is_null($image)) {
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type($image->get_mime_type());
$page->set_data(file_get_contents($image->get_image_filename()));
}
@ -50,7 +50,7 @@ class RandomImage extends Extension
}
} elseif ($action === "widget") {
if (!is_null($image)) {
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("text/html");
$page->set_data($this->theme->build_thumb_html($image));
}

View file

@ -21,10 +21,10 @@ class RandomList extends Extension
// implode(explode()) to resolve aliases and sanitise
$search = url_escape(Tag::implode(Tag::explode($_GET['search'], false)));
if (empty($search)) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("random"));
} else {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link('random/'.$search));
}
return;

View file

@ -37,7 +37,7 @@ class RatingSetEvent extends Event
class Ratings extends Extension
{
protected $db_support = ['mysql','pgsql']; // ?
protected $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::PGSQL];
public function get_priority(): int
{
@ -91,7 +91,7 @@ class Ratings extends Extension
$user_view_level = Ratings::get_user_privs($user);
$user_view_level = preg_split('//', $user_view_level, -1);
if (!in_array($event->image->rating, $user_view_level)) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list"));
}
}
@ -170,7 +170,7 @@ class Ratings extends Extension
global $user;
if ($user->is_admin()) {
$event->add_action("bulk_rate", "Set Rating", "", $this->theme->get_selection_rater_html("bulk_rating"));
$event->add_action("bulk_rate","Set Rating","",$this->theme->get_selection_rater_html("u","bulk_rating"));
}
}
@ -191,7 +191,7 @@ class Ratings extends Extension
if ($image==null) {
continue;
}
send_event(new RatingSetEvent($image, $rating));
$total++;
}
@ -228,7 +228,7 @@ class Ratings extends Extension
# select image_id from image_tags join tags
# on image_tags.tag_id = tags.id where tags.tag = ?);
# ", array($_POST["rating"], $_POST["tag"]));
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list"));
}
}
@ -331,10 +331,10 @@ class Ratings extends Extension
if ($config->get_int("ext_ratings2_version") < 3) {
$database->Execute("UPDATE images SET rating = 'u' WHERE rating is null");
switch ($database->get_driver_name()) {
case "mysql":
case DatabaseDriver::MYSQL:
$database->Execute("ALTER TABLE images CHANGE rating rating CHAR(1) NOT NULL DEFAULT 'u'");
break;
case "pgsql":
case DatabaseDriver::PGSQL:
$database->Execute("ALTER TABLE images ALTER COLUMN rating SET DEFAULT 'u'");
$database->Execute("ALTER TABLE images ALTER COLUMN rating SET NOT NULL");
break;

View file

@ -43,7 +43,7 @@ class RegenThumb extends Extension
$this->regenerate_thumbnail($image);
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list"));
}
}
@ -133,7 +133,7 @@ class RegenThumb extends Extension
$i = 0;
foreach ($images as $image) {
if (!$force) {
$path = warehouse_path("thumbs", $image["hash"], false);
$path = warehouse_path(Image::THUMBNAIL_DIR, $image["hash"], false);
if (file_exists($path)) {
continue;
}
@ -157,7 +157,7 @@ class RegenThumb extends Extension
$i = 0;
foreach ($images as $image) {
$outname = warehouse_path("thumbs", $image["hash"]);
$outname = warehouse_path(Image::THUMBNAIL_DIR, $image["hash"]);
if (file_exists($outname)) {
unlink($outname);
$i++;

View file

@ -8,7 +8,7 @@
class Relationships extends Extension
{
protected $db_support = ['mysql', 'pgsql'];
protected $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::PGSQL];
public function onInitExt(InitExtEvent $event)
{

View file

@ -67,7 +67,7 @@ class ReportImage extends Extension
if (!empty($_POST['image_id']) && !empty($_POST['reason'])) {
$image_id = int_escape($_POST['image_id']);
send_event(new AddReportedImageEvent(new ImageReport($image_id, $user->id, $_POST['reason'])));
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id"));
} else {
$this->theme->display_error(500, "Missing input", "Missing image ID or report reason");
@ -76,7 +76,7 @@ class ReportImage extends Extension
if (!empty($_POST['id'])) {
if ($user->can("view_image_report")) {
send_event(new RemoveReportedImageEvent($_POST['id']));
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("image_report/list"));
}
} else {
@ -85,7 +85,7 @@ class ReportImage extends Extension
} elseif ($event->get_arg(0) == "remove_reports_by" && $user->check_auth_token()) {
if ($user->can("view_image_report")) {
$this->delete_reports_by(int_escape($_POST['user_id']));
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
}
} elseif ($event->get_arg(0) == "list") {

View file

@ -16,6 +16,8 @@
*/
class ResizeImage extends Extension
{
const SUPPORTED_EXT = ["jpg","jpeg","png","gif","webp"];
/**
* Needs to be after the data processing extensions
*/
@ -37,7 +39,8 @@ class ResizeImage extends Extension
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{
global $user, $config;
if ($user->is_admin() && $config->get_bool("resize_enabled")) {
if ($user->is_admin() && $config->get_bool("resize_enabled")
&& in_array($event->image->ext, self::SUPPORTED_EXT)) {
/* Add a link to resize the image */
$event->add_part($this->theme->get_resize_html($event->image));
}
@ -64,7 +67,8 @@ class ResizeImage extends Extension
$image_obj = Image::by_id($event->image_id);
if ($config->get_bool("resize_upload") == true && ($image_obj->ext == "jpg" || $image_obj->ext == "png" || $image_obj->ext == "gif" || $image_obj->ext == "webp")) {
if ($config->get_bool("resize_upload") == true
&& in_array($event->type, self::SUPPORTED_EXT)) {
$width = $height = 0;
if ($config->get_int("resize_default_width") !== 0) {
@ -75,7 +79,7 @@ class ResizeImage extends Extension
}
$isanigif = 0;
if ($image_obj->ext == "gif") {
$image_filename = warehouse_path("images", $image_obj->hash);
$image_filename = warehouse_path(Image::IMAGE_DIR, $image_obj->hash);
if (($fh = @fopen($image_filename, 'rb'))) {
//check if gif is animated (via http://www.php.net/manual/en/function.imagecreatefromgif.php#104473)
while (!feof($fh) && $isanigif < 2) {
@ -141,7 +145,7 @@ class ResizeImage extends Extension
//$this->theme->display_resize_page($page, $image_id);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$image_id));
} catch (ImageResizeException $e) {
$this->theme->display_resize_error($page, "Error Resizing", $e->error);
@ -163,7 +167,7 @@ class ResizeImage extends Extension
}
$hash = $image_obj->hash;
$image_filename = warehouse_path("images", $hash);
$image_filename = warehouse_path(Image::IMAGE_DIR, $hash);
$info = getimagesize($image_filename);
if (($image_obj->width != $info[0]) || ($image_obj->height != $info[1])) {
@ -189,7 +193,7 @@ class ResizeImage extends Extension
$new_image->ext = $image_obj->ext;
/* Move the new image into the main storage location */
$target = warehouse_path("images", $new_image->hash);
$target = warehouse_path(Image::IMAGE_DIR, $new_image->hash);
if (!@copy($tmp_filename, $target)) {
throw new ImageResizeException("Failed to copy new image file from temporary location ({$tmp_filename}) to archive ($target)");
}

View file

@ -31,6 +31,8 @@ class ImageRotateException extends SCoreException
*/
class RotateImage extends Extension
{
const SUPPORTED_EXT = ["jpg","jpeg","png","gif","webp"];
public function onInitExt(InitExtEvent $event)
{
global $config;
@ -41,7 +43,8 @@ class RotateImage extends Extension
public function onImageAdminBlockBuilding(ImageAdminBlockBuildingEvent $event)
{
global $user, $config;
if ($user->is_admin() && $config->get_bool("rotate_enabled")) {
if ($user->is_admin() && $config->get_bool("rotate_enabled")
&& in_array($event->image->ext, self::SUPPORTED_EXT)) {
/* Add a link to rotate the image */
$event->add_part($this->theme->get_rotate_html($event->image->id));
}
@ -93,7 +96,7 @@ class RotateImage extends Extension
//$this->theme->display_rotate_page($page, $image_id);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$image_id));
} catch (ImageRotateException $e) {
$this->theme->display_rotate_error($page, "Error Rotating", $e->error);
@ -120,7 +123,7 @@ class RotateImage extends Extension
throw new ImageRotateException("Image does not have a hash associated with it.");
}
$image_filename = warehouse_path("images", $hash);
$image_filename = warehouse_path(Image::IMAGE_DIR, $hash);
if (file_exists($image_filename)==false) {
throw new ImageRotateException("$image_filename does not exist.");
}
@ -212,7 +215,7 @@ class RotateImage extends Extension
$new_image->ext = $image_obj->ext;
/* Move the new image into the main storage location */
$target = warehouse_path("images", $new_image->hash);
$target = warehouse_path(Image::IMAGE_DIR, $new_image->hash);
if (!@copy($tmp_filename, $target)) {
throw new ImageRotateException("Failed to copy new image file from temporary location ({$tmp_filename}) to archive ($target)");
}

View file

@ -9,7 +9,7 @@
class RSS_Comments extends Extension
{
protected $db_support = ['mysql', 'sqlite']; // pgsql has no UNIX_TIMESTAMP
protected $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::SQLITE]; // pgsql has no UNIX_TIMESTAMP
public function onPostListBuilding(PostListBuildingEvent $event)
{
@ -24,7 +24,7 @@ class RSS_Comments extends Extension
{
global $config, $database, $page;
if ($event->page_matches("rss/comments")) {
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("application/rss+xml");
$comments = $database->get_all("

View file

@ -39,7 +39,7 @@ class RSS_Images extends Extension
{
global $page;
global $config;
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("application/rss+xml");
$data = "";

View file

@ -19,7 +19,7 @@ if ( // kill these glitched requests immediately
class Rule34 extends Extension
{
protected $db_support = ['pgsql']; # Only PG has the NOTIFY pubsub system
protected $db_support = [DatabaseDriver::PGSQL]; # Only PG has the NOTIFY pubsub system
public function onImageDeletion(ImageDeletionEvent $event)
{
@ -90,14 +90,14 @@ class Rule34 extends Extension
'UPDATE users SET comic_admin=? WHERE id=?',
[$input['is_admin'] ? 't' : 'f', $input['user_id']]
);
$page->set_mode('redirect');
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(@$_SERVER['HTTP_REFERER']);
}
}
if ($event->page_matches("tnc_agreed")) {
setcookie("ui-tnc-agreed", "true", 0, "/");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(@$_SERVER['HTTP_REFERER'] ?? "/");
}
@ -116,14 +116,14 @@ class Rule34 extends Extension
continue;
}
log_info("admin", "Cleaning {$hash}");
@unlink(warehouse_path('images', $hash));
@unlink(warehouse_path('thumbs', $hash));
@unlink(warehouse_path(Image::IMAGE_DIR, $hash));
@unlink(warehouse_path(Image::THUMBNAIL_DIR, $hash));
$database->execute("NOTIFY shm_image_bans, '{$hash}';");
}
}
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
}
}

View file

@ -19,7 +19,7 @@ class Rule34Theme extends Themelet
{
global $database, $user;
$h_bans = "";
$prefix = ($database->get_driver_name() == "sqlite" ? "bans." : "");
$prefix = ($database->get_driver_name() == DatabaseDriver::SQLITE ? "bans." : "");
foreach ($bans as $ban) {
$h_bans .= "
<tr>

View file

@ -203,7 +203,7 @@ class Setup extends Extension
global $config, $page, $user;
if ($event->page_matches("nicetest")) {
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_data("ok");
}
@ -216,7 +216,7 @@ class Setup extends Extension
$config->save();
flash_message("Config saved");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("setup"));
} elseif ($event->get_arg(0) == "advanced") {
$this->theme->display_advanced($page, $config->values);

View file

@ -53,7 +53,7 @@ class ShimmieApi extends Extension
global $page, $user;
if ($event->page_matches("api/shimmie")) {
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("text/plain");
if ($event->page_matches("api/shimmie/get_tags")) {
@ -100,7 +100,7 @@ class ShimmieApi extends Extension
$all = $this->api_get_user($type, $query);
$page->set_data(json_encode($all));
} else {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("ext_doc/shimmie_api"));
}
}

View file

@ -152,7 +152,7 @@ class XMLSitemap extends Extension
// Generate new sitemap
file_put_contents($this->sitemap_filepath, $xml);
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("application/xml");
$page->set_data($xml);
}
@ -188,7 +188,7 @@ class XMLSitemap extends Extension
$xml = file_get_contents($this->sitemap_filepath);
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("application/xml");
$page->set_data($xml);
}

View file

@ -132,7 +132,7 @@ class Source_History extends Extension
// check for the nothing case
if ($revert_id < 1) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
return;
}
@ -165,7 +165,7 @@ class Source_History extends Extension
send_event(new SourceSetEvent($image, $stored_source));
// all should be done now so redirect the user back to the image
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link('post/view/'.$stored_image_id));
}

View file

@ -165,14 +165,14 @@ class TagEdit extends Extension
$search = $_POST['search'];
$replace = $_POST['replace'];
$this->mass_tag_edit($search, $replace);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("admin"));
}
}
if ($event->get_arg(0) == "mass_source_set") {
if ($user->can("mass_tag_edit") && isset($_POST['tags']) && isset($_POST['source'])) {
$this->mass_source_edit($_POST['tags'], $_POST['source']);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list"));
}
}

View file

@ -132,7 +132,7 @@ class Tag_History extends Extension
// check for the nothing case
if ($revert_id < 1) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
return;
}
@ -162,7 +162,7 @@ class Tag_History extends Extension
send_event(new TagSetEvent($image, Tag::explode($stored_tags)));
// all should be done now so redirect the user back to the image
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link('post/view/'.$stored_image_id));
}

View file

@ -75,7 +75,7 @@ class TagList extends Extension
$database->cache->set($cache_key, $res, 600);
}
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("text/plain");
$page->set_data(implode("\n", $res));
}

View file

@ -59,7 +59,7 @@ class TaggerXML extends Extension
$tags.
"</tags>";
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->set_type("text/xml");
$page->set_data($xml);
}

View file

@ -10,7 +10,7 @@
class Tips extends Extension
{
protected $db_support = ['mysql', 'sqlite']; // rand() ?
protected $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::SQLITE]; // rand() ?
public function onInitExt(InitExtEvent $event)
{
@ -51,7 +51,7 @@ class Tips extends Extension
case "save":
if ($user->check_auth_token()) {
$this->saveTip();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tips/list"));
}
break;
@ -59,14 +59,14 @@ class Tips extends Extension
// FIXME: HTTP GET CSRF
$tipID = int_escape($event->get_arg(1));
$this->setStatus($tipID);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tips/list"));
break;
case "delete":
// FIXME: HTTP GET CSRF
$tipID = int_escape($event->get_arg(1));
$this->deleteTip($tipID);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("tips/list"));
break;
}

View file

@ -43,6 +43,7 @@ class TranscodeImage extends Extension
"psd",
"tiff",
"webp",
"ico",
]
];
@ -68,6 +69,7 @@ class TranscodeImage extends Extension
const INPUT_FORMATS = [
"BMP" => "bmp",
"GIF" => "gif",
"ICO" => "ico",
"JPG" => "jpg",
"PNG" => "png",
"PSD" => "psd",
@ -197,7 +199,7 @@ class TranscodeImage extends Extension
if (isset($_POST['transcode_format'])) {
try {
$this->transcode_and_replace_image($image_obj, $_POST['transcode_format']);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/".$image_id));
} catch (ImageTranscodeException $e) {
$this->theme->display_transcode_error($page, "Error Transcoding", $e->getMessage());
@ -306,7 +308,7 @@ class TranscodeImage extends Extension
private function transcode_and_replace_image(Image $image_obj, String $target_format)
{
$target_format = $this->clean_format($target_format);
$original_file = warehouse_path("images", $image_obj->hash);
$original_file = warehouse_path(Image::IMAGE_DIR, $image_obj->hash);
$tmp_filename = $this->transcode_image($original_file, $image_obj->ext, $target_format);
@ -319,7 +321,7 @@ class TranscodeImage extends Extension
$new_image->ext = $this->determine_ext($target_format);
/* Move the new image into the main storage location */
$target = warehouse_path("images", $new_image->hash);
$target = warehouse_path(Image::IMAGE_DIR, $new_image->hash);
if (!@copy($tmp_filename, $target)) {
throw new ImageTranscodeException("Failed to copy new image file from temporary location ({$tmp_filename}) to archive ($target)");
}
@ -440,15 +442,21 @@ class TranscodeImage extends Extension
}
$tmp_name = tempnam("/tmp", "shimmie_transcode");
$format = '"%s" %s -quality %u -background %s "%s" %s:"%s"';
$cmd = sprintf($format, $convert, $args, $q, $bg, $source_name, $ext, $tmp_name);
$source_type = "";
switch ($source_format) {
case "ico":
$source_type = "ico:";
}
$format = '"%s" %s -quality %u -background %s %s"%s" %s:"%s" 2>&1';
$cmd = sprintf($format, $convert, $args, $q, $bg, $source_type, $source_name, $ext, $tmp_name);
$cmd = str_replace("\"convert\"", "convert", $cmd); // quotes are only needed if the path to convert contains a space; some other times, quotes break things, see github bug #27
exec($cmd, $output, $ret);
log_debug('transcode', "Transcoding with command `$cmd`, returns $ret");
if ($ret!==0) {
throw new ImageTranscodeException("Transcoding failed with command ".$cmd);
throw new ImageTranscodeException("Transcoding failed with command ".$cmd.", returning ".implode("\r\n", $output));
}
return $tmp_name;

View file

@ -38,7 +38,7 @@ class Update extends Extension
if ($event->page_matches("update/download")) {
$ok = $this->download_shimmie();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
if ($ok) {
$page->set_redirect(make_link("update/update", "sha=".$_GET['sha']));
} else {
@ -47,7 +47,7 @@ class Update extends Extension
} elseif ($event->page_matches("update/update")) {
$ok = $this->update_shimmie();
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
if ($ok) {
$page->set_redirect(make_link("admin"));
} //TODO: Show success?

View file

@ -44,7 +44,7 @@ class Upgrade extends Extension
$config->set_bool("in_upgrade", true);
$config->set_int("db_version", 9);
if ($database->get_driver_name() == 'mysql') {
if ($database->get_driver_name() == DatabaseDriver::MYSQL) {
$tables = $database->get_col("SHOW TABLES");
foreach ($tables as $table) {
log_info("upgrade", "converting $table to innodb");
@ -84,7 +84,7 @@ class Upgrade extends Extension
$config->set_bool("in_upgrade", true);
$config->set_int("db_version", 12);
if ($database->get_driver_name() == 'pgsql') {
if ($database->get_driver_name() == DatabaseDriver::PGSQL) {
log_info("upgrade", "Changing ext column to VARCHAR");
$database->execute("ALTER TABLE images ALTER COLUMN ext SET DATA TYPE VARCHAR(4)");
}
@ -101,9 +101,9 @@ class Upgrade extends Extension
$config->set_int("db_version", 13);
log_info("upgrade", "Changing password column to VARCHAR(250)");
if ($database->get_driver_name() == 'pgsql') {
if ($database->get_driver_name() == DatabaseDriver::PGSQL) {
$database->execute("ALTER TABLE users ALTER COLUMN pass SET DATA TYPE VARCHAR(250)");
} elseif ($database->get_driver_name() == 'mysql') {
} elseif ($database->get_driver_name() == DatabaseDriver::MYSQL) {
$database->execute("ALTER TABLE users CHANGE pass pass VARCHAR(250)");
}
@ -116,11 +116,11 @@ class Upgrade extends Extension
$config->set_int("db_version", 14);
log_info("upgrade", "Changing tag column to VARCHAR(255)");
if ($database->get_driver_name() == 'pgsql') {
if ($database->get_driver_name() == DatabaseDriver::PGSQL) {
$database->execute('ALTER TABLE tags ALTER COLUMN tag SET DATA TYPE VARCHAR(255)');
$database->execute('ALTER TABLE aliases ALTER COLUMN oldtag SET DATA TYPE VARCHAR(255)');
$database->execute('ALTER TABLE aliases ALTER COLUMN newtag SET DATA TYPE VARCHAR(255)');
} elseif ($database->get_driver_name() == 'mysql') {
} elseif ($database->get_driver_name() == DatabaseDriver::MYSQL) {
$database->execute('ALTER TABLE tags MODIFY COLUMN tag VARCHAR(255) NOT NULL');
$database->execute('ALTER TABLE aliases MODIFY COLUMN oldtag VARCHAR(255) NOT NULL');
$database->execute('ALTER TABLE aliases MODIFY COLUMN newtag VARCHAR(255) NOT NULL');
@ -129,6 +129,20 @@ class Upgrade extends Extension
log_info("upgrade", "Database at version 14");
$config->set_bool("in_upgrade", false);
}
if ($config->get_int("db_version") < 15) {
$config->set_bool("in_upgrade", true);
$config->set_int("db_version", 15);
log_info("upgrade", "Adding lower indexes for postgresql use");
if ($database->get_driver_name() == DatabaseDriver::PGSQL) {
$database->execute('CREATE INDEX tags_lower_tag_idx ON tags ((lower(tag)))');
$database->execute('CREATE INDEX users_lower_name_idx ON users ((lower(name)))');
}
log_info("upgrade", "Database at version 15");
$config->set_bool("in_upgrade", false);
}
}
public function get_priority(): int

View file

@ -27,7 +27,6 @@ class DataUploadEvent extends Event
public $merged = false;
/**
* Some data is being uploaded.
* This should be caught by a file handler.
@ -49,10 +48,10 @@ class DataUploadEvent extends Event
if ($config->get_bool("upload_use_mime")) {
$this->set_type(get_extension_from_mime($tmpname));
} else {
if (array_key_exists('extension', $metadata)&&!empty($metadata['extension'])) {
if (array_key_exists('extension', $metadata) && !empty($metadata['extension'])) {
$this->type = strtolower($metadata['extension']);
} else {
throw new UploadException("Could not determine extension for file ".$metadata["filename"]);
throw new UploadException("Could not determine extension for file " . $metadata["filename"]);
}
}
}
@ -130,9 +129,9 @@ class Upload extends Extension
$sb->position = 10;
// Output the limits from PHP so the user has an idea of what they can set.
$sb->add_int_option("upload_count", "Max uploads: ");
$sb->add_label("<i>PHP Limit = ".ini_get('max_file_uploads')."</i>");
$sb->add_label("<i>PHP Limit = " . ini_get('max_file_uploads') . "</i>");
$sb->add_shorthand_int_option("upload_size", "<br/>Max size per file: ");
$sb->add_label("<i>PHP Limit = ".ini_get('upload_max_filesize')."</i>");
$sb->add_label("<i>PHP Limit = " . ini_get('upload_max_filesize') . "</i>");
$sb->add_choice_option("transload_engine", $tes, "<br/>Transload: ");
$sb->add_bool_option("upload_tlsource", "<br/>Use transloaded URL as source if none is provided: ");
$sb->add_bool_option("upload_use_mime", "<br/>Use mime type to determine file types: ");
@ -190,10 +189,10 @@ class Upload extends Extension
if (count($_FILES) > 1) {
throw new UploadException("Can not upload more than one image for replacing.");
}
$source = isset($_POST['source']) ? $_POST['source'] : null;
$tags = []; // Tags aren't changed when replacing. Set to empty to stop PHP warnings.
$ok = false;
if (count($_FILES)) {
foreach ($_FILES as $file) {
@ -249,7 +248,7 @@ class Upload extends Extension
if (!empty($_GET['tags']) && $_GET['tags'] != "null") {
$tags = Tag::explode($_GET['tags']);
}
$ok = $this->try_transload($url, $tags, $source);
$this->theme->display_upload_status($page, $ok);
} else {
@ -314,7 +313,7 @@ class Upload extends Extension
* #param string[] $file
* #param string[] $tags
*/
private function try_upload(array $file, array $tags, ?string $source=null, int $replace=-1): bool
private function try_upload(array $file, array $tags, ?string $source = null, int $replace = -1): bool
{
global $page;
@ -331,7 +330,7 @@ class Upload extends Extension
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new UploadException($this->upload_error_message($file['error']));
}
$pathinfo = pathinfo($file['name']);
$metadata = [];
$metadata['filename'] = $pathinfo['basename'];
@ -340,19 +339,22 @@ class Upload extends Extension
}
$metadata['tags'] = $tags;
$metadata['source'] = $source;
/* check if we have been given an image ID to replace */
if ($replace >= 0) {
$metadata['replace'] = $replace;
}
$event = new DataUploadEvent($file['tmp_name'], $metadata);
send_event($event);
$page->add_http_header("X-Shimmie-Image-ID: ".int_escape($event->image_id));
if ($event->image_id == -1) {
throw new UploadException("File type not supported: " . $metadata['extension']);
}
$page->add_http_header("X-Shimmie-Image-ID: " . int_escape($event->image_id));
} catch (UploadException $ex) {
$this->theme->display_upload_error(
$page,
"Error with ".html_escape($file['name']),
"Error with " . html_escape($file['name']),
$ex->getMessage()
);
$ok = false;
@ -362,7 +364,7 @@ class Upload extends Extension
return $ok;
}
private function try_transload(string $url, array $tags, string $source=null, int $replace=-1): bool
private function try_transload(string $url, array $tags, string $source = null, int $replace = -1): bool
{
global $page, $config, $user;
@ -372,7 +374,7 @@ class Upload extends Extension
if ($user->can("edit_image_lock") && !empty($_GET['locked'])) {
$locked = bool_escape($_GET['locked']);
}
// Checks if url contains rating, also checks if the rating extension is enabled.
if ($config->get_string("transload_engine", "none") != "none" && ext_is_live("Ratings") && !empty($_GET['rating'])) {
// Rating event will validate that this is s/q/e/u
@ -386,7 +388,7 @@ class Upload extends Extension
// transload() returns Array or Bool, depending on the transload_engine.
$headers = transload($url, $tmp_filename);
$s_filename = is_array($headers) ? findHeader($headers, 'Content-Disposition') : null;
$h_filename = ($s_filename ? preg_replace('/^.*filename="([^ ]+)"/i', '$1', $s_filename) : null);
$filename = $h_filename ?: basename($url);
@ -394,8 +396,8 @@ class Upload extends Extension
if (!$headers) {
$this->theme->display_upload_error(
$page,
"Error with ".html_escape($filename),
"Error reading from ".html_escape($url)
"Error with " . html_escape($filename),
"Error reading from " . html_escape($url)
);
return false;
}
@ -403,7 +405,7 @@ class Upload extends Extension
if (filesize($tmp_filename) == 0) {
$this->theme->display_upload_error(
$page,
"Error with ".html_escape($filename),
"Error with " . html_escape($filename),
"No data found -- perhaps the site has hotlink protection?"
);
$ok = false;
@ -413,7 +415,7 @@ class Upload extends Extension
$metadata['filename'] = $filename;
$metadata['tags'] = $tags;
$metadata['source'] = (($url == $source) && !$config->get_bool('upload_tlsource') ? "" : $source);
$ext = false;
if (is_array($headers)) {
$ext = get_extension(findHeader($headers, 'Content-Type'));
@ -422,7 +424,7 @@ class Upload extends Extension
$ext = $pathinfo['extension'];
}
$metadata['extension'] = $ext;
/* check for locked > adds to metadata if it has */
if (!empty($locked)) {
$metadata['locked'] = $locked ? "on" : "";
@ -432,19 +434,22 @@ class Upload extends Extension
if (!empty($rating)) {
$metadata['rating'] = $rating;
}
/* check if we have been given an image ID to replace */
if ($replace >= 0) {
$metadata['replace'] = $replace;
}
try {
$event = new DataUploadEvent($tmp_filename, $metadata);
send_event($event);
if ($event->image_id == -1) {
throw new UploadException("File type not supported: " . $metadata['extension']);
}
} catch (UploadException $ex) {
$this->theme->display_upload_error(
$page,
"Error with ".html_escape($url),
"Error with " . html_escape($url),
$ex->getMessage()
);
$ok = false;

View file

@ -300,7 +300,7 @@ class UploadTheme extends Themelet
public function display_upload_status(Page $page, bool $ok)
{
if ($ok) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link());
} else {
$page->set_title("Upload Status");

View file

@ -372,7 +372,7 @@ class UserPage extends Extension
if (!is_null($duser)) {
$user = $duser;
$this->set_login_cookie($duser->name, $pass);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
// Try returning to previous page
if ($config->get_int("user_loginshowprofile", 0) == 0 &&
@ -397,7 +397,7 @@ class UserPage extends Extension
$page->add_cookie("user", "", time() + 60 * 60 * 24 * $config->get_int('login_memory'), "/");
}
log_info("user", "Logged out");
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
// Try forwarding to same page on logout unless user comes from registration page
if ($config->get_int("user_loginshowprofile", 0) == 0 &&
@ -440,7 +440,7 @@ class UserPage extends Extension
$uce = new UserCreationEvent($_POST['name'], $_POST['pass1'], $_POST['email']);
send_event($uce);
$this->set_login_cookie($uce->username, $uce->password);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user"));
} catch (UserCreationException $ex) {
$this->theme->display_error(400, "User Creation Error", $ex->getMessage());
@ -532,10 +532,10 @@ class UserPage extends Extension
global $page, $user;
if ($user->id == $duser->id) {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user"));
} else {
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("user/{$duser->name}"));
}
}
@ -698,7 +698,7 @@ class UserPage extends Extension
["id" => $_POST['id']]
);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/list"));
}
}

View file

@ -123,7 +123,7 @@ class ViewImage extends Extension
return;
}
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/{$image->id}", $query));
} elseif ($event->page_matches("post/view")) {
if (!is_numeric($event->get_arg(0))) {
@ -157,7 +157,7 @@ class ViewImage extends Extension
send_event(new ImageInfoSetEvent(Image::by_id($image_id)));
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("post/view/$image_id", url_escape(@$_POST['query'])));
}
}

View file

@ -137,7 +137,7 @@ class Wiki extends Extension
send_event(new WikiUpdateEvent($user, $wikipage));
$u_title = url_escape($title);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("wiki/$u_title"));
} catch (WikiUpdateException $e) {
$original = $this->get_page($title);
@ -159,7 +159,7 @@ class Wiki extends Extension
["title"=>$_POST["title"], "rev"=>$_POST["revision"]]
);
$u_title = url_escape($_POST["title"]);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("wiki/$u_title"));
}
} elseif ($event->page_matches("wiki_admin/delete_all")) {
@ -170,7 +170,7 @@ class Wiki extends Extension
["title"=>$_POST["title"]]
);
$u_title = url_escape($_POST["title"]);
$page->set_mode("redirect");
$page->set_mode(PageMode::REDIRECT);
$page->set_redirect(make_link("wiki/$u_title"));
}
}
@ -213,7 +213,7 @@ class Wiki extends Extension
return false;
}
private function get_page(string $title): WikiPage
private function get_page(string $title, int $revision=-1): WikiPage
{
global $database;
// first try and get the actual page
@ -222,21 +222,17 @@ class Wiki extends Extension
SELECT *
FROM wiki_pages
WHERE SCORE_STRNORM(title) LIKE SCORE_STRNORM(:title)
ORDER BY revision DESC
LIMIT 1
"),
ORDER BY revision DESC"),
["title"=>$title]
);
// fall back to wiki:default
if (empty($row)) {
$row = $database->get_row("
SELECT *
FROM wiki_pages
WHERE title LIKE :title
ORDER BY revision DESC
LIMIT 1
", ["title"=>"wiki:default"]);
SELECT *
FROM wiki_pages
WHERE title LIKE :title
ORDER BY revision DESC", ["title"=>"wiki:default"]);
// fall further back to manual
if (empty($row)) {

View file

@ -52,7 +52,7 @@ abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase
$_POST = [];
$page = class_exists("CustomPage") ? new CustomPage() : new Page();
send_event(new PageRequestEvent($page_name));
if ($page->mode == "redirect") {
if ($page->mode == PageMode::REDIRECT) {
$page->code = 302;
}
}
@ -68,7 +68,7 @@ abstract class ShimmiePHPUnitTestCase extends \PHPUnit\Framework\TestCase
$_POST = $args;
$page = class_exists("CustomPage") ? new CustomPage() : new Page();
send_event(new PageRequestEvent($page_name));
if ($page->mode == "redirect") {
if ($page->mode == PageMode::REDIRECT) {
$page->code = 302;
}
}

View file

@ -4,7 +4,7 @@ class CustomHomeTheme extends HomeTheme
{
public function display_page(Page $page, $sitename, $base_href, $theme_name, $body)
{
$page->set_mode("data");
$page->set_mode(PageMode::DATA);
$page->add_auto_html_headers();
$hh = $page->get_all_html_headers();
$page->set_data(