[update] remove extension - unzipping new code over the top of old code is fundamentally unsafe
This commit is contained in:
parent
cc9de6b4b2
commit
79087c51a5
5 changed files with 88 additions and 285 deletions
|
@ -294,25 +294,21 @@ class Pools extends Extension
|
|||
if ($event->page_matches("pool/edit")) {
|
||||
$pool_id = int_escape($event->req_POST("pool_id"));
|
||||
$pool = $this->get_single_pool($pool_id);
|
||||
$this->assert_permission($user, $pool);
|
||||
|
||||
if ($this->have_permission($user, $pool)) {
|
||||
$result = $database->execute("SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order ASC", ["pid" => $pool_id]);
|
||||
$images = [];
|
||||
while ($row = $result->fetch()) {
|
||||
$images[] = Image::by_id((int) $row["image_id"]);
|
||||
}
|
||||
$this->theme->edit_pool($page, $pool, $images);
|
||||
} else {
|
||||
$page->set_mode(PageMode::REDIRECT);
|
||||
$page->set_redirect(make_link("pool/view/" . $pool_id));
|
||||
}
|
||||
}
|
||||
if ($event->page_matches("pool/order")) {
|
||||
$pool_id = int_escape($event->req_POST("pool_id"));
|
||||
$pool = $this->get_single_pool($pool_id);
|
||||
$this->assert_permission($user, $pool);
|
||||
|
||||
if ($event->get_POST("order_view")) {
|
||||
if ($this->have_permission($user, $pool)) {
|
||||
$result = $database->execute(
|
||||
"SELECT image_id FROM pool_images WHERE pool_id=:pid ORDER BY image_order ASC",
|
||||
["pid" => $pool_id]
|
||||
|
@ -332,11 +328,6 @@ class Pools extends Extension
|
|||
|
||||
$this->theme->edit_order($page, $pool, $images);
|
||||
} else {
|
||||
$page->set_mode(PageMode::REDIRECT);
|
||||
$page->set_redirect(make_link("pool/view/" . $pool_id));
|
||||
}
|
||||
} else {
|
||||
if ($this->have_permission($user, $pool)) {
|
||||
foreach ($event->POST as $key => $value) {
|
||||
if (str_starts_with($key, "order_")) {
|
||||
$imageID = (int) substr($key, 6);
|
||||
|
@ -351,16 +342,13 @@ class Pools extends Extension
|
|||
}
|
||||
$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");
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($event->page_matches("pool/reverse")) {
|
||||
$pool_id = int_escape($event->req_POST("pool_id"));
|
||||
$pool = $this->get_single_pool($pool_id);
|
||||
$this->assert_permission($user, $pool);
|
||||
|
||||
if ($this->have_permission($user, $pool)) {
|
||||
$database->with_savepoint(function () use ($pool_id) {
|
||||
global $database;
|
||||
$result = $database->execute(
|
||||
|
@ -381,42 +369,33 @@ class Pools extends Extension
|
|||
});
|
||||
$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");
|
||||
}
|
||||
}
|
||||
if ($event->page_matches("pool/import")) {
|
||||
$pool_id = int_escape($event->req_POST("pool_id"));
|
||||
$pool = $this->get_single_pool($pool_id);
|
||||
$this->assert_permission($user, $pool);
|
||||
|
||||
if ($this->have_permission($user, $pool)) {
|
||||
$images = Search::find_images(
|
||||
limit: $config->get_int(PoolsConfig::MAX_IMPORT_RESULTS, 1000),
|
||||
tags: Tag::explode($event->req_POST("pool_tag"))
|
||||
);
|
||||
$this->theme->pool_result($page, $images, $pool);
|
||||
} else {
|
||||
$this->theme->display_error(403, "Permission Denied", "You do not have permission to access this page");
|
||||
}
|
||||
}
|
||||
if ($event->page_matches("pool/add_posts")) {
|
||||
$pool_id = int_escape($event->req_POST("pool_id"));
|
||||
$pool = $this->get_single_pool($pool_id);
|
||||
$this->assert_permission($user, $pool);
|
||||
|
||||
if ($this->have_permission($user, $pool)) {
|
||||
$image_ids = array_map('intval', $event->req_POST_array('check'));
|
||||
send_event(new PoolAddPostsEvent($pool_id, $image_ids));
|
||||
$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");
|
||||
}
|
||||
}
|
||||
if ($event->page_matches("pool/remove_posts")) {
|
||||
$pool_id = int_escape($event->req_POST("pool_id"));
|
||||
$pool = $this->get_single_pool($pool_id);
|
||||
$this->assert_permission($user, $pool);
|
||||
|
||||
if ($this->have_permission($user, $pool)) {
|
||||
$images = "";
|
||||
foreach ($event->req_POST_array('check') as $imageID) {
|
||||
$database->execute(
|
||||
|
@ -432,24 +411,18 @@ class Pools extends Extension
|
|||
$this->add_history($pool_id, 0, $images, $count);
|
||||
$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");
|
||||
}
|
||||
}
|
||||
if ($event->page_matches("pool/edit_description")) {
|
||||
$pool_id = int_escape($event->req_POST("pool_id"));
|
||||
$pool = $this->get_single_pool($pool_id);
|
||||
$this->assert_permission($user, $pool);
|
||||
|
||||
if ($this->have_permission($user, $pool)) {
|
||||
$database->execute(
|
||||
"UPDATE pools SET description=:dsc,lastupdated=CURRENT_TIMESTAMP WHERE id=:pid",
|
||||
["dsc" => $event->req_POST('description'), "pid" => $pool_id]
|
||||
);
|
||||
$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");
|
||||
}
|
||||
}
|
||||
if ($event->page_matches("pool/nuke")) {
|
||||
// Completely remove the given pool.
|
||||
|
@ -462,7 +435,7 @@ class Pools extends Extension
|
|||
$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");
|
||||
throw new PermissionDeniedException("You do not have permission to access this page");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -646,6 +619,13 @@ class Pools extends Extension
|
|||
);
|
||||
}
|
||||
|
||||
private function assert_permission(User $user, Pool $pool): void
|
||||
{
|
||||
if (!$this->have_permission($user, $pool)) {
|
||||
throw new PermissionDeniedException("You do not have permission to access this pool");
|
||||
}
|
||||
}
|
||||
|
||||
private function list_pools(Page $page, int $pageNumber, ?string $search): void
|
||||
{
|
||||
global $config, $database;
|
||||
|
@ -758,9 +738,7 @@ class Pools extends Extension
|
|||
global $database, $user;
|
||||
|
||||
$pool = $this->get_single_pool($event->pool_id);
|
||||
if (!$this->have_permission($user, $pool)) {
|
||||
return;
|
||||
}
|
||||
$this->assert_permission($user, $pool);
|
||||
|
||||
$images = [];
|
||||
foreach ($event->posts as $post_id) {
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shimmie2;
|
||||
|
||||
class UpdateInfo extends ExtensionInfo
|
||||
{
|
||||
public const KEY = "update";
|
||||
|
||||
public string $key = self::KEY;
|
||||
public string $name = "Update";
|
||||
public string $url = "http://www.codeanimu.net";
|
||||
public array $authors = ["DakuTree" => "dakutree@codeanimu.net"];
|
||||
public string $license = self::LICENSE_GPLV2;
|
||||
public string $description = "Shimmie updater!";
|
||||
public array $dependencies = [AdminPageInfo::KEY];
|
||||
public ExtensionCategory $category = ExtensionCategory::ADMIN;
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shimmie2;
|
||||
|
||||
class Update extends Extension
|
||||
{
|
||||
/** @var UpdateTheme */
|
||||
protected Themelet $theme;
|
||||
|
||||
public function onInitExt(InitExtEvent $event): void
|
||||
{
|
||||
global $config;
|
||||
$config->set_default_string("update_guserrepo", "shish/shimmie2");
|
||||
$config->set_default_string("commit_hash", "unknown");
|
||||
$config->set_default_string("update_time", "01/01/1970");
|
||||
}
|
||||
|
||||
public function onSetupBuilding(SetupBuildingEvent $event): void
|
||||
{
|
||||
$sb = $event->panel->create_new_block("Update");
|
||||
$sb->add_text_option("update_guserrepo", "User/Repo: ");
|
||||
}
|
||||
|
||||
public function onAdminBuilding(AdminBuildingEvent $event): void
|
||||
{
|
||||
global $config;
|
||||
if ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) !== "none") {
|
||||
$this->theme->display_admin_block();
|
||||
}
|
||||
}
|
||||
|
||||
public function onPageRequest(PageRequestEvent $event): void
|
||||
{
|
||||
global $user, $page;
|
||||
$sha = $event->get_GET('sha');
|
||||
|
||||
// FIXME: use POST
|
||||
if ($event->page_matches("update/download", permission: Permissions::EDIT_FILES)) {
|
||||
assert(!is_null($sha));
|
||||
$ok = $this->download_shimmie($sha);
|
||||
|
||||
$page->set_mode(PageMode::REDIRECT);
|
||||
if ($ok) {
|
||||
$page->set_redirect(make_link("update/update", "sha=".$sha));
|
||||
} else {
|
||||
$page->set_redirect(make_link("admin"));
|
||||
} //TODO: Show error?
|
||||
}
|
||||
if ($event->page_matches("update/update", permission: Permissions::EDIT_FILES)) {
|
||||
assert(!is_null($sha));
|
||||
$ok = $this->update_shimmie($sha);
|
||||
|
||||
$page->set_mode(PageMode::REDIRECT);
|
||||
if ($ok) {
|
||||
$page->set_redirect(make_link("admin"));
|
||||
} //TODO: Show success?
|
||||
else {
|
||||
$page->set_redirect(make_link("admin"));
|
||||
} //TODO: Show error?
|
||||
}
|
||||
}
|
||||
|
||||
private function download_shimmie(string $commitSHA): bool
|
||||
{
|
||||
global $config;
|
||||
|
||||
$g_userrepo = $config->get_string('update_guserrepo');
|
||||
|
||||
$url = "https://codeload.github.com/".$g_userrepo."/zip/".$commitSHA;
|
||||
$filename = "./data/update_{$commitSHA}.zip";
|
||||
|
||||
log_info("update", "Attempting to download Shimmie commit: ".$commitSHA);
|
||||
$headers = fetch_url($url, $filename);
|
||||
if (($headers['Content-Type'] !== MimeType::ZIP) || ((int) $headers['Content-Length'] !== filesize($filename))) {
|
||||
unlink("./data/update_{$commitSHA}.zip");
|
||||
log_warning("update", "Download failed: not zip / not same size as remote file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private function update_shimmie(string $commitSHA): bool
|
||||
{
|
||||
global $config;
|
||||
|
||||
log_info("update", "Download succeeded. Attempting to update Shimmie.");
|
||||
$ok = false;
|
||||
|
||||
/** TODO: Backup all folders (except /data, /images, /thumbs) before attempting this?
|
||||
Either that or point to https://github.com/shish/shimmie2/blob/master/README.txt -> Upgrade from 2.3.X **/
|
||||
|
||||
$zip = new \ZipArchive();
|
||||
if ($zip->open("./data/update_$commitSHA.zip") === true) {
|
||||
for ($i = 1; $i < $zip->numFiles; $i++) {
|
||||
$filename = false_throws($zip->getNameIndex($i));
|
||||
|
||||
if (substr($filename, -1) !== "/") {
|
||||
copy("zip://".dirname(dirname(__DIR__)).'/'."./data/update_$commitSHA.zip"."#".$filename, substr($filename, 50));
|
||||
}
|
||||
}
|
||||
$ok = true; //TODO: Do proper checking to see if everything copied properly
|
||||
} else {
|
||||
log_warning("update", "Update failed to open ZIP.");
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
unlink("./data/update_$commitSHA.zip");
|
||||
|
||||
if ($ok) {
|
||||
$config->set_string("commit_hash", $commitSHA);
|
||||
$config->set_string("update_time", date('d-m-Y'));
|
||||
log_info("update", "Update succeeded?");
|
||||
}
|
||||
|
||||
return $ok;
|
||||
}
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
/*jshint bitwise:true, curly:true, forin:false, noarg:true, noempty:true, nonew:true, undef:true, strict:false, browser:true, jquery:true */
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
if($('#updatecheck').length !== 0){
|
||||
$.getJSON('https://api.github.com/repos/shish/shimmie2/commits', function(data){
|
||||
var c = data[0];
|
||||
$('#updatecheck').html('<a href="'+ c.html_url+'">'+ c.sha+'</a>' + " ("+ c.commit.message+")");
|
||||
|
||||
var params = $.param({sha: c.sha, date: c.commit.committer.date});
|
||||
$('#updatelink').attr('href', function(i, val){ return val + "?" + params; });
|
||||
$('#updatelink').text("Update");
|
||||
}).fail(function(){
|
||||
$('#updatecheck').text("Loading failed. (Github down?)");
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1,20 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Shimmie2;
|
||||
|
||||
class UpdateTheme extends Themelet
|
||||
{
|
||||
public function display_admin_block(): void
|
||||
{
|
||||
global $page, $config;
|
||||
|
||||
$html = "".
|
||||
"<b>Current Commit</b>: ".$config->get_string('commit_hash')." | (".$config->get_string('update_time').")".
|
||||
"<br><b>Latest Commit</b>: <span id='updatecheck'>Loading...</span>".
|
||||
"<br><a href='" . make_link('update/download') . "' id='updatelink'></a>";
|
||||
//TODO: Show warning before use.
|
||||
$page->add_block(new Block("Software Update", $html, "main", 75));
|
||||
}
|
||||
}
|
Reference in a new issue