Added ability to upload multiple files through a single upload input

This commit is contained in:
Matthew Barbour 2020-06-16 18:29:59 -05:00 committed by Shish
parent 7f68ef1cfd
commit 688fb8b04b
5 changed files with 87 additions and 64 deletions

View file

@ -263,7 +263,7 @@ function transload(string $url, string $mfile): ?array
{
global $config;
if ($config->get_string("transload_engine") === "curl" && function_exists("curl_init")) {
if ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) === "curl" && function_exists("curl_init")) {
$ch = curl_init($url);
$fp = fopen($mfile, "w");
@ -291,7 +291,7 @@ function transload(string $url, string $mfile): ?array
return $headers;
}
if ($config->get_string("transload_engine") === "wget") {
if ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) === "wget") {
$s_url = escapeshellarg($url);
$s_mfile = escapeshellarg($mfile);
system("wget --no-check-certificate $s_url --output-document=$s_mfile");
@ -299,14 +299,14 @@ function transload(string $url, string $mfile): ?array
return file_exists($mfile) ? ["ok"=>"true"] : null;
}
if ($config->get_string("transload_engine") === "fopen") {
if ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) === "fopen") {
$fp_in = @fopen($url, "r");
$fp_out = fopen($mfile, "w");
if (!$fp_in || !$fp_out) {
return null;
}
$length = 0;
while (!feof($fp_in) && $length <= $config->get_int('upload_size')) {
while (!feof($fp_in) && $length <= $config->get_int(UploadConfig::SIZE)) {
$data = fread($fp_in, 8192);
$length += strlen($data);
fwrite($fp_out, $data);

View file

@ -23,7 +23,7 @@ class Update extends Extension
public function onAdminBuilding(AdminBuildingEvent $event)
{
global $config;
if ($config->get_string('transload_engine') !== "none") {
if ($config->get_string(UploadConfig::TRANSLOAD_ENGINE) !== "none") {
$this->theme->display_admin_block();
}
}

10
ext/upload/config.php Normal file
View file

@ -0,0 +1,10 @@
<?php
class UploadConfig
{
public const COUNT = "upload_count";
public const SIZE = "upload_size";
public const MIN_FREE_SPACE = "upload_min_free_space";
public const TLSOURCE = "upload_tlsource";
public const TRANSLOAD_ENGINE = "transload_engine";
}

View file

@ -1,5 +1,7 @@
<?php declare(strict_types=1);
require_once "config.php";
/**
* Occurs when some data is being uploaded.
*/
@ -101,14 +103,14 @@ class Upload extends Extension
public function onInitExt(InitExtEvent $event)
{
global $config;
$config->set_default_int('upload_count', 3);
$config->set_default_int('upload_size', parse_shorthand_int('1MB'));
$config->set_default_int('upload_min_free_space', parse_shorthand_int('100MB'));
$config->set_default_bool('upload_tlsource', true);
$config->set_default_int(UploadConfig::COUNT, 3);
$config->set_default_int(UploadConfig::SIZE, parse_shorthand_int('1MB'));
$config->set_default_int(UploadConfig::MIN_FREE_SPACE, parse_shorthand_int('100MB'));
$config->set_default_bool(UploadConfig::TLSOURCE, true);
$this->is_full = false;
$min_free_space = $config->get_int("upload_min_free_space");
$min_free_space = $config->get_int(UploadConfig::MIN_FREE_SPACE);
if ($min_free_space > 0) {
// SHIT: fucking PHP "security" measures -_-;;;
$img_path = realpath("./images/");
@ -134,12 +136,12 @@ class Upload extends Extension
$sb = new SetupBlock("Upload");
$sb->position = 10;
// Output the limits from PHP so the user has an idea of what they can set.
$sb->add_int_option("upload_count", "Max uploads: ");
$sb->add_int_option(UploadConfig::COUNT, "Max uploads: ");
$sb->add_label("<i>PHP Limit = " . ini_get('max_file_uploads') . "</i>");
$sb->add_shorthand_int_option("upload_size", "<br/>Max size per file: ");
$sb->add_shorthand_int_option(UploadConfig::SIZE, "<br/>Max size per file: ");
$sb->add_label("<i>PHP Limit = " . ini_get('upload_max_filesize') . "</i>");
$sb->add_choice_option("transload_engine", $tes, "<br/>Transload: ");
$sb->add_bool_option("upload_tlsource", "<br/>Use transloaded URL as source if none is provided: ");
$sb->add_choice_option(UploadConfig::TRANSLOAD_ENGINE, $tes, "<br/>Transload: ");
$sb->add_bool_option(UploadConfig::TLSOURCE, "<br/>Use transloaded URL as source if none is provided: ");
$event->panel->add_block($sb);
}
@ -167,9 +169,9 @@ class Upload extends Extension
if ($this->is_full) {
throw new UploadException("Upload failed; disk nearly full");
}
if (filesize($event->tmpname) > $config->get_int('upload_size')) {
if (filesize($event->tmpname) > $config->get_int(UploadConfig::SIZE)) {
$size = to_shorthand_int(filesize($event->tmpname));
$limit = to_shorthand_int($config->get_int('upload_size'));
$limit = to_shorthand_int($config->get_int(UploadConfig::SIZE));
throw new UploadException("File too large ($size > $limit)");
}
}
@ -320,7 +322,7 @@ class Upload extends Extension
*/
private function try_upload(array $file, array $tags, ?string $source = null, ?int $replace_id = null): bool
{
global $page;
global $page, $config;
if (empty($source)) {
$source = null;
@ -330,38 +332,58 @@ class Upload extends Extension
// blank file boxes cause empty uploads, no need for error message
if (!empty($file['name'])) {
$size = sizeof($file['name']);
$limit = $config->get_int(UploadConfig::COUNT);
try {
// check if the upload was successful
if ($file['error'] !== UPLOAD_ERR_OK) {
throw new UploadException($this->upload_error_message($file['error']));
if ($size > $limit) {
throw new UploadException("Upload limited to $limit");
}
$pathinfo = pathinfo($file['name']);
$metadata = [];
$metadata['filename'] = $pathinfo['basename'];
$metadata['extension'] = "";
if (array_key_exists('extension', $pathinfo)) {
$metadata['extension'] = $pathinfo['extension'];
}
$metadata['mime'] = MimeType::get_for_file($file['tmp_name'], $metadata['extension']);
if (empty($metadata['mime'])) {
throw new UploadException("Unable to determine MIME for file ".$metadata['filename']);
}
for ($i = 0; $i < $size;$i++) {
if (empty($file['name'][$i])) {
continue;
}
try {
// check if the upload was successful
if ($file['error'][$i] !== UPLOAD_ERR_OK) {
throw new UploadException($this->upload_error_message($file['error'][$i]));
}
$metadata['tags'] = $tags;
$metadata['source'] = $source;
$pathinfo = pathinfo($file['name'][$i]);
$metadata = [];
$metadata['filename'] = $pathinfo['basename'];
$metadata['extension'] = "";
if (array_key_exists('extension', $pathinfo)) {
$metadata['extension'] = $pathinfo['extension'];
}
$metadata['mime'] = MimeType::get_for_file($file['tmp_name'][$i], $metadata['extension']);
if (empty($metadata['mime'])) {
throw new UploadException("Unable to determine MIME for file " . $metadata['filename']);
}
$event = new DataUploadEvent($file['tmp_name'], $metadata);
$event->replace_id = $replace_id;
send_event($event);
if ($event->image_id == -1) {
throw new UploadException("MIME type not supported: " . $metadata['mime']);
$metadata['tags'] = $tags;
$metadata['source'] = $source;
$event = new DataUploadEvent($file['tmp_name'][$i], $metadata);
$event->replace_id = $replace_id;
send_event($event);
if ($event->image_id == -1) {
throw new UploadException("MIME type not supported: " . $metadata['mime']);
}
$page->add_http_header("X-Shimmie-Image-ID: " . $event->image_id);
} catch (UploadException $ex) {
$this->theme->display_upload_error(
$page,
"Error with " . html_escape($file['name'][$i]),
$ex->getMessage()
);
$ok = false;
}
}
$page->add_http_header("X-Shimmie-Image-ID: " . $event->image_id);
} catch (UploadException $ex) {
$this->theme->display_upload_error(
$page,
"Error with " . html_escape($file['name']),
"Error with upload",
$ex->getMessage()
);
$ok = false;
@ -383,7 +405,7 @@ class Upload extends Extension
}
// Checks if url contains rating, also checks if the rating extension is enabled.
if ($config->get_string("transload_engine", "none") != "none" && Extension::is_enabled(RatingsInfo::KEY) && !empty($_GET['rating'])) {
if ($config->get_string(UploadConfig::TRANSLOAD_ENGINE, "none") != "none" && Extension::is_enabled(RatingsInfo::KEY) && !empty($_GET['rating'])) {
// Rating event will validate that this is s/q/e/u
$rating = strtolower($_GET['rating']);
$rating = $rating[0];
@ -421,7 +443,7 @@ class Upload extends Extension
$metadata = [];
$metadata['filename'] = $filename;
$metadata['tags'] = $tags;
$metadata['source'] = (($url == $source) && !$config->get_bool('upload_tlsource') ? "" : $source);
$metadata['source'] = (($url == $source) && !$config->get_bool(UploadConfig::TLSOURCE) ? "" : $source);
/* check for locked > adds to metadata if it has */
if (!empty($locked)) {

View file

@ -18,8 +18,8 @@ class UploadTheme extends Themelet
{
global $config, $page;
$tl_enabled = ($config->get_string("transload_engine", "none") != "none");
$max_size = $config->get_int('upload_size');
$tl_enabled = ($config->get_string(UploadConfig::TRANSLOAD_ENGINE, "none") != "none");
$max_size = $config->get_int(UploadConfig::SIZE);
$max_kb = to_shorthand_int($max_size);
$upload_list = $this->h_upload_list_1();
$html = "
@ -47,8 +47,8 @@ class UploadTheme extends Themelet
{
global $config;
$upload_list = "";
$upload_count = $config->get_int('upload_count');
$tl_enabled = ($config->get_string("transload_engine", "none") != "none");
$upload_count = $config->get_int(UploadConfig::COUNT);
$tl_enabled = ($config->get_string(UploadConfig::TRANSLOAD_ENGINE, "none") != "none");
$accept = $this->get_accept();
if ($tl_enabled) {
@ -63,7 +63,7 @@ class UploadTheme extends Themelet
for ($i=0; $i<$upload_count; $i++) {
$upload_list .= "
<tr>
<td colspan='2'><input type='file' name='data$i' accept='$accept'></td>
<td colspan='2'><input type='file' name='data${i}[]' accept='$accept' multiple></td>
<td colspan='2'><input type='text' name='url$i'></td>
<td colspan='2'><input type='text' name='tags$i' class='autocomplete_tags' autocomplete='off'></td>
</tr>
@ -80,7 +80,7 @@ class UploadTheme extends Themelet
for ($i=0; $i<$upload_count; $i++) {
$upload_list .= "
<tr>
<td colspan='4'><input type='file' name='data$i' accept='$accept'></td>
<td colspan='4'><input type='file' name='data${i}[]' accept='$accept' multiple></td>
<td colspan='2'><input type='text' name='tags$i' class='autocomplete_tags' autocomplete='off'></td>
</tr>
";
@ -96,7 +96,7 @@ class UploadTheme extends Themelet
$link = make_http(make_link("upload"));
$main_page = make_http(make_link());
$title = $config->get_string(SetupConfig::TITLE);
$max_size = $config->get_int('upload_size');
$max_size = $config->get_int(UploadConfig::SIZE);
$max_kb = to_shorthand_int($max_size);
$delimiter = $config->get_bool('nice_urls') ? '?' : '&amp;';
$html = '';
@ -146,7 +146,7 @@ class UploadTheme extends Themelet
public function display_replace_page(Page $page, int $image_id)
{
global $config, $page;
$tl_enabled = ($config->get_string("transload_engine", "none") != "none");
$tl_enabled = ($config->get_string(UploadConfig::TRANSLOAD_ENGINE, "none") != "none");
$accept = $this->get_accept();
$upload_list = "
@ -164,7 +164,7 @@ class UploadTheme extends Themelet
";
}
$max_size = $config->get_int('upload_size');
$max_size = $config->get_int(UploadConfig::SIZE);
$max_kb = to_shorthand_int($max_size);
$image = Image::by_id($image_id);
@ -213,26 +213,17 @@ class UploadTheme extends Themelet
{
global $config;
$upload_list = "";
$upload_count = $config->get_int('upload_count');
$upload_count = $config->get_int(UploadConfig::COUNT);
$accept = $this->get_accept();
for ($i=0; $i<$upload_count; $i++) {
if ($i == 0) {
$style = "";
} // "style='display:visible'";
else {
$style = "style='display:none'";
}
$upload_list .= "<input id='data$i' name='data$i' $style onchange=\"$('#data".($i+1)."').show()\" size='16' type='file' accept='$accept'>\n";
}
$max_size = $config->get_int('upload_size');
$max_size = $config->get_int(UploadConfig::SIZE);
$max_kb = to_shorthand_int($max_size);
// <input type='hidden' name='max_file_size' value='$max_size' />
return "
<div class='mini_upload'>
".make_form(make_link("upload"), "POST", $multipart=true)."
$upload_list
<input id='data[]' name='data[]' size='16' type='file' accept='$accept' multiple>
<input name='tags' type='text' placeholder='tagme' class='autocomplete_tags' required='required' autocomplete='off'>
<input type='submit' value='Post'>
</form>