php8.1 gogogo

This commit is contained in:
Shish
2022-10-28 01:45:35 +01:00
parent 522b57da37
commit a04bc2e7e4
67 changed files with 184 additions and 346 deletions

View File

@ -1,10 +1,3 @@
# In retrospect I'm less of a fan of tabs for indentation, because
# while they're better when they work, they're worse when they don't
# work, and so many people use terrible editors when they don't work
# that everything is inconsistent... but tabs are what Shimmie went
# with back in the 90's, so that's what we use now, and we deal with
# the pain of making sure everybody configures their editor properly
# top-most EditorConfig file # top-most EditorConfig file
root = true root = true

View File

@ -32,21 +32,15 @@ jobs:
with: with:
php-version: 8.1 php-version: 8.1
- name: Log Versions
run: ./vendor/bin/php-cs-fixer --version
- name: Format - name: Format
run: ./vendor/bin/php-cs-fixer fix run: ./vendor/bin/php-cs-fixer fix && git diff --exit-code
- name: Log Diff
run: git diff --exit-code
test: test:
name: PHP ${{ matrix.php }} / DB ${{ matrix.database }} name: PHP ${{ matrix.php }} / DB ${{ matrix.database }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
php: ['7.4', '8.0', '8.1'] php: ['8.1']
database: ['pgsql', 'mysql', 'sqlite'] database: ['pgsql', 'mysql', 'sqlite']
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -112,7 +106,7 @@ jobs:
vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-clover=data/coverage.clover vendor/bin/phpunit --configuration tests/phpunit.xml --coverage-clover=data/coverage.clover
- name: Upload coverage - name: Upload coverage
if: matrix.php == '7.4' if: matrix.php == '8.1'
run: | run: |
wget https://scrutinizer-ci.com/ocular.phar wget https://scrutinizer-ci.com/ocular.phar
php ocular.phar code-coverage:upload --format=php-clover data/coverage.clover php ocular.phar code-coverage:upload --format=php-clover data/coverage.clover

View File

@ -1,7 +1,7 @@
# "Build" shimmie (composer install - done in its own stage so that we don't # "Build" shimmie (composer install - done in its own stage so that we don't
# need to include all the composer fluff in the final image) # need to include all the composer fluff in the final image)
FROM debian:stable AS app FROM debian:unstable AS app
RUN apt update && apt install -y composer php7.4-gd php7.4-dom php7.4-sqlite3 php-xdebug imagemagick RUN apt update && apt install -y composer php8.1-gd php8.1-dom php8.1-sqlite3 php-xdebug imagemagick
COPY composer.json composer.lock /app/ COPY composer.json composer.lock /app/
WORKDIR /app WORKDIR /app
RUN composer install --no-dev RUN composer install --no-dev
@ -10,8 +10,8 @@ COPY . /app/
# Tests in their own image. Really we should inherit from app and then # Tests in their own image. Really we should inherit from app and then
# `composer install` phpunit on top of that; but for some reason # `composer install` phpunit on top of that; but for some reason
# `composer install --no-dev && composer install` doesn't install dev # `composer install --no-dev && composer install` doesn't install dev
FROM debian:stable AS tests FROM debian:unstable AS tests
RUN apt update && apt install -y composer php7.4-gd php7.4-dom php7.4-sqlite3 php-xdebug imagemagick RUN apt update && apt install -y composer php8.1-gd php8.1-dom php8.1-sqlite3 php-xdebug imagemagick
COPY composer.json composer.lock /app/ COPY composer.json composer.lock /app/
WORKDIR /app WORKDIR /app
RUN composer install RUN composer install
@ -25,7 +25,7 @@ RUN [ $RUN_TESTS = false ] || (\
echo '=== Cleaning ===' && rm -rf data) echo '=== Cleaning ===' && rm -rf data)
# Build su-exec so that our final image can be nicer # Build su-exec so that our final image can be nicer
FROM debian:stable AS suexec FROM debian:unstable AS suexec
RUN apt-get update && apt-get install -y --no-install-recommends gcc libc-dev curl RUN apt-get update && apt-get install -y --no-install-recommends gcc libc-dev curl
RUN curl -k -o /usr/local/bin/su-exec.c https://raw.githubusercontent.com/ncopa/su-exec/master/su-exec.c; \ RUN curl -k -o /usr/local/bin/su-exec.c https://raw.githubusercontent.com/ncopa/su-exec/master/su-exec.c; \
gcc -Wall /usr/local/bin/su-exec.c -o/usr/local/bin/su-exec; \ gcc -Wall /usr/local/bin/su-exec.c -o/usr/local/bin/su-exec; \
@ -33,13 +33,13 @@ RUN curl -k -o /usr/local/bin/su-exec.c https://raw.githubusercontent.com/ncopa
chmod 0755 /usr/local/bin/su-exec; chmod 0755 /usr/local/bin/su-exec;
# Actually run shimmie # Actually run shimmie
FROM debian:stable FROM debian:unstable
EXPOSE 8000 EXPOSE 8000
HEALTHCHECK --interval=1m --timeout=3s CMD curl --fail http://127.0.0.1:8000/ || exit 1 HEALTHCHECK --interval=1m --timeout=3s CMD curl --fail http://127.0.0.1:8000/ || exit 1
ENV UID=1000 \ ENV UID=1000 \
GID=1000 GID=1000
RUN apt update && apt install -y curl \ RUN apt update && apt install -y curl \
php7.4-cli php7.4-gd php7.4-pgsql php7.4-mysql php7.4-sqlite3 php7.4-zip php7.4-dom php7.4-mbstring \ php8.1-cli php8.1-gd php8.1-pgsql php8.1-mysql php8.1-sqlite3 php8.1-zip php8.1-dom php8.1-mbstring \
imagemagick zip unzip && \ imagemagick zip unzip && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
COPY --from=app /app /app COPY --from=app /app /app

View File

