mirror of
https://github.com/VTECRM/vtenext.git
synced 2026-02-26 16:18:47 +00:00
230 lines
6.7 KiB
PHP
230 lines
6.7 KiB
PHP
<?php
|
|
/*************************************
|
|
* SPDX-FileCopyrightText: 2009-2020 Vtenext S.r.l. <info@vtenext.com>
|
|
* SPDX-License-Identifier: AGPL-3.0-only
|
|
************************************/
|
|
/* crmv@71387 */
|
|
|
|
class TouchUploadFile extends TouchWSClass {
|
|
|
|
public $basepath = 'storage/touch_uploads/';
|
|
|
|
function process(&$request) {
|
|
|
|
$r = $this->checkUploadsTable();
|
|
if (!$r) return $this->error("Unable to create tables");
|
|
|
|
$r = $this->checkPath();
|
|
if (!$r) return $this->error("Unable to create upload directory");
|
|
|
|
$r = $this->cleanOldFiles();
|
|
// no checks here
|
|
|
|
$newfile = '';
|
|
$uploadid = $this->saveUploadedFile($_FILES, $newfile);
|
|
|
|
if ($uploadid > 0) {
|
|
return $this->success(array('uploadid' => $uploadid, 'filename' => $newfile));
|
|
} else {
|
|
// try to get an error message
|
|
$errMsg = $this->extractErrorMessage($_FILES);
|
|
return $this->error('Unable to save the file'.( empty($errMsg) ? '' : ': '.$errMsg));
|
|
}
|
|
}
|
|
|
|
public function extractErrorMessage($files) {
|
|
$errStr = '';
|
|
if (is_array($files) && count($files) > 0) {
|
|
foreach ($files as $fname=>$finfo) {
|
|
if ($finfo['error'] > 0) {
|
|
switch ($finfo['error']) {
|
|
case UPLOAD_ERR_INI_SIZE:
|
|
$errStr = "The uploaded file exceeds the upload_max_filesize directive in php.ini";
|
|
break;
|
|
case UPLOAD_ERR_FORM_SIZE:
|
|
$errStr = "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form";
|
|
break;
|
|
case UPLOAD_ERR_PARTIAL:
|
|
$errStr = "The uploaded file was only partially uploaded";
|
|
break;
|
|
case UPLOAD_ERR_NO_FILE:
|
|
$errStr = "No file was uploaded";
|
|
break;
|
|
case UPLOAD_ERR_NO_TMP_DIR:
|
|
$errStr = "Missing a temporary folder";
|
|
break;
|
|
case UPLOAD_ERR_CANT_WRITE:
|
|
$errStr = "Failed to write file to disk";
|
|
break;
|
|
case UPLOAD_ERR_EXTENSION:
|
|
$errStr = "File upload stopped by extension";
|
|
break;
|
|
default:
|
|
$errStr = "Unknown upload error";
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return $errStr;
|
|
}
|
|
|
|
public function checkUploadsTable() {
|
|
global $adb, $table_prefix;
|
|
|
|
$table = $table_prefix.'_touch_uploads';
|
|
|
|
$schema_table =
|
|
'<schema version="0.3">
|
|
<table name="'.$table.'">
|
|
<opt platform="mysql">ENGINE=InnoDB</opt>
|
|
<field name="uploadid" type="R" size="19">
|
|
<KEY/>
|
|
</field>
|
|
<field name="userid" type="I" size="11" />
|
|
<field name="uploadtime" type="T">
|
|
<DEFAULT value="0000-00-00 00:00:00"/>
|
|
</field>
|
|
<field name="filetype" type="C" size="63" />
|
|
<field name="path" type="C" size="1000" />
|
|
</table>
|
|
</schema>';
|
|
if(!Vtecrm_Utils::CheckTable($table)) {
|
|
$schema_obj = new adoSchema($adb->database);
|
|
$schema_obj->ExecuteSchema($schema_obj->ParseSchemaString($schema_table));
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public function checkPath() {
|
|
|
|
if (!is_dir($this->basepath)) {
|
|
mkdir($this->basepath, 0755);
|
|
}
|
|
|
|
if (!is_writable($this->basepath)) return false;
|
|
return true;
|
|
}
|
|
|
|
public function cleanOldFiles() {
|
|
global $adb, $table_prefix;
|
|
|
|
$table = $table_prefix.'_touch_uploads';
|
|
|
|
$oldTime = date('Y-m-d H:i:s', time() - 3600*24*2); // 2 days
|
|
$res = $adb->pquery("SELECT uploadid, path FROM {$table} WHERE uploadtime < ?", array($oldTime));
|
|
if ($res && $adb->num_rows($res) > 0) {
|
|
while ($row = $adb->FetchByAssoc($res, -1, false)) {
|
|
$path = $this->basepath . $row['path'];
|
|
if (file_exists($path) && is_writable($path)) @unlink($path);
|
|
$adb->pquery("DELETE FROM {$table} WHERE uploadid = ?", array($row['uploadid']));
|
|
}
|
|
}
|
|
|
|
// now remove old files without database entry (something bad happened?)
|
|
$list = glob($this->basepath. '*');
|
|
if (is_array($list) && count($list) > 0) {
|
|
foreach ($list as $file) {
|
|
if (is_file($file) && is_writable($file) && filemtime($file) < (time() - 3600*24*2)) {
|
|
@unlink($file);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public function saveUploadedFile($files, &$newfile) {
|
|
global $adb, $table_prefix;
|
|
global $upload_badext, $current_user;
|
|
|
|
$table = $table_prefix.'_touch_uploads';
|
|
|
|
$extMapping = array(
|
|
'image/jpeg' => 'jpg',
|
|
'image/png' => 'png',
|
|
);
|
|
|
|
$uploadid = false;
|
|
foreach($files as $fileindex => $fileinfo) {
|
|
if ($fileinfo['name'] != '' && $fileinfo['size'] > 0){
|
|
$binFile = sanitizeUploadFileName($fileinfo['name'], $upload_badext);
|
|
$binFile = $this->sanitizeFileName($binFile);
|
|
|
|
$uploadid = $adb->getUniqueID($table);
|
|
$binFile = $uploadid . '_' . $current_user->id . '_' .$binFile;
|
|
|
|
// add extension if missing
|
|
$ext = pathinfo($binFile, PATHINFO_EXTENSION);
|
|
if (empty($ext) && !empty($fileinfo['type'])) {
|
|
if (array_key_exists($fileinfo['type'], $extMapping)) {
|
|
if (substr($binFile, -1, 1) == '.') $binFile = substr($binFile, 0, -1);
|
|
$binFile .= '.'.$extMapping[$fileinfo['type']];
|
|
}
|
|
}
|
|
|
|
$upload_status = move_uploaded_file($fileinfo['tmp_name'], $this->basepath.$binFile);
|
|
if (!$upload_status) $uploadid = false;
|
|
|
|
if ($uploadid > 0) {
|
|
$adb->pquery("INSERT INTO {$table} (uploadid, userid, uploadtime, filetype, path) VALUES (?,?,?,?,?)", array($uploadid, $current_user->id, date('Y-m-d H:i:s'), $fileinfo['type'], $binFile));
|
|
$newfile = $binFile;
|
|
}
|
|
|
|
break; // save only one file
|
|
}
|
|
}
|
|
return $uploadid;
|
|
}
|
|
|
|
public function sanitizeFileName($filename) {
|
|
return preg_replace('/[^a-zA-Z0-9_.)(-]/', '', $filename);
|
|
}
|
|
|
|
public function getTouchUploadList($ids) {
|
|
global $adb, $table_prefix, $current_user;
|
|
|
|
if (!is_array($ids)) $ids = array($ids);
|
|
$ids = array_map('intval', $ids);
|
|
$list = array();
|
|
$res = $adb->pquery("SELECT * FROM {$table_prefix}_touch_uploads WHERE userid = ? AND uploadid IN (".generateQuestionMarks($ids).")", array($current_user->id, $ids));
|
|
if ($res) {
|
|
while ($row = $adb->fetchByAssoc($res, -1, false)) {
|
|
$prefix = $row['uploadid'].'_'.$row['userid'].'_';
|
|
if (substr($row['path'], 0, strlen($prefix)) == $prefix) {
|
|
$row['realname'] = substr($row['path'], strlen($prefix));
|
|
} else {
|
|
$row['realname'] = $row['path'];
|
|
}
|
|
$list[$row['uploadid']] = $row;
|
|
}
|
|
}
|
|
|
|
return $list;
|
|
}
|
|
|
|
public function removeUploads($ids) {
|
|
global $adb, $table_prefix, $current_user;
|
|
|
|
if (!is_array($ids)) $ids = array($ids);
|
|
if (empty($ids)) return true;
|
|
|
|
$files = $this->getTouchUploadList($ids);
|
|
|
|
// from db
|
|
$res = $adb->pquery("DELETE FROM {$table_prefix}_touch_uploads WHERE userid = ? AND uploadid IN (".generateQuestionMarks($ids).")", array($current_user->id, $ids));
|
|
|
|
// and files
|
|
foreach ($files as $finfo) {
|
|
$file = $this->basepath . $finfo['path'];
|
|
if (is_file($file) && is_writable($file)) {
|
|
@unlink($file);
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
}
|