summaryrefslogtreecommitdiff
path: root/src/application
diff options
context:
space:
mode:
Diffstat (limited to 'src/application')
-rw-r--r--src/application/i18n.php26
-rw-r--r--src/application/messages/de.msg20
-rw-r--r--src/application/messages/strings.mst173
-rw-r--r--src/application/mystic/forum/Database.php7
-rw-r--r--src/application/views/alert_error.php9
-rw-r--r--src/application/views/alert_info.php9
-rw-r--r--src/application/views/alert_success.php9
-rw-r--r--src/application/views/form_register.php2
-rw-r--r--src/application/views/template_end.php2
-rw-r--r--src/application/views/template_start.php3
-rw-r--r--src/application/views/view_post.php26
-rw-r--r--src/application/views/view_topic_start.php54
-rw-r--r--src/application/views/view_user.php8
13 files changed, 331 insertions, 17 deletions
diff --git a/src/application/i18n.php b/src/application/i18n.php
index f5b755d..cdc61e1 100644
--- a/src/application/i18n.php
+++ b/src/application/i18n.php
@@ -9,7 +9,8 @@ const MESSAGE_DIR = __DIR__ . "/messages";
$__i18n_msg_store = [];
$__i18n_msg_store_plural = [];
$__i18n_msg_metadata = [];
-$__i18n_current_locale = null;
+/** @var string $__i18n_current_locale */
+$__i18n_current_locale = "en";
const _I18N_MSGID = 0;
const _I18N_MSGSTR = 1;
@@ -200,7 +201,7 @@ function i18n_get_plural(string $msgid_singular, string $msgid_plural, int $coun
$ctx->def("n", $count);
$parser = new Parser(new Scanner($expression));
$index = $parser->reduce($ctx);
- $index = max(0, min(count($msgs), $index));
+ $index = max(0, min(count($msgs) - 1, $index));
$msg = $msgs[$index];
}
@@ -212,6 +213,27 @@ function i18n_get_plural(string $msgid_singular, string $msgid_plural, int $coun
);
}
+function i18n_get_current_locale(): string {
+ global $__i18n_current_locale;
+ return $__i18n_current_locale;
+}
+
+function i18n_get_available_locales(): array {
+ global $__i18n_msg_store;
+ return [
+ "en",
+ ...array_keys($__i18n_msg_store),
+ ];
+}
+
+function i18n_get_message_store(string $locale): array {
+ global $__i18n_msg_store, $__i18n_msg_store_plural;
+ return [
+ $__i18n_msg_store[$locale] ?? (object)[],
+ $__i18n_msg_store_plural[$locale] ?? (object)[],
+ ];
+}
+
function __(string $msgid, array $params = [], ?string $context = null): string {
return i18n_get($msgid, $params, $context);
}
diff --git a/src/application/messages/de.msg b/src/application/messages/de.msg
index c797241..a7f401d 100644
--- a/src/application/messages/de.msg
+++ b/src/application/messages/de.msg
@@ -10,8 +10,17 @@ metadata({
: "Register"
= "Registrieren"
-: "Failed to connect to database!"
-= "Fehler bei Datenbankverbindung"
+: "Error"
+= "Fehler"
+
+: "Failed to connect to database:\n%details%"
+= "Fehler bei der Datenbankverbindung:\n%details%"
+
+: "Attachment"
+= "Anhang"
+
+: "Download"
+= "Herunterladen"
: "Username or password incorrect!"
= "Nutzername oder Passwort falsch!"
@@ -116,8 +125,8 @@ metadata({
: "No attachment exists with this id"
= "Kein Anhang exsitier mit dieser ID"
-: "Attachment is not an image"
-= "Anhang ist kein Bild"
+: "Attachment is neither an image nor a video"
+= "Anhang ist weder Bild noch Video"
: "Delete post"
= "Beitrag löschen"
@@ -275,3 +284,6 @@ metadata({
- "%n% Datei ausgewählt"
- "%n% Dateien ausgewählt"
- "Keine Datei ausgewählt"
+
+: "Created this topic"
+= "Hat dieses Thema erstellt"
diff --git a/src/application/messages/strings.mst b/src/application/messages/strings.mst
index 6f6ec38..51ab91d 100644
--- a/src/application/messages/strings.mst
+++ b/src/application/messages/strings.mst
@@ -1,10 +1,25 @@
+metadata({
+ "plural": {
+ "indexMapping": "ifelse(n = 0, 2, ifelse(n = 1, 0, 1))"
+ }
+})
+
: "Log in"
= ""
: "Register"
= ""
-: "Failed to connect to database!"
+: "Error"
+= ""
+
+: "Failed to connect to database:\n%details%"
+= ""
+
+: "Attachment"
+= ""
+
+: "Download"
= ""
: "Username or password incorrect!"
@@ -104,8 +119,162 @@
: "No attachment exists with this id"
= ""
-: "Attachment is not an image"
+: "Attachment is neither an image nor a video"
= ""
: "Delete post"
= ""
+
+: "Username:"
+= ""
+
+: "Display name:"
+= ""
+
+: "Choose password:"
+= ""
+
+: "Repeat password:"
+= ""
+
+: "Email address:"
+= ""
+
+: "CAPTCHA:"
+= ""
+
+: "New CAPTCHA"
+= ""
+
+: "Register now"
+= ""
+
+: "Already have an account? %link%Sign in now%/link%"
+= ""
+
+: "Don't have an account? %link%Register now%/link%"
+= ""
+
+: "Edit post"
+= ""
+
+: "Message:"
+= ""
+
+: "Cancel"
+= ""
+
+: "Save changes"
+= ""
+
+: "Permission denied"
+= ""
+
+: "Close"
+= ""
+
+: "Edit title"
+= ""
+
+: "Reply"
+= ""
+
+: "Delete topic"
+= ""
+
+: "(deleted)"
+= ""
+
+: "Started by %user% on %date%"
+= ""
+
+: "Welcome, %user%!"
+= ""
+
+: "This post has been deleted"
+= ""
+
+: "Profile picture"
+= ""
+
+: "Permalink"
+= ""
+
+: "Reply to post"
+= ""
+
+: "(edited)"
+= ""
+
+: "You"
+= ""
+
+: "Reply to this topic"
+= ""
+
+: "Attachments: <small>(max. %max_attachment_count% files, max. %max_attachment_size% MiB each)</small>"
+= ""
+
+: "Post reply"
+= ""
+
+: "Topic title:"
+= ""
+
+: "Create topic"
+= ""
+
+: "Member since %join_date%"
+= ""
+
+: "Your posts"
+= ""
+
+: "%display_name%'s posts"
+= ""
+
+: "unknown"
+= ""
+
+: "posted on %post_date% in %topic%"
+= ""
+
+: "Show all posts"
+= ""
+
+: "This user has not posted anything yet"
+= ""
+
+: "Edit profile"
+= ""
+
+: "Profile picture:"
+= ""
+
+: "Keep current profile picture"
+= ""
+
+: "No profile picture"
+= ""
+
+: "Remove profile picture"
+= ""
+
+: "Upload new profile picture"
+= ""
+
+:...
+- "Select file"
+- "Select files"
+=...
+- ""
+
+:...
+- "%n% file selected"
+- "%n% files selected"
+- "No files selected"
+=...
+- ""
+
+: "Created this topic"
+= ""
diff --git a/src/application/mystic/forum/Database.php b/src/application/mystic/forum/Database.php
index 6d633fa..a1e67ea 100644
--- a/src/application/mystic/forum/Database.php
+++ b/src/application/mystic/forum/Database.php
@@ -47,13 +47,20 @@ class Database {
return $buf;
}
+ private static function exception_error_handler($errno, $errstr, $errfile, $errline ) {
+ throw new \ErrorException(html_entity_decode($errstr), $errno, 0, $errfile, $errline);
+ }
+
public function __construct(string $connectionString) {
try {
+ set_error_handler(self::exception_error_handler(...));
$conn = \pg_connect($connectionString);
if ($conn !== false)
$this->connection = $conn;
} catch (\ErrorException $ex) {
throw new DatabaseConnectionException($ex->getMessage(), $ex->getCode(), $ex);
+ } finally {
+ restore_error_handler();
}
}
diff --git a/src/application/views/alert_error.php b/src/application/views/alert_error.php
index c18546b..acdb295 100644
--- a/src/application/views/alert_error.php
+++ b/src/application/views/alert_error.php
@@ -1,3 +1,10 @@
+<?php
+if (str_starts_with($message, "?!HTML::"))
+ $message = substr($message, 8);
+else
+ $message = htmlentities($message);
+?>
<div class="alert alert-danger" role="alert">
-<?= htmlentities($message); ?>
+<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
+<?= $message; ?>
</div>
diff --git a/src/application/views/alert_info.php b/src/application/views/alert_info.php
new file mode 100644
index 0000000..7bf2e7b
--- /dev/null
+++ b/src/application/views/alert_info.php
@@ -0,0 +1,9 @@
+<?php
+if (str_starts_with($message, "?!HTML::"))
+ $message = substr($message, 8);
+else
+ $message = htmlentities($message);
+?>
+<div class="alert alert-info" role="alert">
+<?= $message; ?>
+</div>
diff --git a/src/application/views/alert_success.php b/src/application/views/alert_success.php
new file mode 100644
index 0000000..de3e023
--- /dev/null
+++ b/src/application/views/alert_success.php
@@ -0,0 +1,9 @@
+<?php
+if (str_starts_with($message, "?!HTML::"))
+ $message = substr($message, 8);
+else
+ $message = htmlentities($message);
+?>
+<div class="alert alert-success" role="alert">
+<?= $message; ?>
+</div>
diff --git a/src/application/views/form_register.php b/src/application/views/form_register.php
index a37e5c3..a082611 100644
--- a/src/application/views/form_register.php
+++ b/src/application/views/form_register.php
@@ -27,7 +27,7 @@ if (($_formError = RequestUtils::getAndClearFormError()) !== null) {
<div class="form-group" id="group1">
<label for="i_username"><?= __("Username:") ?></label>
- <input class="form-control" id="i_username" type="text" name="df82a9bc21" value="<?= htmlentities($lastForm["username"] ?? "") ?>" required>
+ <input class="form-control" id="i_username" type="text" name="df82a9bc21" value="<?= htmlentities($lastForm["df82a9bc21"] ?? "") ?>" required>
</div>
<div class="form-group" id="group2">
diff --git a/src/application/views/template_end.php b/src/application/views/template_end.php
index c30330e..d12e2ff 100644
--- a/src/application/views/template_end.php
+++ b/src/application/views/template_end.php
@@ -39,7 +39,7 @@ $(function() {
$("input[type=file]").each(function(i, e) {
var isMultiple = !!$(e).prop("multiple");
- var $input = $('<input type="text" readonly class="form-control" />').attr("placeholder", _messages.filesSelected[0]);
+ var $input = $('<input type="text" readonly class="form-control" />').attr("placeholder", _messages.filesSelected[0]).css("text-overflow", "ellipsis");
$(e).after($('<div class="input-group file-input-group"></div>').append(
$input,
$('<span class="input-group-btn"></span>').append(
diff --git a/src/application/views/template_start.php b/src/application/views/template_start.php
index 56af9bf..51f873a 100644
--- a/src/application/views/template_start.php
+++ b/src/application/views/template_start.php
@@ -16,10 +16,11 @@ $pageTitle .= env("MYSTIC_FORUM_TITLE") ?? "Forum";
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title><?= htmlentities($pageTitle) ?></title>
- <link rel="stylesheet" href="/themes/<?= env("MYSTIC_FORUM_THEME") ?? "default" ?>/theme.css">
+ <link rel="stylesheet" href="?_action=ctheme">
<script src="/ui/jquery-1.12.4.min.js"></script>
<script src="/ui/dist/js/bootstrap.min.js"></script>
<script src="/ui/modernizr-2.6.2.min.js"></script>
+ <script src="?_action=ji18n"></script>
<!--[if lt IE 9]>
<script src="/ui/html5shiv.min.js"></script>
<script src="/ui/respond.min.js"></script>
diff --git a/src/application/views/view_post.php b/src/application/views/view_post.php
index 510b22c..fe885bc 100644
--- a/src/application/views/view_post.php
+++ b/src/application/views/view_post.php
@@ -6,8 +6,10 @@ use mystic\forum\orm\Attachment;
/** @var mystic\forum\orm\Post $post */
/** @var mystic\forum\orm\User $postAuthor */
-$fileAttachments = array_filter($attachments, fn(Attachment $a) => !str_starts_with($a->mimeType, "image/"));
-$imageAttachments = array_filter($attachments, fn(Attachment $a) => str_starts_with($a->mimeType, "image/"));
+$isImage = fn(string $m) => str_starts_with($m, "image/") || str_starts_with($m, "video/");
+
+$fileAttachments = array_filter($attachments, fn(Attachment $a) => !$isImage($a->mimeType));
+$imageAttachments = array_filter($attachments, fn(Attachment $a) => $isImage($a->mimeType));
$canReply = $GLOBALS["currentUser"]?->hasPermission(UserPermissions::CREATE_OWN_POST) ?? false;
@@ -17,9 +19,12 @@ $canEdit = ($GLOBALS["currentUser"]?->id === $postAuthor?->id && $postAuthor?->h
$canDelete = ($GLOBALS["currentUser"]?->id === $postAuthor?->id && $postAuthor?->hasPermission(UserPermissions::DELETE_OWN_POST))
|| ($GLOBALS["currentUser"]?->hasPermission(UserPermissions::DELETE_OTHER_POST));
+$canViewAttachments = $GLOBALS["currentUser"] !== null;
+
$hide_actions ??= false;
$hide_pfp ??= false;
$your_are_the_author = $GLOBALS["currentUser"]?->id === $postAuthor?->id;
+$is_op = $postAuthor?->id === $topicAuthor?->id && $postAuthor?->id !== null;
?>
@@ -78,6 +83,9 @@ $your_are_the_author = $GLOBALS["currentUser"]?->id === $postAuthor?->id;
<?= htmlentities($postAuthor->displayName) ?>
<?php else: ?>
<a href="?_action=viewuser&amp;user=<?= htmlentities(urlencode($postAuthor->id)) ?>"><?= htmlentities($postAuthor->displayName) ?></a>
+ <?php if ($is_op): ?>
+ <span title="<?= __("Created this topic") ?>" class="text-info glyphicon glyphicon-comment"></span>
+ <?php endif; ?>
<?php endif; ?>
<?php if ($your_are_the_author): ?>
<span class="text-normal label label-primary"><?= __("You") ?></span>
@@ -101,8 +109,13 @@ $your_are_the_author = $GLOBALS["currentUser"]?->id === $postAuthor?->id;
<img class="image-attachment-image" src="?_action=thumb&amp;attachment=<?= htmlentities(urlencode($attachment->id)) ?>" alt="" width="100">
</span>
<?php else: ?>
- <a class="image-attachment attachment" href="?_action=attachment&amp;attachment=<?= htmlentities(urlencode($attachment->id)) ?>" title="<?= htmlentities($attachment->name) ?>">
+ <a class="image-attachment attachment<?php if (str_starts_with($attachment->mimeType, "video/")): ?> video-attachment<?php endif; ?>" href="?_action=attachment&amp;attachment=<?= htmlentities(urlencode($attachment->id)) ?>" title="<?= htmlentities($attachment->name) ?>" data-attachment-id="<?= htmlentities($attachment->id) ?>">
<img class="image-attachment-image" src="?_action=thumb&amp;attachment=<?= htmlentities(urlencode($attachment->id)) ?>" alt="" width="100">
+ <?php if (!$canViewAttachments): ?>
+ <span class="attachment-lock glyphicon glyphicon-ban-circle" aria-hidden="true"></span>
+ <?php elseif (str_starts_with($attachment->mimeType, "video/")): ?>
+ <span class="video-player-icon glyphicon glyphicon-play" aria-hidden="true"></span>
+ <?php endif; ?>
</a>
<?php endif; ?>
<?php endforeach; ?>
@@ -116,7 +129,12 @@ $your_are_the_author = $GLOBALS["currentUser"]?->id === $postAuthor?->id;
<?php if ($hide_actions): ?>
<button class="btn btn-default"><?= htmlentities($attachment->name) ?></button>
<?php else: ?>
- <a class="btn btn-default attachment" href="?_action=attachment&amp;attachment=<?= htmlentities(urlencode($attachment->id)) ?>"><?= htmlentities($attachment->name) ?></a>
+ <a class="btn btn-default attachment" href="?_action=attachment&amp;attachment=<?= htmlentities(urlencode($attachment->id)) ?>">
+ <?php if (!$canViewAttachments): ?>
+ <span class="glyphicon glyphicon-ban-circle" aria-hidden="true"></span>
+ <?php endif; ?>
+ <?= htmlentities($attachment->name) ?>
+ </a>
<?php endif; ?>
<?php endforeach; ?>
</div>
diff --git a/src/application/views/view_topic_start.php b/src/application/views/view_topic_start.php
index 35befc7..da8c0cd 100644
--- a/src/application/views/view_topic_start.php
+++ b/src/application/views/view_topic_start.php
@@ -55,6 +55,60 @@ $canDelete = ($GLOBALS["currentUser"]?->id === $topicAuthor->id && $topicAuthor-
});
});
</script>
+<?php else: ?>
+ <div class="modal fade" tabindex="-1" role="dialog" id="diag-image-attachment">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title"><?= __("Attachment") ?></h4>
+ </div>
+ <div class="modal-body">
+ <img class="image-attachment-view attachment-view" id="image-attachment-view" alt="">
+ </div>
+ <div class="modal-footer">
+ <a href="" download id="image-attachment-dl-btn" class="btn btn-default"><span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span> <?= __("Download") ?></a>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div class="modal fade" tabindex="-1" role="dialog" id="diag-video-attachment">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title"><?= __("Attachment") ?></h4>
+ </div>
+ <div class="modal-body">
+ <video class="video-attachment-view attachment-view" id="video-attachment-view" controls></video>
+ </div>
+ <div class="modal-footer">
+ <a href="" download id="video-attachment-dl-btn" class="btn btn-default"><span class="glyphicon glyphicon-download-alt" aria-hidden="true"></span> <?= __("Download") ?></a>
+ </div>
+ </div>
+ </div>
+ </div>
+ <script>
+ $(function() {
+ $(".image-attachment:not(.video-attachment)").click(function(e) {
+ e.preventDefault();
+ var attUrl = "?_action=attachment&attachment=" + encodeURIComponent($(this).attr("data-attachment-id"));
+ $("#image-attachment-view").attr("src", attUrl);
+ $("#image-attachment-dl-btn").attr("href", attUrl);
+ $("#diag-image-attachment").modal();
+ });
+ $(".image-attachment.video-attachment").click(function(e) {
+ e.preventDefault();
+ var attUrl = "?_action=attachment&attachment=" + encodeURIComponent($(this).attr("data-attachment-id"));
+ $("#video-attachment-view").attr("src", attUrl);
+ $("#video-attachment-dl-btn").attr("href", attUrl);
+ $("#diag-video-attachment").modal();
+ });
+ $("#diag-video-attachment").on("hide.bs.modal", function() {
+ $("#video-attachment-view")[0].pause();
+ });
+ });
+ </script>
<?php endif; ?>
<div class="page-header margin-top-0 clearfix">
diff --git a/src/application/views/view_user.php b/src/application/views/view_user.php
index 536cc33..6631407 100644
--- a/src/application/views/view_user.php
+++ b/src/application/views/view_user.php
@@ -46,8 +46,14 @@ $dateJoined->setTime(0, 0, 0, 0);
<div class="post-container">
<div class="post-container-posts">
<div class="list-group margin-top">
- <?php foreach ($posts as $post): if ($post->deleted) continue; ?>
+ <?php foreach ($posts as $post):
+ if ($post->deleted) continue;
+ $hasAttachments = count($attachments[$post->id]) > 0;
+ ?>
<a href="?_action=viewtopic&amp;topic=<?= htmlentities(urlencode($post->topicId)) ?>#post-<?= htmlentities(urlencode($post->id)) ?>" class="list-group-item">
+ <?php if ($hasAttachments): ?>
+ <span class="badge"><span class="glyphicon glyphicon-paperclip"></span></span>
+ <?php endif; ?>
<?= htmlentities(StringUtils::truncate(strip_tags(renderPost($post->content)), 100)) ?><br>
<span class="text-muted"><?= __("posted on %post_date% in %topic%", [
"post_date" => '<span class="_time">' . htmlentities($post->postDate->format("c")) . '</span>',