@ -7,7 +7,7 @@
"config": { "config": {
"platform": { "platform": {
"php": "7.4.0" "php": "8.1.0"
} }
}, },
@ -31,7 +31,7 @@
], ],
"require" : { "require" : {
"php" : "^7.4 | ^8.0", "php" : "^8.1",
"ext-pdo": "*", "ext-pdo": "*",
"ext-json": "*", "ext-json": "*",
"ext-fileinfo": "*", "ext-fileinfo": "*",

View File

@ -3,13 +3,13 @@
declare(strict_types=1); declare(strict_types=1);
require_once "core/event.php"; require_once "core/event.php";
abstract class PageMode enum PageMode: string
{ {
public const REDIRECT = 'redirect'; case REDIRECT = 'redirect';
public const DATA = 'data'; case DATA = 'data';
public const PAGE = 'page'; case PAGE = 'page';
public const FILE = 'file'; case FILE = 'file';
public const MANUAL = 'manual'; case MANUAL = 'manual';
} }
/** /**
@ -22,13 +22,13 @@ abstract class PageMode
*/ */
class BasePage class BasePage
{ {
public string $mode = PageMode::PAGE; public PageMode $mode = PageMode::PAGE;
private string $mime; private string $mime;
/** /**
* Set what this page should do; "page", "data", or "redirect". * Set what this page should do; "page", "data", or "redirect".
*/ */
public function set_mode(string $mode): void public function set_mode(PageMode $mode): void
{ {
$this->mode = $mode; $this->mode = $mode;
} }

View File

@ -43,10 +43,10 @@ class Block
*/ */
public bool $is_content = true; public bool $is_content = true;
public function __construct(string $header=null, string $body=null, string $section="main", int $position=50, string $id=null) public function __construct(string $header=null, string|\MicroHTML\HTMLElement $body=null, string $section="main", int $position=50, string $id=null)
{ {
$this->header = $header; $this->header = $header;
$this->body = $body; $this->body = (string)$body;
$this->section = $section; $this->section = $section;
$this->position = $position; $this->position = $position;

View File

@ -3,11 +3,11 @@
declare(strict_types=1); declare(strict_types=1);
use FFSPHP\PDO; use FFSPHP\PDO;
abstract class DatabaseDriver enum DatabaseDriverID: string
{ {
public const MYSQL = "mysql"; case MYSQL = "mysql";
public const PGSQL = "pgsql"; case PGSQL = "pgsql";
public const SQLITE = "sqlite"; case SQLITE = "sqlite";
} }
/** /**
@ -54,11 +54,11 @@ class Database
throw new SCoreException("Can't figure out database engine"); throw new SCoreException("Can't figure out database engine");
} }
if ($db_proto === DatabaseDriver::MYSQL) { if ($db_proto === DatabaseDriverID::MYSQL->value) {
$this->engine = new MySQL(); $this->engine = new MySQL();
} elseif ($db_proto === DatabaseDriver::PGSQL) { } elseif ($db_proto === DatabaseDriverID::PGSQL->value) {
$this->engine = new PostgreSQL(); $this->engine = new PostgreSQL();
} elseif ($db_proto === DatabaseDriver::SQLITE) { } elseif ($db_proto === DatabaseDriverID::SQLITE->value) {
$this->engine = new SQLite(); $this->engine = new SQLite();
} else { } else {
die_nicely( die_nicely(
@ -106,12 +106,12 @@ class Database
return $this->engine->scoreql_to_sql($input); return $this->engine->scoreql_to_sql($input);
} }
public function get_driver_name(): string public function get_driver_id(): DatabaseDriverID
{ {
if (is_null($this->engine)) { if (is_null($this->engine)) {
$this->connect_engine(); $this->connect_engine();
} }
return $this->engine->name; return $this->engine->id;
} }
public function get_version(): string public function get_version(): string
@ -269,7 +269,7 @@ class Database
*/ */
public function get_last_insert_id(string $seq): int public function get_last_insert_id(string $seq): int
{ {
if ($this->engine->name == DatabaseDriver::PGSQL) { if ($this->engine->id == DatabaseDriverID::PGSQL) {
$id = $this->db->lastInsertId($seq); $id = $this->db->lastInsertId($seq);
} else { } else {
$id = $this->db->lastInsertId(); $id = $this->db->lastInsertId();
@ -301,20 +301,20 @@ class Database
$this->connect_db(); $this->connect_db();
} }
if ($this->engine->name === DatabaseDriver::MYSQL) { if ($this->engine->id === DatabaseDriverID::MYSQL) {
return count( return count(
$this->get_all("SHOW TABLES") $this->get_all("SHOW TABLES")
); );
} elseif ($this->engine->name === DatabaseDriver::PGSQL) { } elseif ($this->engine->id === DatabaseDriverID::PGSQL) {
return count( return count(
$this->get_all("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'") $this->get_all("SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'")
); );
} elseif ($this->engine->name === DatabaseDriver::SQLITE) { } elseif ($this->engine->id === DatabaseDriverID::SQLITE) {
return count( return count(
$this->get_all("SELECT name FROM sqlite_master WHERE type = 'table'") $this->get_all("SELECT name FROM sqlite_master WHERE type = 'table'")
); );
} else { } else {
throw new SCoreException("Can't count tables for database type {$this->engine->name}"); throw new SCoreException("Can't count tables for database type {$this->engine->id}");
} }
} }
@ -325,8 +325,8 @@ class Database
public function standardise_boolean(string $table, string $column, bool $include_postgres=false): void public function standardise_boolean(string $table, string $column, bool $include_postgres=false): void
{ {
$d = $this->get_driver_name(); $d = $this->get_driver_id();
if ($d == DatabaseDriver::MYSQL) { if ($d == DatabaseDriverID::MYSQL) {
# In mysql, ENUM('Y', 'N') is secretly INTEGER where Y=1 and N=2. # In mysql, ENUM('Y', 'N') is secretly INTEGER where Y=1 and N=2.
# BOOLEAN is secretly TINYINT where true=1 and false=0. # BOOLEAN is secretly TINYINT where true=1 and false=0.
# So we can cast directly from ENUM to BOOLEAN which gives us a # So we can cast directly from ENUM to BOOLEAN which gives us a
@ -335,12 +335,12 @@ class Database
$this->execute("ALTER TABLE $table MODIFY COLUMN $column BOOLEAN;"); $this->execute("ALTER TABLE $table MODIFY COLUMN $column BOOLEAN;");
$this->execute("UPDATE $table SET $column=0 WHERE $column=2;"); $this->execute("UPDATE $table SET $column=0 WHERE $column=2;");
} }
if ($d == DatabaseDriver::SQLITE) { if ($d == DatabaseDriverID::SQLITE) {
# SQLite doesn't care about column types at all, everything is # SQLite doesn't care about column types at all, everything is
# text, so we can in-place replace a char with a bool # text, so we can in-place replace a char with a bool
$this->execute("UPDATE $table SET $column = ($column IN ('Y', 1))"); $this->execute("UPDATE $table SET $column = ($column IN ('Y', 1))");
} }
if ($d == DatabaseDriver::PGSQL && $include_postgres) { if ($d == DatabaseDriverID::PGSQL && $include_postgres) {
$this->execute("ALTER TABLE $table ADD COLUMN ${column}_b BOOLEAN DEFAULT FALSE NOT NULL"); $this->execute("ALTER TABLE $table ADD COLUMN ${column}_b BOOLEAN DEFAULT FALSE NOT NULL");
$this->execute("UPDATE $table SET ${column}_b = ($column = 'Y')"); $this->execute("UPDATE $table SET ${column}_b = ($column = 'Y')");
$this->execute("ALTER TABLE $table DROP COLUMN $column"); $this->execute("ALTER TABLE $table DROP COLUMN $column");

View File

@ -9,7 +9,7 @@ abstract class SCORE
abstract class DBEngine abstract class DBEngine
{ {
public ?string $name = null; public DatabaseDriverID $id;
public function init(PDO $db) public function init(PDO $db)
{ {
@ -34,7 +34,7 @@ abstract class DBEngine
class MySQL extends DBEngine class MySQL extends DBEngine
{ {
public ?string $name = DatabaseDriver::MYSQL; public DatabaseDriverID $id = DatabaseDriverID::MYSQL;
public function init(PDO $db) public function init(PDO $db)
{ {
@ -73,7 +73,7 @@ class MySQL extends DBEngine
class PostgreSQL extends DBEngine class PostgreSQL extends DBEngine
{ {
public ?string $name = DatabaseDriver::PGSQL; public DatabaseDriverID $id = DatabaseDriverID::PGSQL;
public function init(PDO $db) public function init(PDO $db)
{ {
@ -171,7 +171,7 @@ function _ln($n): float
class SQLite extends DBEngine class SQLite extends DBEngine
{ {
public ?string $name = DatabaseDriver::SQLITE; public DatabaseDriverID $id = DatabaseDriverID::SQLITE;
public function init(PDO $db) public function init(PDO $db)
{ {

View File

@ -107,6 +107,12 @@ abstract class Extension
} }
} }
enum ExtensionVisibility {
case DEFAULT;
case ADMIN;
case HIDDEN;
}
abstract class ExtensionInfo abstract class ExtensionInfo
{ {
// Every credit you get costs us RAM. It stops now. // Every credit you get costs us RAM. It stops now.
@ -119,11 +125,6 @@ abstract class ExtensionInfo
public const LICENSE_MIT = "MIT"; public const LICENSE_MIT = "MIT";
public const LICENSE_WTFPL = "WTFPL"; public const LICENSE_WTFPL = "WTFPL";
public const VISIBLE_DEFAULT = "default";
public const VISIBLE_ADMIN = "admin";
public const VISIBLE_HIDDEN = "hidden";
private const VALID_VISIBILITY = [self::VISIBLE_DEFAULT, self::VISIBLE_ADMIN, self::VISIBLE_HIDDEN];
public string $key; public string $key;
public bool $core = false; public bool $core = false;
@ -135,12 +136,12 @@ abstract class ExtensionInfo
public array $authors = []; public array $authors = [];
public array $dependencies = []; public array $dependencies = [];
public array $conflicts = []; public array $conflicts = [];
public string $visibility = self::VISIBLE_DEFAULT; public ExtensionVisibility $visibility = ExtensionVisibility::DEFAULT;
public ?string $link = null; public ?string $link = null;
public ?string $version = null; public ?string $version = null;
public ?string $documentation = null; public ?string $documentation = null;
/** @var string[] which DBs this ext supports (blank for 'all') */ /** @var DatabaseDriverID[] which DBs this ext supports (blank for 'all') */
public array $db_support = []; public array $db_support = [];
private ?bool $supported = null; private ?bool $supported = null;
private ?string $support_info = null; private ?string $support_info = null;
@ -169,7 +170,6 @@ abstract class ExtensionInfo
{ {
assert(!empty($this->key), "key field is required"); assert(!empty($this->key), "key field is required");
assert(!empty($this->name), "name field is required for extension $this->key"); assert(!empty($this->name), "name field is required for extension $this->key");
assert(empty($this->visibility) || in_array($this->visibility, self::VALID_VISIBILITY), "Invalid visibility for extension $this->key");
assert(is_array($this->db_support), "db_support has to be an array for extension $this->key"); assert(is_array($this->db_support), "db_support has to be an array for extension $this->key");
assert(is_array($this->authors), "authors has to be an array for extension $this->key"); assert(is_array($this->authors), "authors has to be an array for extension $this->key");
assert(is_array($this->dependencies), "dependencies has to be an array for extension $this->key"); assert(is_array($this->dependencies), "dependencies has to be an array for extension $this->key");
@ -184,7 +184,7 @@ abstract class ExtensionInfo
{ {
global $database; global $database;
$this->support_info = ""; $this->support_info = "";
if (!empty($this->db_support) && !in_array($database->get_driver_name(), $this->db_support)) { if (!empty($this->db_support) && !in_array($database->get_driver_id(), $this->db_support)) {
$this->support_info .= "Database not supported. "; $this->support_info .= "Database not supported. ";
} }
if (!empty($this->conflicts)) { if (!empty($this->conflicts)) {

View File

@ -8,7 +8,6 @@ declare(strict_types=1);
class ImageAdditionEvent extends Event class ImageAdditionEvent extends Event
{ {
public User $user; public User $user;
public Image $image;
public bool $merged = false; public bool $merged = false;
/** /**
@ -16,10 +15,10 @@ class ImageAdditionEvent extends Event
* information. Also calls TagSetEvent to set the tags for * information. Also calls TagSetEvent to set the tags for
* this new image. * this new image.
*/ */
public function __construct(Image $image) public function __construct(
{ public Image $image,
) {
parent::__construct(); parent::__construct();
$this->image = $image;
} }
} }
@ -32,20 +31,17 @@ class ImageAdditionException extends SCoreException
*/ */
class ImageDeletionEvent extends Event class ImageDeletionEvent extends Event
{ {
public Image $image;
public bool $force = false;
/** /**
* Deletes an image. * Deletes an image.
* *
* Used by things like tags and comments handlers to * Used by things like tags and comments handlers to
* clean out related rows in their tables. * clean out related rows in their tables.
*/ */
public function __construct(Image $image, bool $force = false) public function __construct(
{ public Image $image,
public bool $force = false,
) {
parent::__construct(); parent::__construct();
$this->image = $image;
$this->force = $force;
} }
} }
@ -54,9 +50,6 @@ class ImageDeletionEvent extends Event
*/ */
class ImageReplaceEvent extends Event class ImageReplaceEvent extends Event
{ {
public int $id;
public Image $image;
/** /**
* Replaces an image. * Replaces an image.
* *
@ -64,11 +57,11 @@ class ImageReplaceEvent extends Event
* file, leaving the tags and such unchanged. Also removes * file, leaving the tags and such unchanged. Also removes
* the old image file and thumbnail from the disk. * the old image file and thumbnail from the disk.
*/ */
public function __construct(int $id, Image $image) public function __construct(
{ public int $id,
public Image $image
) {
parent::__construct(); parent::__construct();
$this->id = $id;
$this->image = $image;
} }
} }
@ -81,20 +74,17 @@ class ImageReplaceException extends SCoreException
*/ */
class ThumbnailGenerationEvent extends Event class ThumbnailGenerationEvent extends Event
{ {
public string $hash;
public string $mime;
public bool $force;
public bool $generated; public bool $generated;
/** /**
* Request a thumbnail be made for an image object * Request a thumbnail be made for an image object
*/ */
public function __construct(string $hash, string $mime, bool $force=false) public function __construct(
{ public string $hash,
public string $mime,
public bool $force=false
) {
parent::__construct(); parent::__construct();
$this->hash = $hash;
$this->mime = $mime;
$this->force = $force;
$this->generated = false; $this->generated = false;
} }
} }

View File

@ -650,7 +650,7 @@ class Image
public function delete_tags_from_image(): void public function delete_tags_from_image(): void
{ {
global $database; global $database;
if ($database->get_driver_name() == DatabaseDriver::MYSQL) { if ($database->get_driver_id() == DatabaseDriverID::MYSQL) {
//mysql < 5.6 has terrible subquery optimization, using EXISTS / JOIN fixes this //mysql < 5.6 has terrible subquery optimization, using EXISTS / JOIN fixes this
$database->execute( $database->execute(
" "
@ -796,7 +796,7 @@ class Image
{ {
global $database; global $database;
$sq = "SELECT id FROM tags WHERE LOWER(tag) LIKE LOWER(:tag)"; $sq = "SELECT id FROM tags WHERE LOWER(tag) LIKE LOWER(:tag)";
if ($database->get_driver_name() === DatabaseDriver::SQLITE) { if ($database->get_driver_id() === DatabaseDriverID::SQLITE) {
$sq .= "ESCAPE '\\'"; $sq .= "ESCAPE '\\'";
} }
return $database->get_col($sq, ["tag" => Tag::sqlify($tag)]); return $database->get_col($sq, ["tag" => Tag::sqlify($tag)]);

View File

@ -3,13 +3,10 @@
declare(strict_types=1); declare(strict_types=1);
class Querylet class Querylet
{ {
public string $sql; public function __construct(
public array $variables; public string $sql,
public array $variables=[],
public function __construct(string $sql, array $variables=[]) ) {
{
$this->sql = $sql;
$this->variables = $variables;
} }
public function append(Querylet $querylet): void public function append(Querylet $querylet): void
@ -31,24 +28,18 @@ class Querylet
class TagCondition class TagCondition
{ {
public string $tag; public function __construct(
public bool $positive; public string $tag,
public bool $positive,
public function __construct(string $tag, bool $positive) ) {
{
$this->tag = $tag;
$this->positive = $positive;
} }
} }
class ImgCondition class ImgCondition
{ {
public Querylet $qlet; public function __construct(
public bool $positive; public Querylet $qlet,
public bool $positive,
public function __construct(Querylet $qlet, bool $positive) ) {
{
$this->qlet = $qlet;
$this->positive = $positive;
} }
} }

View File

@ -159,7 +159,7 @@ class Tag
public static function sqlify(string $term): string public static function sqlify(string $term): string
{ {
global $database; global $database;
if ($database->get_driver_name() === DatabaseDriver::SQLITE) { if ($database->get_driver_id() === DatabaseDriverID::SQLITE) {
$term = str_replace('\\', '\\\\', $term); $term = str_replace('\\', '\\\\', $term);
} }
$term = str_replace('_', '\_', $term); $term = str_replace('_', '\_', $term);

View File

@ -49,7 +49,7 @@ function get_dsn()
{ {
if (getenv("INSTALL_DSN")) { if (getenv("INSTALL_DSN")) {
$dsn = getenv("INSTALL_DSN"); $dsn = getenv("INSTALL_DSN");
} elseif (@$_POST["database_type"] == DatabaseDriver::SQLITE) { } elseif (@$_POST["database_type"] == DatabaseDriverID::SQLITE) {
/** @noinspection PhpUnhandledExceptionInspection */ /** @noinspection PhpUnhandledExceptionInspection */
$id = bin2hex(random_bytes(5)); $id = bin2hex(random_bytes(5));
$dsn = "sqlite:data/shimmie.{$id}.sqlite"; $dsn = "sqlite:data/shimmie.{$id}.sqlite";
@ -99,9 +99,9 @@ function ask_questions()
$drivers = PDO::getAvailableDrivers(); $drivers = PDO::getAvailableDrivers();
if ( if (
!in_array(DatabaseDriver::MYSQL, $drivers) && !in_array(DatabaseDriverID::MYSQL, $drivers) &&
!in_array(DatabaseDriver::PGSQL, $drivers) && !in_array(DatabaseDriverID::PGSQL, $drivers) &&
!in_array(DatabaseDriver::SQLITE, $drivers) !in_array(DatabaseDriverID::SQLITE, $drivers)
) { ) {
$errors[] = " $errors[] = "
No database connection library could be found; shimmie needs No database connection library could be found; shimmie needs
@ -109,9 +109,9 @@ function ask_questions()
"; ";
} }
$db_m = in_array(DatabaseDriver::MYSQL, $drivers) ? '<option value="'. DatabaseDriver::MYSQL .'">MySQL</option>' : ""; $db_m = in_array(DatabaseDriverID::MYSQL, $drivers) ? '<option value="'. DatabaseDriverID::MYSQL .'">MySQL</option>' : "";
$db_p = in_array(DatabaseDriver::PGSQL, $drivers) ? '<option value="'. DatabaseDriver::PGSQL .'">PostgreSQL</option>' : ""; $db_p = in_array(DatabaseDriverID::PGSQL, $drivers) ? '<option value="'. DatabaseDriverID::PGSQL .'">PostgreSQL</option>' : "";
$db_s = in_array(DatabaseDriver::SQLITE, $drivers) ? '<option value="'. DatabaseDriver::SQLITE .'">SQLite</option>' : ""; $db_s = in_array(DatabaseDriverID::SQLITE, $drivers) ? '<option value="'. DatabaseDriverID::SQLITE .'">SQLite</option>' : "";
$warn_msg = $warnings ? "<h3>Warnings</h3>".implode("\n<p>", $warnings) : ""; $warn_msg = $warnings ? "<h3>Warnings</h3>".implode("\n<p>", $warnings) : "";
$err_msg = $errors ? "<h3>Errors</h3>".implode("\n<p>", $errors) : ""; $err_msg = $errors ? "<h3>Errors</h3>".implode("\n<p>", $errors) : "";

View File

@ -344,27 +344,6 @@ function unparse_url(array $parsed_url): string
return "$scheme$user$pass$host$port$path$query$fragment"; return "$scheme$user$pass$host$port$path$query$fragment";
} }
# finally in the core library starting from php8
if (!function_exists('str_starts_with')) {
function str_starts_with(string $haystack, string $needle): bool
{
return strncmp($haystack, $needle, strlen($needle)) === 0;
}
}
if (!function_exists('str_ends_with')) {
function str_ends_with(string $haystack, string $needle): bool
{
return $needle === '' || $needle === substr($haystack, - strlen($needle));
}
}
if (!function_exists('str_contains')) {
function str_contains(string $haystack, string $needle): bool
{
return '' === $needle || false !== strpos($haystack, $needle);
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* Input / Output Sanitising * * Input / Output Sanitising *

View File

@ -31,7 +31,7 @@ function die_nicely($title, $body, $code=0)
exit($code); exit($code);
} }
$min_php = "7.3"; $min_php = "8.1";
if (version_compare(phpversion(), $min_php, ">=") === false) { if (version_compare(phpversion(), $min_php, ">=") === false) {
die_nicely("Not Supported", " die_nicely("Not Supported", "
Shimmie does not support versions of PHP lower than $min_php Shimmie does not support versions of PHP lower than $min_php

View File

@ -28,7 +28,7 @@ _d("DEBUG", false); // boolean print various debugging details
_d("COOKIE_PREFIX", 'shm'); // string if you run multiple galleries with non-shared logins, give them different prefixes _d("COOKIE_PREFIX", 'shm'); // string if you run multiple galleries with non-shared logins, give them different prefixes
_d("SPEED_HAX", false); // boolean do some questionable things in the name of performance _d("SPEED_HAX", false); // boolean do some questionable things in the name of performance
_d("WH_SPLITS", 1); // int how many levels of subfolders to put in the warehouse _d("WH_SPLITS", 1); // int how many levels of subfolders to put in the warehouse
_d("VERSION", "2.9.2$_g"); // string shimmie version _d("VERSION", "2.10.0-alpha$_g"); // string shimmie version
_d("TIMEZONE", null); // string timezone _d("TIMEZONE", null); // string timezone
_d("EXTRA_EXTS", ""); // string optional extra extensions _d("EXTRA_EXTS", ""); // string optional extra extensions
_d("BASE_HREF", null); // string force a specific base URL (default is auto-detect) _d("BASE_HREF", null); // string force a specific base URL (default is auto-detect)

View File

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

View File

@ -13,5 +13,5 @@ class AdminPageInfo extends ExtensionInfo
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $description = "Provides a base for various small admin functions"; public string $description = "Provides a base for various small admin functions";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -142,7 +142,7 @@ class AutoTagger extends Extension
additional_tags VARCHAR(2000) NOT NULL additional_tags VARCHAR(2000) NOT NULL
"); ");
if ($database->get_driver_name() == DatabaseDriver::PGSQL) { if ($database->get_driver_id() == DatabaseDriverID::PGSQL) {
$database->execute('CREATE INDEX auto_tag_lower_tag_idx ON auto_tag ((lower(tag)))'); $database->execute('CREATE INDEX auto_tag_lower_tag_idx ON auto_tag ((lower(tag)))');
} }
$this->set_version(AutoTaggerConfig::VERSION, 1); $this->set_version(AutoTaggerConfig::VERSION, 1);

View File

@ -496,14 +496,14 @@ class CommentList extends Extension
global $config, $database; global $config, $database;
// sqlite fails at intervals // sqlite fails at intervals
if ($database->get_driver_name() === DatabaseDriver::SQLITE) { if ($database->get_driver_id() === DatabaseDriverID::SQLITE) {
return false; return false;
} }
$window = $config->get_int('comment_window'); $window = $config->get_int('comment_window');
$max = $config->get_int('comment_limit'); $max = $config->get_int('comment_limit');
if ($database->get_driver_name() == DatabaseDriver::MYSQL) { if ($database->get_driver_id() == DatabaseDriverID::MYSQL) {
$window_sql = "interval $window minute"; $window_sql = "interval $window minute";
} else { } else {
$window_sql = "interval '$window minute'"; $window_sql = "interval '$window minute'";

View File

@ -10,5 +10,5 @@ class DownloadInfo extends ExtensionInfo
public string $license = self::LICENSE_WTFPL; public string $license = self::LICENSE_WTFPL;
public string $description = "System-wide download functions"; public string $description = "System-wide download functions";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -13,5 +13,5 @@ class EmoticonListInfo extends ExtensionInfo
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $description = "Lists available graphical smilies"; public string $description = "Lists available graphical smilies";
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -71,7 +71,7 @@ class ET extends Extension
'shimmie' => VERSION, 'shimmie' => VERSION,
'schema' => $config->get_int("db_version"), 'schema' => $config->get_int("db_version"),
'php' => phpversion(), 'php' => phpversion(),
'db' => $database->get_driver_name() . " " . $database->get_version(), 'db' => $database->get_driver_id()->value . " " . $database->get_version(),
'os' => php_uname(), 'os' => php_uname(),
'server' => $_SERVER["SERVER_SOFTWARE"] ?? 'unknown', 'server' => $_SERVER["SERVER_SOFTWARE"] ?? 'unknown',
], ],

View File

@ -24,9 +24,9 @@ class ETTheme extends Themelet
$page->add_block(new Block("Information:", $this->build_data_form($yaml))); $page->add_block(new Block("Information:", $this->build_data_form($yaml)));
} }
protected function build_data_form($yaml): string protected function build_data_form($yaml): \MicroHTML\HTMLElement
{ {
return (string)FORM( return FORM(
["action"=>"https://shimmie.shishnet.org/register.php", "method"=>"POST"], ["action"=>"https://shimmie.shishnet.org/register.php", "method"=>"POST"],
INPUT(["type"=>"hidden", "name"=>"registration_api", "value"=>"2"]), INPUT(["type"=>"hidden", "name"=>"registration_api", "value"=>"2"]),
P( P(

View File

@ -13,5 +13,5 @@ class ETServerInfo extends ExtensionInfo
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $description = "Keep track of shimmie registrations"; public string $description = "Keep track of shimmie registrations";
public ?string $documentation = "For internal use"; public ?string $documentation = "For internal use";
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -26,7 +26,7 @@ class ETServer extends Extension
foreach ($database->get_all("SELECT responded, data FROM registration ORDER BY responded DESC") as $row) { foreach ($database->get_all("SELECT responded, data FROM registration ORDER BY responded DESC") as $row) {
$page->add_block(new Block( $page->add_block(new Block(
$row["responded"], $row["responded"],
(string)PRE(["style"=>"text-align: left; overflow: scroll;"], $row["data"]), PRE(["style"=>"text-align: left; overflow: scroll;"], $row["data"]),
"main", "main",
$n++ $n++
)); ));

View File

@ -11,7 +11,7 @@ class ExtManagerInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $visibility = self::VISIBLE_ADMIN; public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
public string $description = "A thing for point & click extension management"; public string $description = "A thing for point & click extension management";
public ?string $documentation = "Allows the admin to view a list of all extensions and enable or disable them; also allows users to view the list of activated extensions and read their documentation"; public ?string $documentation = "Allows the admin to view a list of all extensions and enable or disable them; also allows users to view the list of activated extensions and read their documentation";
public bool $core = true; public bool $core = true;

View File

@ -45,8 +45,8 @@ class ExtManagerTheme extends Themelet
); );
foreach ($extensions as $extension) { foreach ($extensions as $extension) {
if ((!$editable && $extension->visibility === ExtensionInfo::VISIBLE_ADMIN) if ((!$editable && $extension->visibility === ExtensionVisibility::ADMIN)
|| $extension->visibility === ExtensionInfo::VISIBLE_HIDDEN) { || $extension->visibility === ExtensionVisibility::HIDDEN) {
continue; continue;
} }
@ -87,7 +87,7 @@ class ExtManagerTheme extends Themelet
$page->set_title("Extensions"); $page->set_title("Extensions");
$page->set_heading("Extensions"); $page->set_heading("Extensions");
$page->add_block(new NavBlock()); $page->add_block(new NavBlock());
$page->add_block(new Block("Extension Manager", (string)$form)); $page->add_block(new Block("Extension Manager", $form));
} }
public function display_doc(Page $page, ExtensionInfo $info) public function display_doc(Page $page, ExtensionInfo $info)
@ -119,6 +119,6 @@ class ExtManagerTheme extends Themelet
$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->set_heading(html_escape($info->name));
$page->add_block(new NavBlock()); $page->add_block(new NavBlock());
$page->add_block(new Block("Documentation", (string)$html)); $page->add_block(new Block("Documentation", $html));
} }
} }

View File

@ -143,7 +143,7 @@ class Favorites extends Extension
public function onHelpPageBuilding(HelpPageBuildingEvent $event) public function onHelpPageBuilding(HelpPageBuildingEvent $event)
{ {
if ($event->key===HelpPages::SEARCH) { if ($event->key===HelpPages::SEARCH) {
$event->add_block(new Block("Favorites", (string)$this->theme->get_help_html())); $event->add_block(new Block("Favorites", $this->theme->get_help_html()));
} }
} }

View File

@ -22,11 +22,11 @@ class FeaturedTheme extends Themelet
); );
} }
public function build_featured_html(Image $image, ?string $query=null): string public function build_featured_html(Image $image, ?string $query=null): \MicroHTML\HTMLElement
{ {
$tsize = get_thumbnail_size($image->width, $image->height); $tsize = get_thumbnail_size($image->width, $image->height);
return (string)DIV( return DIV(
["style"=>"text-align: center;"], ["style"=>"text-align: center;"],
A( A(
["href"=>make_link("post/view/{$image->id}", $query)], ["href"=>make_link("post/view/{$image->id}", $query)],

View File

@ -11,7 +11,7 @@ class FourOhFourInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
public string $description = "If no other extension puts anything onto the page, show 404"; public string $description = "If no other extension puts anything onto the page, show 404";
public bool $core = true; public bool $core = true;
} }

View File

@ -11,6 +11,6 @@ class HelpPagesInfo extends ExtensionInfo
public array $authors = ["Matthew Barbour"=>"matthew@darkholme.net"]; public array $authors = ["Matthew Barbour"=>"matthew@darkholme.net"];
public string $license = self::LICENSE_WTFPL; public string $license = self::LICENSE_WTFPL;
public string $description = "Provides documentation screens"; public string $description = "Provides documentation screens";
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
public bool $core = true; public bool $core = true;
} }

View File

@ -10,7 +10,7 @@ class HomeInfo extends ExtensionInfo
public string $name = "Home Page"; public string $name = "Home Page";
public array $authors =["Bzchan"=>"bzchan@animemahou.com"]; public array $authors =["Bzchan"=>"bzchan@animemahou.com"];
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $visibility = self::VISIBLE_ADMIN; public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
public string $description = "Displays a front page with logo, search box and post count"; public string $description = "Displays a front page with logo, search box and post count";
public ?string $documentation = public ?string $documentation =
"Once enabled, the page will show up at the URL \"home\", so if you want "Once enabled, the page will show up at the URL \"home\", so if you want

View File

@ -12,6 +12,6 @@ class ImageIOInfo extends ExtensionInfo
public array $authors = [self::SHISH_NAME=> self::SHISH_EMAIL, "jgen"=>"jgen.tech@gmail.com"]; public array $authors = [self::SHISH_NAME=> self::SHISH_EMAIL, "jgen"=>"jgen.tech@gmail.com"];
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $description = "Handle the image database"; public string $description = "Handle the image database";
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
public bool $core = true; public bool $core = true;
} }

View File

@ -39,6 +39,6 @@ class ImageIOTest extends ShimmiePHPUnitTestCase
$image_id = $this->post_image("tests/pbx_screenshot.jpg", "test"); $image_id = $this->post_image("tests/pbx_screenshot.jpg", "test");
$_POST['image_id'] = "$image_id"; $_POST['image_id'] = "$image_id";
send_event(new PageRequestEvent("image/replace")); send_event(new PageRequestEvent("image/replace"));
$this->assertEquals("redirect", $page->mode); $this->assertEquals(PageMode::REDIRECT, $page->mode);
} }
} }

View File

@ -13,115 +13,7 @@ class IndexInfo extends ExtensionInfo
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $description = "Show a list of uploaded posts"; public string $description = "Show a list of uploaded posts";
public bool $core = true; public bool $core = true;
public ?string $documentation = "Here is a list of the search methods available out of the box; public ?string $documentation = " etc.
Shimmie extensions may provide other filters:
<ul>
<li>by tag, eg
<ul>
<li>cat
<li>pie
<li>somethi* -- wildcards are supported
</ul>
</li>
<li>size (=, &lt;, &gt;, &lt;=, &gt;=) width x height, eg
<ul>
<li>size=1024x768 -- a specific wallpaper size
<li>size&gt;=500x500 -- no small posts
<li>size&lt;1000x1000 -- no large posts
</ul>
</li>
<li>width (=, &lt;, &gt;, &lt;=, &gt;=) width, eg
<ul>
<li>width=1024 -- find posts with 1024 width
<li>width>2000 -- find posts bigger than 2000 width
</ul>
</li>
<li>height (=, &lt;, &gt;, &lt;=, &gt;=) height, eg
<ul>
<li>height=768 -- find posts with 768 height
<li>height>1000 -- find posts bigger than 1000 height
</ul>
</li>
<li>ratio (=, &lt;, &gt;, &lt;=, &gt;=) width : height, eg
<ul>
<li>ratio=4:3, ratio=16:9 -- standard wallpaper
<li>ratio=1:1 -- square posts
<li>ratio<1:1 -- tall posts
<li>ratio>1:1 -- wide posts
</ul>
</li>
<li>filesize (=, &lt;, &gt;, &lt;=, &gt;=) size, eg
<ul>
<li>filesize&gt;1024 -- no posts under 1KB
<li>filesize&lt=3MB -- shorthand filesizes are supported too
</ul>
</li>
<li>id (=, &lt;, &gt;, &lt;=, &gt;=) number, eg
<ul>
<li>id<20 -- search only the first few posts
<li>id>=500 -- search later posts
</ul>
</li>
<li>user=Username & poster=Username, eg
<ul>
<li>user=Shish -- find all of Shish's posts
<li>poster=Shish -- same as above
</ul>
</li>
<li>user_id=userID & poster_id=userID, eg
<ul>
<li>user_id=2 -- find all posts by user id 2
<li>poster_id=2 -- same as above
</ul>
</li>
<li>hash=md5sum & md5=md5sum, eg
<ul>
<li>hash=bf5b59173f16b6937a4021713dbfaa72 -- find the \"Taiga want up!\" post
<li>md5=bf5b59173f16b6937a4021713dbfaa72 -- same as above
</ul>
</li>
<li>filename=blah & name=blah, eg
<ul>
<li>filename=kitten -- find all posts with \"kitten\" in the original filename
<li>name=kitten -- same as above
</ul>
</li>
<li>posted (=, &lt;, &gt;, &lt;=, &gt;=) date, eg
<ul>
<li>posted&gt;=2009-12-25 posted&lt;=2010-01-01 -- find posts posted between christmas and new year
</ul>
</li>
<li>tags (=, &lt;, &gt;, &lt;=, &gt;=) count, eg
<ul>
<li>tags=1 -- search for posts with only 1 tag
<li>tags>=10 -- search for posts with 10 or more tags
<li>tags<25 -- search for posts with less than 25 tags
</ul>
</li>
<li>source=(URL, any, none) eg
<ul>
<li>source=http://example.com -- find all posts with \"http://example.com\" in the source
<li>source=any -- find all posts with a source
<li>source=none -- find all posts without a source
</ul>
</li>
<li>order=(id, width, height, filesize, filename)_(ASC, DESC), eg
<ul>
<li>order=width -- find all posts sorted from highest > lowest width
<li>order=filesize_asc -- find all posts sorted from lowest > highest filesize
</ul>
</li>
<li>order=random_####, eg
<ul>
<li>order=random_8547 -- find all posts sorted randomly using 8547 as a seed
</ul>
</li>
</ul>
<p>Search items can be combined to search for posts which match both,
or you can stick \"-\" in front of an item to search for things that don't
match it.
<p>Metatags can be followed by \":\" rather than \"=\" if you prefer.
<br />I.E: \"posted:2014-01-01\", \"id:>=500\" etc.
<p>Some search methods provided by extensions: <p>Some search methods provided by extensions:
<ul> <ul>
<li>Numeric Score <li>Numeric Score

View File

@ -291,8 +291,8 @@ and of course start organising your images :-)
<p>Search for posts by source</p> <p>Search for posts by source</p>
<div class="command_example"> <div class="command_example">
<pre>source=http://google.com/</pre> <pre>source=https:///google.com/</pre>
<p>Returns posts with a source of "http://google.com/".</p> <p>Returns posts with a source of "https://google.com/".</p>
</div> </div>
<div class="command_example"> <div class="command_example">

View File

@ -10,6 +10,6 @@ class LiveFeedInfo extends ExtensionInfo
public string $name = "Live Feed"; public string $name = "Live Feed";
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $visibility = self::VISIBLE_ADMIN; public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
public string $description = "Logs user-safe (no IPs) data to a UDP socket, eg IRCCat"; public string $description = "Logs user-safe (no IPs) data to a UDP socket, eg IRCCat";
} }

View File

@ -11,5 +11,5 @@ class LogDatabaseInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $description = "Keep a record of SCore events (in the database)."; public string $description = "Keep a record of SCore events (in the database).";
public string $visibility = self::VISIBLE_ADMIN; public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
} }

View File

@ -11,5 +11,5 @@ class LogLogstashInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $description = "Send log events to a network port."; public string $description = "Send log events to a network port.";
public string $visibility = self::VISIBLE_ADMIN; public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
} }

View File

@ -11,5 +11,5 @@ class LogNetInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $description = "Send log events to a network port."; public string $description = "Send log events to a network port.";
public string $visibility = self::VISIBLE_ADMIN; public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
} }

View File

@ -13,5 +13,5 @@ class MediaInfo extends ExtensionInfo
public string $license = self::LICENSE_WTFPL; public string $license = self::LICENSE_WTFPL;
public string $description = "Provides common functions and settings used for media operations."; public string $description = "Provides common functions and settings used for media operations.";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -902,9 +902,9 @@ class Media extends Extension
if ($this->get_version(MediaConfig::VERSION) < 2) { if ($this->get_version(MediaConfig::VERSION) < 2) {
$database->execute("ALTER TABLE images ADD COLUMN image BOOLEAN NULL"); $database->execute("ALTER TABLE images ADD COLUMN image BOOLEAN NULL");
switch ($database->get_driver_name()) { switch ($database->get_driver_id()) {
case DatabaseDriver::PGSQL: case DatabaseDriverID::PGSQL:
case DatabaseDriver::SQLITE: case DatabaseDriverID::SQLITE:
$database->execute('CREATE INDEX images_image_idx ON images(image) WHERE image IS NOT NULL'); $database->execute('CREATE INDEX images_image_idx ON images(image) WHERE image IS NOT NULL');
break; break;
default: default:

View File

@ -12,5 +12,5 @@ class MimeSystemInfo extends ExtensionInfo
public string $license = self::LICENSE_WTFPL; public string $license = self::LICENSE_WTFPL;
public string $description = "Provides system mime-related functionality"; public string $description = "Provides system mime-related functionality";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -551,8 +551,8 @@ class OuroborosAPI extends Extension
if (array_key_exists(0, $data)) { if (array_key_exists(0, $data)) {
$xml->startElement($type . 's'); $xml->startElement($type . 's');
if ($type == 'post') { if ($type == 'post') {
$xml->writeAttribute('count', count($data)); $xml->writeAttribute('count', (string)count($data));
$xml->writeAttribute('offset', $offset); $xml->writeAttribute('offset', (string)$offset);
} }
if ($type == 'tag') { if ($type == 'tag') {
$xml->writeAttribute('type', 'array'); $xml->writeAttribute('type', 'array');

View File

@ -916,9 +916,8 @@ class Pools extends Extension
if ($entry['action'] == 0) { if ($entry['action'] == 0) {
// READ ENTRIES // READ ENTRIES
foreach ($images as $image) { foreach ($images as $imageID) {
$imageID = $image; $this->add_post($poolID, int_escape($imageID));
$this->add_post($poolID, $imageID);
$imageArray .= " " . $imageID; $imageArray .= " " . $imageID;
$newAction = 1; $newAction = 1;

View File

@ -121,7 +121,7 @@ class PoolsTest extends ShimmiePHPUnitTestCase
"pool_id" => $pool_id, "pool_id" => $pool_id,
"check" => [(string)($image_ids[0]), (string)($image_ids[1])] "check" => [(string)($image_ids[0]), (string)($image_ids[1])]
]); ]);
$this->assertEquals("redirect", $page->mode); $this->assertEquals(PageMode::REDIRECT, $page->mode);
return [$pool_id, $image_ids]; return [$pool_id, $image_ids];
} }
@ -135,7 +135,7 @@ class PoolsTest extends ShimmiePHPUnitTestCase
"pool_id" => $pool_id, "pool_id" => $pool_id,
"check" => [(string)($image_ids[0]), (string)($image_ids[1])] "check" => [(string)($image_ids[0]), (string)($image_ids[1])]
]); ]);
$this->assertEquals("redirect", $page->mode); $this->assertEquals(PageMode::REDIRECT, $page->mode);
} }
/** @depends testCreate */ /** @depends testCreate */
@ -147,7 +147,7 @@ class PoolsTest extends ShimmiePHPUnitTestCase
"pool_id" => $pool_id, "pool_id" => $pool_id,
"description" => "Updated description" "description" => "Updated description"
]); ]);
$this->assertEquals("redirect", $page->mode); $this->assertEquals(PageMode::REDIRECT, $page->mode);
return [$pool_id, $image_ids]; return [$pool_id, $image_ids];
} }
@ -173,6 +173,6 @@ class PoolsTest extends ShimmiePHPUnitTestCase
$page = $this->post_page("pool/nuke", [ $page = $this->post_page("pool/nuke", [
"pool_id" => "$pool_id", "pool_id" => "$pool_id",
]); ]);
$this->assertEquals("redirect", $page->mode); $this->assertEquals(PageMode::REDIRECT, $page->mode);
} }
} }

View File

@ -501,11 +501,11 @@ class Ratings extends Extension
if ($this->get_version(RatingsConfig::VERSION) < 3) { if ($this->get_version(RatingsConfig::VERSION) < 3) {
$database->execute("UPDATE images SET rating = 'u' WHERE rating is null"); $database->execute("UPDATE images SET rating = 'u' WHERE rating is null");
switch ($database->get_driver_name()) { switch ($database->get_driver_id()) {
case DatabaseDriver::MYSQL: case DatabaseDriverID::MYSQL:
$database->execute("ALTER TABLE images CHANGE rating rating CHAR(1) NOT NULL DEFAULT 'u'"); $database->execute("ALTER TABLE images CHANGE rating rating CHAR(1) NOT NULL DEFAULT 'u'");
break; break;
case DatabaseDriver::PGSQL: case DatabaseDriverID::PGSQL:
$database->execute("ALTER TABLE images ALTER COLUMN rating SET DEFAULT 'u'"); $database->execute("ALTER TABLE images ALTER COLUMN rating SET DEFAULT 'u'");
$database->execute("ALTER TABLE images ALTER COLUMN rating SET NOT NULL"); $database->execute("ALTER TABLE images ALTER COLUMN rating SET NOT NULL");
break; break;
@ -527,11 +527,11 @@ class Ratings extends Extension
$config->set_array("ext_rating_admin_privs", str_split($value)); $config->set_array("ext_rating_admin_privs", str_split($value));
} }
switch ($database->get_driver_name()) { switch ($database->get_driver_id()) {
case DatabaseDriver::MYSQL: case DatabaseDriverID::MYSQL:
$database->execute("ALTER TABLE images CHANGE rating rating CHAR(1) NOT NULL DEFAULT '?'"); $database->execute("ALTER TABLE images CHANGE rating rating CHAR(1) NOT NULL DEFAULT '?'");
break; break;
case DatabaseDriver::PGSQL: case DatabaseDriverID::PGSQL:
$database->execute("ALTER TABLE images ALTER COLUMN rating SET DEFAULT '?'"); $database->execute("ALTER TABLE images ALTER COLUMN rating SET DEFAULT '?'");
break; break;
} }

View File

@ -14,5 +14,5 @@ class Rule34Info extends ExtensionInfo
public string $description = "Extra site-specific bits"; public string $description = "Extra site-specific bits";
public ?string $documentation = public ?string $documentation =
"Probably not much use to other sites, but it gives a few examples of how a shimmie-based site can be integrated with other systems"; "Probably not much use to other sites, but it gives a few examples of how a shimmie-based site can be integrated with other systems";
public array $db_support = [DatabaseDriver::PGSQL]; # Only PG has the NOTIFY pubsub system public array $db_support = [DatabaseDriverID::PGSQL]; # Only PG has the NOTIFY pubsub system
} }

View File

@ -12,5 +12,5 @@ class SetupInfo extends ExtensionInfo
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $description = "Allows the site admin to configure the board to his or her taste"; public string $description = "Allows the site admin to configure the board to his or her taste";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -11,7 +11,7 @@ class SiteDescriptionInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $visibility = self::VISIBLE_ADMIN; public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
public string $description = "A description for search engines"; public string $description = "A description for search engines";
public ?string $documentation = public ?string $documentation =
"This extension sets the \"description\" meta tag in the header of pages so that search engines can pick it up"; "This extension sets the \"description\" meta tag in the header of pages so that search engines can pick it up";

View File

@ -11,7 +11,7 @@ class StaticFilesInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
public string $description = 'If Shimmie can\'t handle a request, check static files ($theme/static/$filename, then ext/static_files/static/$filename)'; public string $description = 'If Shimmie can\'t handle a request, check static files ($theme/static/$filename, then ext/static_files/static/$filename)';
public bool $core = true; public bool $core = true;
} }

View File

@ -11,7 +11,7 @@ class StatsDInterfaceInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $visibility = self::VISIBLE_ADMIN; public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
public string $description = "Sends Shimmie stats to a StatsD server"; public string $description = "Sends Shimmie stats to a StatsD server";
public ?string $documentation = "define('STATSD_HOST', 'my.server.com:8125'); in shimmie.conf.php to set the host"; public ?string $documentation = "define('STATSD_HOST', 'my.server.com:8125'); in shimmie.conf.php to set the host";
} }

View File

@ -12,5 +12,5 @@ class SystemInfo extends ExtensionInfo
public string $license = self::LICENSE_WTFPL; public string $license = self::LICENSE_WTFPL;
public string $description = "Provides system screen"; public string $description = "Provides system screen";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -12,5 +12,5 @@ class TagListInfo extends ExtensionInfo
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $description = "Show the tags in various ways"; public string $description = "Show the tags in various ways";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -9,6 +9,6 @@ class TaggerXMLInfo extends ExtensionInfo
public string $key = self::KEY; public string $key = self::KEY;
public string $name = "Tagger AJAX backend"; public string $name = "Tagger AJAX backend";
public array $authors = ["Artanis (Erik Youngren)"=>"artanis.00@gmail.com"]; public array $authors = ["Artanis (Erik Youngren)"=>"artanis.00@gmail.com"];
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
public string $description = "Advanced Tagging v2 AJAX backend"; public string $description = "Advanced Tagging v2 AJAX backend";
} }

View File

@ -12,5 +12,5 @@ class TipsInfo extends ExtensionInfo
public string $license = "GPLv2"; public string $license = "GPLv2";
public string $description = "Show a random line of text in the subheader space"; public string $description = "Show a random line of text in the subheader space";
public ?string $documentation = "Formatting is done with HTML"; public ?string $documentation = "Formatting is done with HTML";
public array $db_support = [DatabaseDriver::MYSQL, DatabaseDriver::SQLITE]; // rand() ? public array $db_support = [DatabaseDriverID::MYSQL, DatabaseDriverID::SQLITE]; // rand() ?
} }

View File

@ -11,6 +11,6 @@ class UpgradeInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $description = "Keeps things happy behind the scenes"; public string $description = "Keeps things happy behind the scenes";
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
public bool $core = true; public bool $core = true;
} }

View File

@ -42,7 +42,7 @@ class Upgrade extends Extension
} }
if ($this->get_version("db_version") < 9) { if ($this->get_version("db_version") < 9) {
if ($database->get_driver_name() == DatabaseDriver::MYSQL) { if ($database->get_driver_id() == DatabaseDriverID::MYSQL) {
$tables = $database->get_col("SHOW TABLES"); $tables = $database->get_col("SHOW TABLES");
foreach ($tables as $table) { foreach ($tables as $table) {
log_info("upgrade", "converting $table to innodb"); log_info("upgrade", "converting $table to innodb");
@ -70,7 +70,7 @@ class Upgrade extends Extension
} }
if ($this->get_version("db_version") < 12) { if ($this->get_version("db_version") < 12) {
if ($database->get_driver_name() == DatabaseDriver::PGSQL) { if ($database->get_driver_id() == DatabaseDriverID::PGSQL) {
log_info("upgrade", "Changing ext column to VARCHAR"); log_info("upgrade", "Changing ext column to VARCHAR");
$database->execute("ALTER TABLE images ALTER COLUMN ext SET DATA TYPE VARCHAR(4)"); $database->execute("ALTER TABLE images ALTER COLUMN ext SET DATA TYPE VARCHAR(4)");
} }
@ -83,9 +83,9 @@ class Upgrade extends Extension
if ($this->get_version("db_version") < 13) { if ($this->get_version("db_version") < 13) {
log_info("upgrade", "Changing password column to VARCHAR(250)"); log_info("upgrade", "Changing password column to VARCHAR(250)");
if ($database->get_driver_name() == DatabaseDriver::PGSQL) { if ($database->get_driver_id() == DatabaseDriverID::PGSQL) {
$database->execute("ALTER TABLE users ALTER COLUMN pass SET DATA TYPE VARCHAR(250)"); $database->execute("ALTER TABLE users ALTER COLUMN pass SET DATA TYPE VARCHAR(250)");
} elseif ($database->get_driver_name() == DatabaseDriver::MYSQL) { } elseif ($database->get_driver_id() == DatabaseDriverID::MYSQL) {
$database->execute("ALTER TABLE users CHANGE pass pass VARCHAR(250)"); $database->execute("ALTER TABLE users CHANGE pass pass VARCHAR(250)");
} }
@ -94,11 +94,11 @@ class Upgrade extends Extension
if ($this->get_version("db_version") < 14) { if ($this->get_version("db_version") < 14) {
log_info("upgrade", "Changing tag column to VARCHAR(255)"); log_info("upgrade", "Changing tag column to VARCHAR(255)");
if ($database->get_driver_name() == DatabaseDriver::PGSQL) { if ($database->get_driver_id() == DatabaseDriverID::PGSQL) {
$database->execute('ALTER TABLE tags ALTER COLUMN tag SET DATA TYPE VARCHAR(255)'); $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 oldtag SET DATA TYPE VARCHAR(255)');
$database->execute('ALTER TABLE aliases ALTER COLUMN newtag SET DATA TYPE VARCHAR(255)'); $database->execute('ALTER TABLE aliases ALTER COLUMN newtag SET DATA TYPE VARCHAR(255)');
} elseif ($database->get_driver_name() == DatabaseDriver::MYSQL) { } elseif ($database->get_driver_id() == DatabaseDriverID::MYSQL) {
$database->execute('ALTER TABLE tags MODIFY COLUMN tag VARCHAR(255) NOT NULL'); $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 oldtag VARCHAR(255) NOT NULL');
$database->execute('ALTER TABLE aliases MODIFY COLUMN newtag VARCHAR(255) NOT NULL'); $database->execute('ALTER TABLE aliases MODIFY COLUMN newtag VARCHAR(255) NOT NULL');
@ -109,7 +109,7 @@ class Upgrade extends Extension
if ($this->get_version("db_version") < 15) { if ($this->get_version("db_version") < 15) {
log_info("upgrade", "Adding lower indexes for postgresql use"); log_info("upgrade", "Adding lower indexes for postgresql use");
if ($database->get_driver_name() == DatabaseDriver::PGSQL) { if ($database->get_driver_id() == DatabaseDriverID::PGSQL) {
$database->execute('CREATE INDEX tags_lower_tag_idx ON tags ((lower(tag)))'); $database->execute('CREATE INDEX tags_lower_tag_idx ON tags ((lower(tag)))');
$database->execute('CREATE INDEX users_lower_name_idx ON users ((lower(name)))'); $database->execute('CREATE INDEX users_lower_name_idx ON users ((lower(name)))');
} }
@ -122,13 +122,13 @@ class Upgrade extends Extension
$database->execute('CREATE UNIQUE INDEX image_tags_tag_id_image_id_idx ON image_tags(tag_id,image_id) '); $database->execute('CREATE UNIQUE INDEX image_tags_tag_id_image_id_idx ON image_tags(tag_id,image_id) ');
log_info("upgrade", "Changing filename column to VARCHAR(255)"); log_info("upgrade", "Changing filename column to VARCHAR(255)");
if ($database->get_driver_name() == DatabaseDriver::PGSQL) { if ($database->get_driver_id() == DatabaseDriverID::PGSQL) {
$database->execute('ALTER TABLE images ALTER COLUMN filename SET DATA TYPE VARCHAR(255)'); $database->execute('ALTER TABLE images ALTER COLUMN filename SET DATA TYPE VARCHAR(255)');
// Postgresql creates a unique index for unique columns, not just a constraint, // Postgresql creates a unique index for unique columns, not just a constraint,
// so we don't need two indexes on the same column // so we don't need two indexes on the same column
$database->execute('DROP INDEX IF EXISTS images_hash_idx'); $database->execute('DROP INDEX IF EXISTS images_hash_idx');
$database->execute('DROP INDEX IF EXISTS users_name_idx'); $database->execute('DROP INDEX IF EXISTS users_name_idx');
} elseif ($database->get_driver_name() == DatabaseDriver::MYSQL) { } elseif ($database->get_driver_id() == DatabaseDriverID::MYSQL) {
$database->execute('ALTER TABLE images MODIFY COLUMN filename VARCHAR(255) NOT NULL'); $database->execute('ALTER TABLE images MODIFY COLUMN filename VARCHAR(255) NOT NULL');
} }
// SQLite doesn't support altering existing columns? This seems like a problem? // SQLite doesn't support altering existing columns? This seems like a problem?
@ -144,9 +144,9 @@ class Upgrade extends Extension
$database->execute("ALTER TABLE images ADD COLUMN length INTEGER NULL "); $database->execute("ALTER TABLE images ADD COLUMN length INTEGER NULL ");
log_info("upgrade", "Setting indexes for media columns"); log_info("upgrade", "Setting indexes for media columns");
switch ($database->get_driver_name()) { switch ($database->get_driver_id()) {
case DatabaseDriver::PGSQL: case DatabaseDriverID::PGSQL:
case DatabaseDriver::SQLITE: case DatabaseDriverID::SQLITE:
$database->execute('CREATE INDEX images_video_idx ON images(video) WHERE video IS NOT NULL'); $database->execute('CREATE INDEX images_video_idx ON images(video) WHERE video IS NOT NULL');
$database->execute('CREATE INDEX images_audio_idx ON images(audio) WHERE audio IS NOT NULL'); $database->execute('CREATE INDEX images_audio_idx ON images(audio) WHERE audio IS NOT NULL');
$database->execute('CREATE INDEX images_length_idx ON images(length) WHERE length IS NOT NULL'); $database->execute('CREATE INDEX images_length_idx ON images(length) WHERE length IS NOT NULL');

View File

@ -12,5 +12,5 @@ class UploadInfo extends ExtensionInfo
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $description = "Allows people to upload files to the website"; public string $description = "Allows people to upload files to the website";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -11,5 +11,5 @@ class UserPageInfo extends ExtensionInfo
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $description = "Allows people to sign up to the website"; public string $description = "Allows people to sign up to the website";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -11,6 +11,6 @@ class UserConfigInfo extends ExtensionInfo
public array $authors = ["Matthew Barbour"=>"matthew@darkholme.net"]; public array $authors = ["Matthew Barbour"=>"matthew@darkholme.net"];
public string $license = self::LICENSE_WTFPL; public string $license = self::LICENSE_WTFPL;
public string $description = "Provides system-wide support for user-specific settings"; public string $description = "Provides system-wide support for user-specific settings";
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
public bool $core = true; public bool $core = true;
} }

View File

@ -11,6 +11,6 @@ class VarnishPurgerInfo extends ExtensionInfo
public string $url = self::SHIMMIE_URL; public string $url = self::SHIMMIE_URL;
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $license = self::LICENSE_GPLV2; public string $license = self::LICENSE_GPLV2;
public string $visibility = self::VISIBLE_ADMIN; public ExtensionVisibility $visibility = ExtensionVisibility::ADMIN;
public string $description = "Sends PURGE requests when a /post/view is updated"; public string $description = "Sends PURGE requests when a /post/view is updated";
} }

View File

@ -12,5 +12,5 @@ class ViewImageInfo extends ExtensionInfo
public array $authors = self::SHISH_AUTHOR; public array $authors = self::SHISH_AUTHOR;
public string $description = "Allows users to see uploaded posts"; public string $description = "Allows users to see uploaded posts";
public bool $core = true; public bool $core = true;
public string $visibility = self::VISIBLE_HIDDEN; public ExtensionVisibility $visibility = ExtensionVisibility::HIDDEN;
} }

View File

@ -42,8 +42,8 @@
<li><a href="#" class="top_parent">Sites</a> <li><a href="#" class="top_parent">Sites</a>
<ul> <ul>
<li><a href="//rule34.paheal.net/" class="sub_option">Rule #34</a></li> <li><a href="//rule34.paheal.net/" class="sub_option">Rule #34</a></li>
<li><a href="http://rule63.paheal.net/" class="sub_option">Rule #63</a></li> <li><a href="//rule63.paheal.net/" class="sub_option">Rule #63</a></li>
<li><a href="http://cosplay.paheal.net/" class="sub_option">Cosplay</a></li> <li><a href="//cosplay.paheal.net/" class="sub_option">Cosplay</a></li>
<li><a href="//rule34c.paheal.net/" class="sub_option">Rule #34c</a></li> <li><a href="//rule34c.paheal.net/" class="sub_option">Rule #34c</a></li>
</ul> </ul>
</li> </li>
@ -52,7 +52,7 @@
<ul> <ul>
<li><a href="#" class="top_parent">Community &#9660;</a> <li><a href="#" class="top_parent">Community &#9660;</a>
<ul> <ul>
<!--<li><a href="http://forum.paheal.net" class="sub_option">Forum</a></li>--> <!--<li><a href="//forum.paheal.net" class="sub_option">Forum</a></li>-->
<li><a href="//rule34.paheal.net/wiki/friends" class="parent">Friends of paheal</a> <li><a href="//rule34.paheal.net/wiki/friends" class="parent">Friends of paheal</a>
<li><a href="//rule34.paheal.net/wiki/DNP" class="parent">DNP List</a> <li><a href="//rule34.paheal.net/wiki/DNP" class="parent">DNP List</a>
<li><a href="#" class="parent">Chat</a> <li><a href="#" class="parent">Chat</a>

View File

@ -53,7 +53,7 @@ EOD
"; ";
return " return "
<div id='front-page'> <div id='front-page'>
<h1><a style='text-decoration: none;' href='".make_link()."'><span>$sitename</span></a></h1> <h1><a style='text-decoration: none;' href='".make_link(). "'><span>$sitename</span></a></h1>
$main_links_html $main_links_html
$search_html $search_html
$message_html $message_html
@ -68,7 +68,7 @@ EOD
<small><small> <small><small>
$contact_link Serving $num_comma posts &ndash; $contact_link Serving $num_comma posts &ndash;
Running <a href='http://code.shishnet.org/shimmie2/'>Shimmie2</a> Running <a href='https://code.shishnet.org/shimmie2/'>Shimmie2</a>
</small></small> </small></small>
</div> </div>
</div>"; </div>";