337 lines
9.3 KiB
PHP
337 lines
9.3 KiB
PHP
<?php // phpcs:ignore PSR1.Files.SideEffects
|
|
|
|
header("Content-Type: application/json; charset=UTF-8");
|
|
session_start();
|
|
define('DS', DIRECTORY_SEPARATOR);
|
|
define('DIR', __DIR__ . DS);
|
|
define('LOG', 'log' . DS);
|
|
// run id
|
|
DEFINE('RUNUID', session_id());
|
|
|
|
function logWrite(string $message): void
|
|
{
|
|
global $fh;
|
|
if (!$fh) {
|
|
$fh = fopen(DIR . LOG . 'backend.' . date("Y-m-d") . '.log', 'a');
|
|
}
|
|
fwrite($fh, '{' . RUNUID . '} [' . printTime() . '] ' . $message . "\n");
|
|
}
|
|
|
|
function logHandleClose(): void
|
|
{
|
|
global $fh;
|
|
if ($fh) {
|
|
fclose($fh);
|
|
}
|
|
}
|
|
|
|
function printTime(): string
|
|
{
|
|
$set_microtime = 4;
|
|
list($microtime, $timestamp) = explode(' ', microtime());
|
|
$string = date("Y-m-d H:i:s", $timestamp);
|
|
// if microtime flag is -1 no round, if 0, no microtime, if >= 1, round that size
|
|
$string .= substr(number_format(round($microtime, $set_microtime), $set_microtime), 1);
|
|
return $string;
|
|
}
|
|
|
|
function errMsg(string $level, string $message): void
|
|
{
|
|
global $error_string;
|
|
|
|
$error_string[] = [
|
|
'level' => $level,
|
|
'str' => $message
|
|
];
|
|
}
|
|
|
|
/**
|
|
* [printAr description]
|
|
* @param array $array [description]
|
|
* @return string [description]
|
|
*/
|
|
function printAr(array $array): string
|
|
{
|
|
return "<pre>" . print_r($array, true) . "</pre>";
|
|
}
|
|
|
|
/**
|
|
* helper function for PHP file upload error messgaes to messge string
|
|
* @param int $error_code integer _FILE upload error code
|
|
* @return string message string, translated
|
|
*/
|
|
function fileUploadErrorMessage(int $error_code): string
|
|
{
|
|
switch ($error_code) {
|
|
case UPLOAD_ERR_INI_SIZE:
|
|
$message = 'The uploaded file exceeds the upload_max_filesize directive in php.ini';
|
|
break;
|
|
case UPLOAD_ERR_FORM_SIZE:
|
|
$message = 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form';
|
|
break;
|
|
case UPLOAD_ERR_PARTIAL:
|
|
$message = 'The uploaded file was only partially uploaded';
|
|
break;
|
|
case UPLOAD_ERR_NO_FILE:
|
|
$message = 'No file was uploaded';
|
|
break;
|
|
case UPLOAD_ERR_NO_TMP_DIR:
|
|
$message = 'Missing a temporary folder';
|
|
break;
|
|
case UPLOAD_ERR_CANT_WRITE:
|
|
$message = 'Failed to write file to disk';
|
|
break;
|
|
case UPLOAD_ERR_EXTENSION:
|
|
$message = 'File upload stopped by extension';
|
|
break;
|
|
default:
|
|
$message = 'Unknown upload error';
|
|
break;
|
|
}
|
|
return $message;
|
|
}
|
|
|
|
/**
|
|
* creates psuedo random uuid v4
|
|
* Code take from class here:
|
|
* https://www.php.net/manual/en/function.uniqid.php#94959
|
|
* @return string pseudo random uuid v4
|
|
*/
|
|
function uuidv4(): string
|
|
{
|
|
return sprintf(
|
|
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
|
|
// 32 bits for "time_low"
|
|
mt_rand(0, 0xffff),
|
|
mt_rand(0, 0xffff),
|
|
// 16 bits for "time_mid"
|
|
mt_rand(0, 0xffff),
|
|
// 16 bits for "time_hi_and_version",
|
|
// four most significant bits holds version number 4
|
|
mt_rand(0, 0x0fff) | 0x4000,
|
|
// 16 bits, 8 bits for "clk_seq_hi_res",
|
|
// 8 bits for "clk_seq_low",
|
|
// two most significant bits holds zero and one for variant DCE1.1
|
|
mt_rand(0, 0x3fff) | 0x8000,
|
|
// 48 bits for "node"
|
|
mt_rand(0, 0xffff),
|
|
mt_rand(0, 0xffff),
|
|
mt_rand(0, 0xffff)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param string|int|float $bytes bytes as string int or pure int
|
|
* @return string converted byte number (float) with suffix
|
|
*/
|
|
function humanReadableByteFormat($bytes): string
|
|
{
|
|
// if not numeric, return as is
|
|
if (is_numeric($bytes)) {
|
|
// space before name
|
|
$space = true;
|
|
// use sprintf instead of round
|
|
$adjust = true;
|
|
// use SI 1000 mod and not 1024 mod
|
|
$si = false;
|
|
|
|
// si or normal
|
|
$unit = $si ? 1000 : 1024;
|
|
// always positive
|
|
$abs_bytes = $bytes == PHP_INT_MIN ? PHP_INT_MAX : abs($bytes);
|
|
// smaller than unit is always B
|
|
if ($abs_bytes < $unit) {
|
|
return $bytes . 'B';
|
|
}
|
|
// labels in order of size [Y, Z]
|
|
$labels = array('', 'K', 'M', 'G', 'T', 'P', 'E');
|
|
// exp position calculation
|
|
$exp = floor(log($abs_bytes, $unit));
|
|
// avoid printing out anything larger than max labels
|
|
if ($exp >= count($labels)) {
|
|
$exp = count($labels) - 1;
|
|
}
|
|
// deviation calculation
|
|
$dev = pow($unit, $exp) * ($unit - 0.05);
|
|
// shift the exp +1 for on the border units
|
|
if (
|
|
$exp < 6 &&
|
|
$abs_bytes > ($dev - (((int)$dev & 0xfff) == 0xd00 ? 52 : 0))
|
|
) {
|
|
$exp++;
|
|
}
|
|
// label name, including leading space if flagged
|
|
$pre = ($space ? ' ' : '') . ($labels[$exp] ?? '>E') . ($si ? 'i' : '') . 'B';
|
|
$bytes_calc = $abs_bytes / pow($unit, $exp);
|
|
if ($adjust) {
|
|
return sprintf("%.2f%s", $bytes_calc, $pre);
|
|
} else {
|
|
return round($bytes_calc, 2) . $pre;
|
|
}
|
|
} else {
|
|
// if anything other return as string
|
|
return (string)$bytes;
|
|
}
|
|
}
|
|
|
|
$error = false;
|
|
$status = 'error';
|
|
$error_string = [];
|
|
$ajax_data = [];
|
|
$folder = DIR . 'uploaded' . DS;
|
|
|
|
logWrite(print_r($_POST, true));
|
|
|
|
// backend receiver calls
|
|
if (isset($_POST['action'])) {
|
|
// action switch statement
|
|
switch ($_POST['action']) {
|
|
case 'chainAction':
|
|
$ajax_data['chain'] = 'Just A chain action: ' . ($_POST['chain'] ?? '-');
|
|
$status = 'ok';
|
|
errMsg($status, 'Successful chained action');
|
|
break;
|
|
// list current files
|
|
case 'fileList':
|
|
$ajax_data['reference_id'] = uniqid();
|
|
if (is_dir($folder)) {
|
|
$file_array = [];
|
|
// sorted by date
|
|
$files = glob($folder . DIRECTORY_SEPARATOR . '*');
|
|
// oldest top
|
|
usort($files, function ($x, $y) {
|
|
return filemtime($x) > filemtime($y) ? 1 : -1;
|
|
});
|
|
foreach ($files as $file) {
|
|
$file_array[] = [
|
|
'name' => basename($file),
|
|
'create_date' => date("Y-m-d H:i:s", filemtime($file)),
|
|
'size' => humanReadableByteFormat((int)filesize($file))
|
|
];
|
|
}
|
|
$ajax_data['file_list'] = $file_array;
|
|
$status = 'ok';
|
|
if (!count($file_array)) {
|
|
$status = 'warn';
|
|
$ajax_data['info'] = 'No files uploaded yet';
|
|
}
|
|
} else {
|
|
$error = true;
|
|
errMsg($status, 'Uploaded folder not found');
|
|
}
|
|
break;
|
|
// for simple single file upload
|
|
case 'fileUpload':
|
|
// has a target name (file prefix flag)
|
|
$upload_name = $_POST['uploadName'];
|
|
// $this->debug('FILE UPLOAD', 'ALL FILES: '.$this->printAr($_FILES));
|
|
// errMsg('debug', 'Called for: ' . $upload_name . ' with data: '
|
|
// . (isset($_FILES[$upload_name]) ? printAr($_FILES[$upload_name]) : 'NOT FOUND'));
|
|
// return string & array init
|
|
$file_upload_message = [];
|
|
// do we have an upload actually
|
|
if (
|
|
isset($_FILES[$upload_name]['error']) &&
|
|
$_FILES[$upload_name]['error'] == UPLOAD_ERR_OK
|
|
) {
|
|
// set status to success post all checks
|
|
$status = 'success';
|
|
// strip out -file from upload name for search
|
|
$_upload_name = str_replace('-file', '', $upload_name);
|
|
$mime_type = null;
|
|
|
|
$ajax_data = [
|
|
'msg' => [],
|
|
'file_uid' => null,
|
|
'file_url' => null,
|
|
'file_name' => null,
|
|
'file_size' => null,
|
|
'file_size_raw' => null,
|
|
'file_type' => null,
|
|
];
|
|
// check mime type for file and do check if we have a "valid_files" settings
|
|
$finfo = new \finfo(FILEINFO_MIME_TYPE);
|
|
$mime_type = $finfo->file($_FILES[$upload_name]['tmp_name']);
|
|
if (!in_array($mime_type, ['text/csv', 'text/plain', 'text/x-php'])) {
|
|
$file_upload_message[] = 'File type must be CSV or PHP: ' . $mime_type;
|
|
$ajax_data['msg'] = $file_upload_message;
|
|
$ajax_data['error'] = 'File type must be CSV or PHP: ' . $mime_type;
|
|
$status = 'error';
|
|
}
|
|
// ON ERROR set status = 'error';
|
|
// file type ok and file size ok, we commence actualy upload
|
|
if ($status == 'success') {
|
|
// basic file id data
|
|
$file_uid = null;
|
|
$file_url = null;
|
|
$file_name = null;
|
|
$file_size = null;
|
|
$file_size_raw = null;
|
|
|
|
$file_upload_message[] = 'File upload successful';
|
|
// internal file id
|
|
$file_uid = uuidv4();
|
|
// move file to tmp location and return new name
|
|
move_uploaded_file(
|
|
$_FILES[$upload_name]['tmp_name'],
|
|
$folder . $file_uid
|
|
);
|
|
$file_name = $_FILES[$upload_name]['name'];
|
|
$file_size = humanReadableByteFormat($_FILES[$upload_name]['size']);
|
|
$file_size_raw = $_FILES[$upload_name]['size'];
|
|
// correct the image rotation
|
|
// $this->correctImageOrientation(BASE.TMP.$file_uid);
|
|
// make a copy to layout/cache/images for file url
|
|
// as a thumbnail in defined size
|
|
// $file_url = $this->form_base_path
|
|
// . $this->createThumbnailSimple(BASE.TMP.$file_uid, THUMB_WIDTH, THUMB_HEIGHT);
|
|
// write back data for frontend processing
|
|
$ajax_data = [
|
|
'msg' => $file_upload_message,
|
|
'file_uid' => $file_uid,
|
|
'file_url' => $file_url,
|
|
'file_name' => $file_name,
|
|
'file_size' => $file_size,
|
|
'file_size_raw' => $file_size_raw,
|
|
'file_type' => $mime_type,
|
|
];
|
|
} else {
|
|
$info_msg = 'File uploaded and check failed';
|
|
errMsg($status, $info_msg);
|
|
$ajax_data['msg'][] = $info_msg;
|
|
}
|
|
} else {
|
|
$info_msg = isset($_FILES[$upload_name]) ?
|
|
'File upload filed: ' . fileUploadErrorMessage($_FILES[$upload_name]['error']) :
|
|
'General file upload error';
|
|
errMsg($status, $info_msg);
|
|
$ajax_data = [
|
|
'msg' => [
|
|
$info_msg
|
|
]
|
|
];
|
|
}
|
|
break;
|
|
default:
|
|
$error = true;
|
|
errMsg($status, 'Abnormal action');
|
|
break;
|
|
}
|
|
} else {
|
|
$error = true;
|
|
errMsg($status, 'No action set');
|
|
}
|
|
|
|
$data = [
|
|
'status' => $status,
|
|
'msg' => $error_string,
|
|
'action' => $_POST['action'] ?? null,
|
|
'content' => $ajax_data
|
|
];
|
|
|
|
// print the JSON data out to the browsers
|
|
$output = json_encode($data);
|
|
print $output;
|
|
|
|
// __END__
|