Merged in feature/HOR-4508 (pull request #6649)

HOR-4508

Approved-by: Julio Cesar Laura Avendaño <contact@julio-laura.com>
This commit is contained in:
Paula Quispe
2018-11-12 17:42:09 +00:00
committed by Julio Cesar Laura Avendaño
28 changed files with 831 additions and 99 deletions

View File

@@ -88,7 +88,8 @@
"thirdparty/pake/pakeFunction.php", "thirdparty/pake/pakeFunction.php",
"thirdparty/HTMLPurifier/HTMLPurifier.auto.php", "thirdparty/HTMLPurifier/HTMLPurifier.auto.php",
"workflow/engine/classes/class.pmFunctions.php", "workflow/engine/classes/class.pmFunctions.php",
"workflow/engine/src/ProcessMaker/Util/helpers.php" "workflow/engine/src/ProcessMaker/Util/helpers.php",
"framework/src/Maveriks/Extension/Restler/UploadFormat.php"
] ]
}, },
"autoload-dev": { "autoload-dev": {

View File

@@ -0,0 +1,36 @@
<?php
/**
* This is a partial list of the known types, add the type you want to be recognized,
* this affects the whole application globally.
*
* https://www.iana.org/assignments/media-types/media-types.xml
*/
return [
'dat' => 'text/plain',
'doc' => ['application/msword', 'text/html'],
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'exe' => ['application/x-msdownload', 'application/x-dosexec'],
'gif' => 'image/gif',
'htm' => 'text/html',
'html' => 'text/html',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'mp3' => 'audio/mpeg',
'mp4' => 'video/mp4',
'ppt' => 'application/vnd.ms-office',
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
'pm' => 'text/plain',
'pmt' => 'text/plain',
'pmx' => 'application/xml',
'po' => 'text/x-po',
'pdf' => 'application/pdf',
'png' => 'image/png',
'php' => 'text/x-php',
'rar' => 'application/x-rar',
'txt' => 'text/plain',
'wmv' => ['video/x-ms-asf', 'video/x-ms-wmv'],
'xls' => ['application/vnd.ms-excel', 'text/plain'],
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'zip' => 'application/zip',
];

View File

@@ -3,14 +3,16 @@
namespace Maveriks; namespace Maveriks;
use Bootstrap; use Bootstrap;
use G;
use Illuminate\Foundation\Http\Kernel;
use Luracast\Restler\Format\UploadFormat;
use Luracast\Restler\RestException;
use Maveriks\Util; use Maveriks\Util;
use ProcessMaker\Core\System; use ProcessMaker\Core\System;
use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Services; use ProcessMaker\Services;
use ProcessMaker\Services\Api; use ProcessMaker\Services\Api;
use Luracast\Restler\RestException; use ProcessMaker\Validation\ValidationUploadedFiles;
use Illuminate\Foundation\Http\Kernel;
use G;
/** /**
* Web application bootstrap * Web application bootstrap
@@ -252,8 +254,6 @@ class WebApplication
*/ */
protected function initRest($uri, $version, $multipart = false) protected function initRest($uri, $version, $multipart = false)
{ {
require_once $this->rootDir . "/framework/src/Maveriks/Extension/Restler/UploadFormat.php";
// $servicesDir contains directory where Services Classes are allocated // $servicesDir contains directory where Services Classes are allocated
$servicesDir = $this->workflowDir . 'engine' . DS . 'src' . DS . 'ProcessMaker' . DS . 'Services' . DS; $servicesDir = $this->workflowDir . 'engine' . DS . 'src' . DS . 'ProcessMaker' . DS . 'Services' . DS;
// $apiDir - contains directory to scan classes and add them to Restler // $apiDir - contains directory to scan classes and add them to Restler
@@ -331,6 +331,17 @@ class WebApplication
$this->rest->setOverridingFormats('JsonFormat', 'UploadFormat'); $this->rest->setOverridingFormats('JsonFormat', 'UploadFormat');
UploadFormat::$customValidationFunction = function($target) {
$validator = ValidationUploadedFiles::getValidationUploadedFiles()->runRules([
'filename' => $target['name'],
'path' => $target['tmp_name']
]);
if ($validator->fails()) {
throw new RestException($validator->getStatus(), $validator->getMessage());
}
return true;
};
// scan all api directory to find api classes // scan all api directory to find api classes
$classesList = Util\Common::rglob($apiDir . "/*"); $classesList = Util\Common::rglob($apiDir . "/*");

View File

@@ -4,6 +4,7 @@ use ProcessMaker\Core\System;
use ProcessMaker\AuditLog\AuditLog; use ProcessMaker\AuditLog\AuditLog;
use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Services\OAuth2\Server; use ProcessMaker\Services\OAuth2\Server;
use ProcessMaker\Validation\ValidationUploadedFiles;
class G class G
{ {
@@ -1183,7 +1184,7 @@ class G
\Bootstrap::registerMonologPhpUploadExecution('phpExecution', 200, 'Php Execution', $filename); \Bootstrap::registerMonologPhpUploadExecution('phpExecution', 200, 'Php Execution', $filename);
require_once($filename); require_once($filename);
} else { } else {
$message = G::LoadTranslation('THE_PHP_FILES_EXECUTION_WAS_DISABLED'); $message = G::LoadTranslation('ID_THE_PHP_FILES_EXECUTION_WAS_DISABLED');
\Bootstrap::registerMonologPhpUploadExecution('phpExecution', 550, $message, $filename); \Bootstrap::registerMonologPhpUploadExecution('phpExecution', 550, $message, $filename);
echo $message; echo $message;
} }
@@ -5488,6 +5489,16 @@ class G
*/ */
public static function verifyInputDocExtension($InpDocAllowedFiles, $fileName, $filesTmpName) public static function verifyInputDocExtension($InpDocAllowedFiles, $fileName, $filesTmpName)
{ {
$error = null;
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) use(&$error) {
$error = new stdclass();
$error->status = false;
$error->message = $validator->getMessage();
});
if (!is_null($error)) {
return $error;
}
// Initialize variables // Initialize variables
$res = new stdclass(); $res = new stdclass();
$res->status = false; $res->status = false;
@@ -5497,14 +5508,6 @@ class G
$aux = pathinfo($fileName); $aux = pathinfo($fileName);
$fileExtension = isset($aux['extension']) ? strtolower($aux['extension']) : ''; $fileExtension = isset($aux['extension']) ? strtolower($aux['extension']) : '';
if (\Bootstrap::getDisablePhpUploadExecution() === 1 && $fileExtension === 'php') {
$message = \G::LoadTranslation('THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED');
\Bootstrap::registerMonologPhpUploadExecution('phpUpload', 550, $message, $fileName);
$res->status = false;
$res->message = $message;
return $res;
}
// If required extension is *.* don't validate // If required extension is *.* don't validate
if (in_array('*', $allowedTypes)) { if (in_array('*', $allowedTypes)) {
$res->status = true; $res->status = true;

View File

@@ -24851,18 +24851,36 @@ msgstr "Error: The application {0} is not canceled."
msgid "The default configuration was not defined" msgid "The default configuration was not defined"
msgstr "The default configuration was not defined" msgstr "The default configuration was not defined"
# TRANSLATION
# LABEL/ID_THE_MIMETYPE_EXTENSION_ERROR
#: LABEL/ID_THE_MIMETYPE_EXTENSION_ERROR
msgid "The mime type does not correspond to the permitted extension, please verify your file."
msgstr "The mime type does not correspond to the permitted extension, please verify your file."
# TRANSLATION # TRANSLATION
# LABEL/ID_THE_NAME_CHANGE_MAY_CAUSE_DATA_LOSS # LABEL/ID_THE_NAME_CHANGE_MAY_CAUSE_DATA_LOSS
#: LABEL/ID_THE_NAME_CHANGE_MAY_CAUSE_DATA_LOSS #: LABEL/ID_THE_NAME_CHANGE_MAY_CAUSE_DATA_LOSS
msgid "The change might cause data loss in the PM table. Do you want to continue?" msgid "The change might cause data loss in the PM table. Do you want to continue?"
msgstr "The change might cause data loss in the PM table. Do you want to continue?" msgstr "The change might cause data loss in the PM table. Do you want to continue?"
# TRANSLATION
# LABEL/ID_THE_PHP_FILES_EXECUTION_WAS_DISABLED
#: LABEL/ID_THE_PHP_FILES_EXECUTION_WAS_DISABLED
msgid "The PHP files execution was disabled please contact the system administrator."
msgstr "The PHP files execution was disabled please contact the system administrator."
# TRANSLATION # TRANSLATION
# LABEL/ID_THE_REASON_REASSIGN_USER_EMPTY # LABEL/ID_THE_REASON_REASSIGN_USER_EMPTY
#: LABEL/ID_THE_REASON_REASSIGN_USER_EMPTY #: LABEL/ID_THE_REASON_REASSIGN_USER_EMPTY
msgid "Please complete the reassign reason." msgid "Please complete the reassign reason."
msgstr "Please complete the reassign reason." msgstr "Please complete the reassign reason."
# TRANSLATION
# LABEL/ID_THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED
#: LABEL/ID_THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED
msgid "The upload of PHP files was disabled please contact the system administrator."
msgstr "The upload of PHP files was disabled please contact the system administrator."
# TRANSLATION # TRANSLATION
# LABEL/ID_THE_USERNAME_EMAIL_IS_INCORRECT # LABEL/ID_THE_USERNAME_EMAIL_IS_INCORRECT
#: LABEL/ID_THE_USERNAME_EMAIL_IS_INCORRECT #: LABEL/ID_THE_USERNAME_EMAIL_IS_INCORRECT
@@ -25187,6 +25205,12 @@ msgstr "Today"
msgid "Tools" msgid "Tools"
msgstr "Tools" msgstr "Tools"
# TRANSLATION
# LABEL/ID_TOO_MANY_REQUESTS
#: LABEL/ID_TOO_MANY_REQUESTS
msgid "Too many requests"
msgstr "Too many requests"
# TRANSLATION # TRANSLATION
# LABEL/ID_TOP_MARGIN # LABEL/ID_TOP_MARGIN
#: LABEL/ID_TOP_MARGIN #: LABEL/ID_TOP_MARGIN
@@ -25913,6 +25937,18 @@ msgstr "The uploaded file exceeds the upload_max_filesize directive in php.ini"
msgid "The file has not been attached because the extension is not allowed or because the content doesn't correspond." msgid "The file has not been attached because the extension is not allowed or because the content doesn't correspond."
msgstr "The file has not been attached because the extension is not allowed or because the content doesn't correspond." msgstr "The file has not been attached because the extension is not allowed or because the content doesn't correspond."
# TRANSLATION
# LABEL/ID_UPLOAD_INVALID_DOC_MAX_FILESIZE
#: LABEL/ID_UPLOAD_INVALID_DOC_MAX_FILESIZE
msgid "File size exceeds the allowable limit of {0}"
msgstr "File size exceeds the allowable limit of {0}"
# TRANSLATION
# LABEL/ID_UPLOAD_INVALID_DOC_TYPE_FILE
#: LABEL/ID_UPLOAD_INVALID_DOC_TYPE_FILE
msgid "Invalid file format, please upload a file with one of the following formats {0}"
msgstr "Invalid file format, please upload a file with one of the following formats {0}"
# TRANSLATION # TRANSLATION
# LABEL/ID_UPLOAD_ERR_NO_FILE # LABEL/ID_UPLOAD_ERR_NO_FILE
#: LABEL/ID_UPLOAD_ERR_NO_FILE #: LABEL/ID_UPLOAD_ERR_NO_FILE

View File

@@ -2,6 +2,7 @@
use ProcessMaker\Core\System; use ProcessMaker\Core\System;
use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Validation\ValidationUploadedFiles;
/** /**
* adminProxy.php * adminProxy.php
@@ -1025,7 +1026,14 @@ class adminProxy extends HttpProxyController
*/ */
public function uploadImage() public function uploadImage()
{ {
//!dataSystem ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
echo G::json_encode([
'success' => true,
'failed' => true,
'message' => $validator->getMessage()
]);
exit();
});
$filter = new InputFilter(); $filter = new InputFilter();
$_SERVER["REQUEST_URI"] = $filter->xssFilterHard($_SERVER["REQUEST_URI"]); $_SERVER["REQUEST_URI"] = $filter->xssFilterHard($_SERVER["REQUEST_URI"]);

View File

@@ -8,6 +8,8 @@
*/ */
use ProcessMaker\Core\System; use ProcessMaker\Core\System;
use ProcessMaker\Validation\ExceptionRestApi;
use ProcessMaker\Validation\ValidationUploadedFiles;
header("Content-type: text/html;charset=utf-8"); header("Content-type: text/html;charset=utf-8");
require_once 'classes/model/AdditionalTables.php'; require_once 'classes/model/AdditionalTables.php';
@@ -723,6 +725,9 @@ class pmTablesProxy extends HttpProxyController
} }
try { try {
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
throw new ExceptionRestApi($validator->getMessage());
});
$result = new stdClass(); $result = new stdClass();
$errors = ''; $errors = '';
$fromConfirm = false; $fromConfirm = false;
@@ -891,6 +896,11 @@ class pmTablesProxy extends HttpProxyController
} }
$result->message = $msg; $result->message = $msg;
} catch (ExceptionRestApi $e) {
$result = new stdClass();
$result->success = false;
$result->errorType = 'notice';
$result->message = $e->getMessage();
} catch (Exception $e) { } catch (Exception $e) {
$result = new stdClass(); $result = new stdClass();
$result->fromAdmin = $fromAdmin; $result->fromAdmin = $fromAdmin;

View File

@@ -61035,8 +61035,11 @@ INSERT INTO TRANSLATION (TRN_CATEGORY,TRN_ID,TRN_LANG,TRN_VALUE,TRN_UPDATE_DATE
( 'LABEL','ID_THERE_PROBLEM_SENDING_EMAIL','en','There was a problem sending the email to','2016-04-08') , ( 'LABEL','ID_THERE_PROBLEM_SENDING_EMAIL','en','There was a problem sending the email to','2016-04-08') ,
( 'LABEL','ID_THE_APPLICATION_IS_NOT_CANCELED','en','Error: The application {0} is not canceled.','2016-06-15') , ( 'LABEL','ID_THE_APPLICATION_IS_NOT_CANCELED','en','Error: The application {0} is not canceled.','2016-06-15') ,
( 'LABEL','ID_THE_DEFAULT_CONFIGURATION','en','The default configuration was not defined','2016-11-16') , ( 'LABEL','ID_THE_DEFAULT_CONFIGURATION','en','The default configuration was not defined','2016-11-16') ,
( 'LABEL','ID_THE_MIMETYPE_EXTENSION_ERROR','en','The mime type does not correspond to the permitted extension, please verify your file.','2018-10-2') ,
( 'LABEL','ID_THE_NAME_CHANGE_MAY_CAUSE_DATA_LOSS','en','The change might cause data loss in the PM table. Do you want to continue?','2017-03-30') , ( 'LABEL','ID_THE_NAME_CHANGE_MAY_CAUSE_DATA_LOSS','en','The change might cause data loss in the PM table. Do you want to continue?','2017-03-30') ,
( 'LABEL','ID_THE_PHP_FILES_EXECUTION_WAS_DISABLED','en','The PHP files execution was disabled please contact the system administrator.','2018-04-20') ,
( 'LABEL','ID_THE_REASON_REASSIGN_USER_EMPTY','en','Please complete the reassign reason.','2016-10-20') , ( 'LABEL','ID_THE_REASON_REASSIGN_USER_EMPTY','en','Please complete the reassign reason.','2016-10-20') ,
( 'LABEL','ID_THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED','en','The upload of PHP files was disabled please contact the system administrator.','2018-04-20') ,
( 'LABEL','ID_THE_USERNAME_EMAIL_IS_INCORRECT','en','The username or email is incorrect','2018-01-18') , ( 'LABEL','ID_THE_USERNAME_EMAIL_IS_INCORRECT','en','The username or email is incorrect','2018-01-18') ,
( 'LABEL','ID_THIS_MONTH','en','This Month','2014-01-15') , ( 'LABEL','ID_THIS_MONTH','en','This Month','2014-01-15') ,
( 'LABEL','ID_THIS_QUARTER','en','This quarter','2014-01-15') , ( 'LABEL','ID_THIS_QUARTER','en','This quarter','2014-01-15') ,
@@ -61093,6 +61096,7 @@ INSERT INTO TRANSLATION (TRN_CATEGORY,TRN_ID,TRN_LANG,TRN_VALUE,TRN_UPDATE_DATE
( 'LABEL','ID_TO','en','To','2014-01-15') , ( 'LABEL','ID_TO','en','To','2014-01-15') ,
( 'LABEL','ID_TODAY','en','Today','2014-01-15') , ( 'LABEL','ID_TODAY','en','Today','2014-01-15') ,
( 'LABEL','ID_TOOLS','en','Tools','2014-01-15') , ( 'LABEL','ID_TOOLS','en','Tools','2014-01-15') ,
( 'LABEL','ID_TOO_MANY_REQUESTS','en','Too many requests','2018-04-25') ,
( 'LABEL','ID_TOP_MARGIN','en','Top Margin','2014-01-15') , ( 'LABEL','ID_TOP_MARGIN','en','Top Margin','2014-01-15') ,
( 'LABEL','ID_TOTAL_CASES','en','Total Cases','2014-01-15') , ( 'LABEL','ID_TOTAL_CASES','en','Total Cases','2014-01-15') ,
( 'LABEL','ID_TOTAL_CASES_REASSIGNED','en','Total Cases Reassigned','2014-01-15') , ( 'LABEL','ID_TOTAL_CASES_REASSIGNED','en','Total Cases Reassigned','2014-01-15') ,
@@ -61216,6 +61220,8 @@ INSERT INTO TRANSLATION (TRN_CATEGORY,TRN_ID,TRN_LANG,TRN_VALUE,TRN_UPDATE_DATE
( 'LABEL','ID_UPLOAD_ERR_FORM_SIZE','en','The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form','2014-01-15') , ( 'LABEL','ID_UPLOAD_ERR_FORM_SIZE','en','The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form','2014-01-15') ,
( 'LABEL','ID_UPLOAD_ERR_INI_SIZE','en','The uploaded file exceeds the upload_max_filesize directive in php.ini','2014-01-15') , ( 'LABEL','ID_UPLOAD_ERR_INI_SIZE','en','The uploaded file exceeds the upload_max_filesize directive in php.ini','2014-01-15') ,
( 'LABEL','ID_UPLOAD_ERR_NOT_ALLOWED_EXTENSION','en','The file has not been attached because the extension is not allowed or because the content doesn''t correspond.','2014-10-21') , ( 'LABEL','ID_UPLOAD_ERR_NOT_ALLOWED_EXTENSION','en','The file has not been attached because the extension is not allowed or because the content doesn''t correspond.','2014-10-21') ,
( 'LABEL','ID_UPLOAD_INVALID_DOC_MAX_FILESIZE','en','File size exceeds the allowable limit of {0}','2018-11-06') ,
( 'LABEL','ID_UPLOAD_INVALID_DOC_TYPE_FILE','en','Invalid file format, please upload a file with one of the following formats {0}','2018-11-05') ,
( 'LABEL','ID_UPLOAD_ERR_NO_FILE','en','No file was uploaded','2014-01-15') , ( 'LABEL','ID_UPLOAD_ERR_NO_FILE','en','No file was uploaded','2014-01-15') ,
( 'LABEL','ID_UPLOAD_ERR_NO_TMP_DIR','en','Missing a temporary folder','2014-01-15') , ( 'LABEL','ID_UPLOAD_ERR_NO_TMP_DIR','en','Missing a temporary folder','2014-01-15') ,
( 'LABEL','ID_UPLOAD_ERR_PARTIAL','en','The uploaded file was only partially uploaded','2014-01-15') , ( 'LABEL','ID_UPLOAD_ERR_PARTIAL','en','The uploaded file was only partially uploaded','2014-01-15') ,

View File

@@ -1,6 +1,7 @@
<?php <?php
use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Validation\ValidationUploadedFiles;
$filter = new InputFilter(); $filter = new InputFilter();
$_POST = $filter->xssFilterHard($_POST); $_POST = $filter->xssFilterHard($_POST);
@@ -1445,6 +1446,15 @@ function checkTree($uidOriginFolder, $uidNewFolder)
*/ */
function uploadExternalDocument() function uploadExternalDocument()
{ {
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
$response = [
'error' => $validator->getMessage(),
'message' => $validator->getMessage(),
'success' => false
];
print_r(G::json_encode($response));
die();
});
$response = []; $response = [];
$response['action'] = $_POST['action'] . " - " . $_POST['option']; $response['action'] = $_POST['action'] . " - " . $_POST['option'];
$response['error'] = "error"; $response['error'] = "error";
@@ -1531,18 +1541,6 @@ function uploadExternalDocument()
//Read. Instance Document classes //Read. Instance Document classes
if (!empty($quequeUpload)) { if (!empty($quequeUpload)) {
foreach ($quequeUpload as $key => $fileObj) {
$extension = pathinfo($fileObj['fileName'], PATHINFO_EXTENSION);
if (\Bootstrap::getDisablePhpUploadExecution() === 1 && $extension === 'php') {
$message = \G::LoadTranslation('THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED');
\Bootstrap::registerMonologPhpUploadExecution('phpUpload', 550, $message, $fileObj['fileName']);
$response['error'] = $message;
$response['message'] = $message;
$response['success'] = false;
print_r(G::json_encode($response));
exit();
}
}
$docUid = $_POST['docUid']; $docUid = $_POST['docUid'];
$appDocUid = isset($_POST['APP_DOC_UID']) ? $_POST['APP_DOC_UID'] : ""; $appDocUid = isset($_POST['APP_DOC_UID']) ? $_POST['APP_DOC_UID'] : "";
$docVersion = isset($_POST['docVersion']) ? $_POST['docVersion'] : ""; $docVersion = isset($_POST['docVersion']) ? $_POST['docVersion'] : "";

View File

@@ -2,6 +2,8 @@
use ProcessMaker\Core\System; use ProcessMaker\Core\System;
use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Validation\ExceptionRestApi;
use ProcessMaker\Validation\ValidationUploadedFiles;
function runBgProcessmaker($task, $log) function runBgProcessmaker($task, $log)
{ {
@@ -16,6 +18,9 @@ function runBgProcessmaker($task, $log)
} }
try { try {
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
throw new ExceptionRestApi($validator->getMessage());
});
if (isset($_REQUEST["action"])) { if (isset($_REQUEST["action"])) {
$action = $_REQUEST["action"]; $action = $_REQUEST["action"];
} else { } else {
@@ -312,6 +317,15 @@ try {
$result["addons"] = array(); $result["addons"] = array();
} }
G::outRes(G::json_encode($result)); G::outRes(G::json_encode($result));
} catch (ExceptionRestApi $e) {
$token = strtotime("now");
PMException::registerErrorLog($e, $token);
G::outRes(
G::json_encode(array(
"success" => false,
"errors" => $e->getMessage()
))
);
} catch (Exception $e) { } catch (Exception $e) {
$token = strtotime("now"); $token = strtotime("now");
PMException::registerErrorLog($e, $token); PMException::registerErrorLog($e, $token);

View File

@@ -27,6 +27,7 @@
global $RBAC; global $RBAC;
use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Validation\ValidationUploadedFiles;
$RBAC->requirePermissions("PM_SETUP_ADVANCE"); $RBAC->requirePermissions("PM_SETUP_ADVANCE");
require_once PATH_CORE . 'methods' . PATH_SEP . 'enterprise' . PATH_SEP . 'enterprise.php'; require_once PATH_CORE . 'methods' . PATH_SEP . 'enterprise' . PATH_SEP . 'enterprise.php';
@@ -35,6 +36,9 @@ $response = array();
$status = 1; $status = 1;
try { try {
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
throw new Exception($validator->getMessage());
});
if (!isset($_FILES["form"]["error"]["PLUGIN_FILENAME"]) || $_FILES["form"]["error"]["PLUGIN_FILENAME"] == 1) { if (!isset($_FILES["form"]["error"]["PLUGIN_FILENAME"]) || $_FILES["form"]["error"]["PLUGIN_FILENAME"] == 1) {
$str = "There was an error uploading the file, probably the file size if greater than upload_max_filesize parameter in php.ini, please check this parameter and try again."; $str = "There was an error uploading the file, probably the file size if greater than upload_max_filesize parameter in php.ini, please check this parameter and try again.";

View File

@@ -23,6 +23,16 @@
*/ */
use \ProcessMaker\Importer\XmlImporter; use \ProcessMaker\Importer\XmlImporter;
use ProcessMaker\Validation\ValidationUploadedFiles;
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
echo G::json_encode([
'status' => 'ERROR',
'success' => true,
'catchMessage' => $validator->getMessage()
]);
exit();
});
ini_set("max_execution_time", 0); ini_set("max_execution_time", 0);
$affectedGroups = array(); $affectedGroups = array();

View File

@@ -1,5 +1,7 @@
<?php <?php
use ProcessMaker\Validation\ValidationUploadedFiles;
sleep(1); sleep(1);
global $RBAC; global $RBAC;
if ($RBAC->userCanAccess('PM_FACTORY') == 1) { if ($RBAC->userCanAccess('PM_FACTORY') == 1) {
@@ -25,26 +27,23 @@ if ($RBAC->userCanAccess('PM_FACTORY') == 1) {
} }
} }
$fileName = $_FILES['form']['name']; ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
$canUploadPhpFile = true; $response = [
$extension = pathinfo($fileName, PATHINFO_EXTENSION); 'result' => 0,
if (\Bootstrap::getDisablePhpUploadExecution() === 1 && $extension === 'php') { 'msg' => $validator->getMessage()
$message = \G::LoadTranslation('THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED'); ];
\Bootstrap::registerMonologPhpUploadExecution('phpUpload', 550, $message, $fileName); print_r(G::json_encode($response));
$canUploadPhpFile = false; die();
} });
if ($_FILES['form']['error'] == "0" && $canUploadPhpFile) { $fileName = $_FILES['form']['name'];
if ($_FILES['form']['error'] == "0") {
G::uploadFile($_FILES['form']['tmp_name'], $sDirectory, $fileName); G::uploadFile($_FILES['form']['tmp_name'], $sDirectory, $fileName);
$msg = "Uploaded (" . (round((filesize($sDirectory . $fileName) / 1024) * 10) / 10) . " kb)"; $msg = "Uploaded (" . (round((filesize($sDirectory . $fileName) / 1024) * 10) / 10) . " kb)";
$result = 1; $result = 1;
} else { } else {
$msg = "Failed"; $msg = "Failed";
if ($canUploadPhpFile === false) {
$msg = $message;
}
$result = 0; $result = 0;
} }
echo "{'result': $result, 'msg':'$msg'}"; echo "{'result': $result, 'msg':'$msg'}";
} }

View File

@@ -2,6 +2,8 @@
require_once "classes/model/Language.php"; require_once "classes/model/Language.php";
use ProcessMaker\Validation\ValidationUploadedFiles;
global $RBAC; global $RBAC;
$access = $RBAC->userCanAccess('PM_SETUP_ADVANCE'); $access = $RBAC->userCanAccess('PM_SETUP_ADVANCE');
@@ -24,6 +26,9 @@ if ($access != 1) {
$result = new stdClass(); $result = new stdClass();
try { try {
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
throw new Exception($validator->getMessage());
});
//if the xmlform path is writeable //if the xmlform path is writeable
if (!is_writable(PATH_XMLFORM)) { if (!is_writable(PATH_XMLFORM)) {
throw new Exception(G::LoadTranslation('IMPORT_LANGUAGE_ERR_NO_WRITABLE')); throw new Exception(G::LoadTranslation('IMPORT_LANGUAGE_ERR_NO_WRITABLE'));

View File

@@ -26,11 +26,15 @@
use ProcessMaker\Core\System; use ProcessMaker\Core\System;
use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Validation\ValidationUploadedFiles;
global $RBAC; global $RBAC;
$RBAC->requirePermissions('PM_SETUP_ADVANCE'); $RBAC->requirePermissions('PM_SETUP_ADVANCE');
try { try {
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
throw new Exception($validator->getMessage());
});
//load the variables //load the variables
if (!isset($_FILES['form']['error']['PLUGIN_FILENAME']) || $_FILES['form']['error']['PLUGIN_FILENAME'] == 1) { if (!isset($_FILES['form']['error']['PLUGIN_FILENAME']) || $_FILES['form']['error']['PLUGIN_FILENAME'] == 1) {
throw (new Exception(G::loadTranslation('ID_ERROR_UPLOADING_PLUGIN_FILENAME'))); throw (new Exception(G::loadTranslation('ID_ERROR_UPLOADING_PLUGIN_FILENAME')));

View File

@@ -1,6 +1,7 @@
<?php <?php
use ProcessMaker\Core\System; use ProcessMaker\Core\System;
use ProcessMaker\Validation\ValidationUploadedFiles;
if (! isset( $_REQUEST['action'] )) { if (! isset( $_REQUEST['action'] )) {
$res['success'] = false; $res['success'] = false;
@@ -199,6 +200,9 @@ function newSkin ($baseSkin = 'classic')
function importSkin () function importSkin ()
{ {
try { try {
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
throw new Exception($validator->getMessage());
});
if (! isset( $_FILES['uploadedFile'] )) { if (! isset( $_FILES['uploadedFile'] )) {
throw (new Exception( G::LoadTranslation( 'ID_SKIN_FILE_REQUIRED' ) )); throw (new Exception( G::LoadTranslation( 'ID_SKIN_FILE_REQUIRED' ) ));
} }

View File

@@ -1,28 +1,29 @@
<?php <?php
namespace ProcessMaker\BusinessModel\Cases; namespace ProcessMaker\BusinessModel\Cases;
use ProcessMaker\Plugins\PluginRegistry;
use AppDocument;
use AppDocumentPeer;
use Exception;
use Criteria;
use ResultSet;
use G;
use ObjectPermissionPeer;
use StepPeer;
use StepSupervisorPeer;
use AppDelegation; use AppDelegation;
use AppDelegationPeer; use AppDelegationPeer;
use Users; use AppDocument;
use Configurations; use AppDocumentPeer;
use Bootstrap;
use WsBase;
use ApplicationPeer;
use ProcessMaker\BusinessModel\ProcessSupervisor;
use ProcessMaker\BusinessModel\Cases AS BusinessModelCases;
use Cases;
use ProcessUserPeer;
use AppFolder; use AppFolder;
use ApplicationPeer;
use Bootstrap;
use Cases;
use Configurations;
use Criteria;
use Exception;
use G;
use ObjectPermissionPeer;
use ProcessMaker\BusinessModel\Cases AS BusinessModelCases;
use ProcessMaker\BusinessModel\ProcessSupervisor;
use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Validation\ValidationUploadedFiles;
use ProcessUserPeer;
use ResultSet;
use StepPeer;
use StepSupervisorPeer;
use Users;
use WsBase;
class InputDocument class InputDocument
@@ -936,6 +937,12 @@ class InputDocument
*/ */
public function uploadFileCase($files, $caseInstance, $aData, $userUid, $appUid, $delIndex) public function uploadFileCase($files, $caseInstance, $aData, $userUid, $appUid, $delIndex)
{ {
ValidationUploadedFiles::getValidationUploadedFiles()->dispach(function($validator) {
G::SendMessageText($validator->getMessage(), "ERROR");
$url = explode("sys" . config("system.workspace"), $_SERVER['HTTP_REFERER']);
G::header("location: " . "/sys" . config("system.workspace") . $url[1]);
die();
});
$arrayField = array(); $arrayField = array();
$arrayFileName = array(); $arrayFileName = array();
$arrayFileTmpName = array(); $arrayFileTmpName = array();
@@ -1034,16 +1041,6 @@ class InputDocument
$aFields = array("APP_UID" => $appUid, "DEL_INDEX" => $delIndex, "USR_UID" => $userUid, "DOC_UID" => -1, "APP_DOC_TYPE" => "ATTACHED", "APP_DOC_CREATE_DATE" => date("Y-m-d H:i:s"), "APP_DOC_COMMENT" => "", "APP_DOC_TITLE" => "", "APP_DOC_FILENAME" => $arrayFileName[$i], "APP_DOC_FIELDNAME" => $fieldName); $aFields = array("APP_UID" => $appUid, "DEL_INDEX" => $delIndex, "USR_UID" => $userUid, "DOC_UID" => -1, "APP_DOC_TYPE" => "ATTACHED", "APP_DOC_CREATE_DATE" => date("Y-m-d H:i:s"), "APP_DOC_COMMENT" => "", "APP_DOC_TITLE" => "", "APP_DOC_FILENAME" => $arrayFileName[$i], "APP_DOC_FIELDNAME" => $fieldName);
} }
$sExtension = pathinfo($aFields["APP_DOC_FILENAME"]);
if (Bootstrap::getDisablePhpUploadExecution() === 1 && $sExtension["extension"] === 'php') {
$message = G::LoadTranslation('THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED');
Bootstrap::registerMonologPhpUploadExecution('phpUpload', 550, $message, 'processmaker.log');
G::SendMessageText($message, "ERROR");
$backUrlObj = explode("sys" . config("system.workspace"), $_SERVER['HTTP_REFERER']);
G::header("location: " . "/sys" . config("system.workspace") . $backUrlObj[1]);
die();
}
$oAppDocument = new AppDocument(); $oAppDocument = new AppDocument();
$oAppDocument->create($aFields); $oAppDocument->create($aFields);

View File

@@ -196,11 +196,6 @@ class FilesManager
if ($extention == '.exe') { if ($extention == '.exe') {
throw new \Exception(\G::LoadTranslation('ID_FILE_UPLOAD_INCORRECT_EXTENSION')); throw new \Exception(\G::LoadTranslation('ID_FILE_UPLOAD_INCORRECT_EXTENSION'));
} }
if (\Bootstrap::getDisablePhpUploadExecution() === 1 && $extention === '.php' && !$isImport) {
$message = \G::LoadTranslation('THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED');
\Bootstrap::registerMonologPhpUploadExecution('phpUpload', 550, $message, $aData['prf_filename']);
throw new \Exception($message);
}
break; break;
default: default:
$sDirectory = PATH_DATA_MAILTEMPLATES . $sProcessUID . PATH_SEP . $sSubDirectory . $aData['prf_filename']; $sDirectory = PATH_DATA_MAILTEMPLATES . $sProcessUID . PATH_SEP . $sSubDirectory . $aData['prf_filename'];

View File

@@ -32,6 +32,8 @@ use ProcessMaker\Core\RoutingScreen;
use ProcessMaker\Core\System; use ProcessMaker\Core\System;
use ProcessMaker\Services\Api\Project\Activity\Step as ActivityStep; use ProcessMaker\Services\Api\Project\Activity\Step as ActivityStep;
use ProcessMaker\Util\DateTime; use ProcessMaker\Util\DateTime;
use ProcessMaker\Validation\ExceptionRestApi;
use ProcessMaker\Validation\Validator;
use ProcessPeer; use ProcessPeer;
use Propel; use Propel;
use RBAC; use RBAC;
@@ -995,16 +997,6 @@ class Light
$confEnvSetting = $config->getFormats(); $confEnvSetting = $config->getFormats();
$user = new Users(); $user = new Users();
foreach ($requestData as $k => $file) { foreach ($requestData as $k => $file) {
$ext = pathinfo($file['name'], PATHINFO_EXTENSION);
if (Bootstrap::getDisablePhpUploadExecution() === 1 && $ext === 'php') {
$message = G::LoadTranslation('THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED');
Bootstrap::registerMonologPhpUploadExecution('phpUpload', 550, $message, $file['name']);
$response[$k]['error'] = array(
"code" => "400",
"message" => $message
);
continue;
}
$cases = new Cases(); $cases = new Cases();
$delIndex = $cases->getCurrentDelegation($appUid, $userUid); $delIndex = $cases->getCurrentDelegation($appUid, $userUid);
$docUid = !empty($file['docUid']) ? $file['docUid'] : -1; $docUid = !empty($file['docUid']) ? $file['docUid'] : -1;
@@ -1071,7 +1063,7 @@ class Light
* *
* @throws Exception * @throws Exception
*/ */
public function documentUploadFiles($userUid, $app_uid, $app_doc_uid, $request_data) public function documentUploadFiles($userUid, $app_uid, $app_doc_uid)
{ {
$response = array("status" => "fail"); $response = array("status" => "fail");
if (isset($_FILES["form"]["name"]) && count($_FILES["form"]["name"]) > 0) { if (isset($_FILES["form"]["name"]) && count($_FILES["form"]["name"]) > 0) {
@@ -1107,6 +1099,58 @@ class Light
} }
} }
if (count($arrayField) > 0) { if (count($arrayField) > 0) {
//rule validation
$appDocument = new AppDocument();
$appDocument->load($app_doc_uid);
$inputDocument = new InputDocument();
$ifInputExist = $inputDocument->InputExists($appDocument->getDocUid());
if ($ifInputExist) {
$inputProperties = $inputDocument->load($appDocument->getDocUid());
$inpDocTypeFile = $inputProperties['INP_DOC_TYPE_FILE'];
$inpDocMaxFilesize = (int) $inputProperties["INP_DOC_MAX_FILESIZE"];
$inpDocMaxFilesizeUnit = $inputProperties["INP_DOC_MAX_FILESIZE_UNIT"];
}
for ($i = 0; $ifInputExist && $i < count($arrayField); $i++) {
$file = [
'filename' => $arrayFileName[$i],
'path' => $arrayFileTmpName[$i]
];
$validator = new Validator();
//rule: extension
$validator->addRule()
->validate($file, function($file) use($inpDocTypeFile) {
$result = G::verifyInputDocExtension($inpDocTypeFile, $file->filename, $file->path);
return $result->status === false;
})
->status(415)
->message(G::LoadTranslation('ID_UPLOAD_INVALID_DOC_TYPE_FILE', [$inpDocTypeFile]))
->log(function($rule) {
Bootstrap::registerMonologPhpUploadExecution('phpUpload', 250, $rule->getMessage(), $rule->getData()->filename);
});
//rule: maximum file size
$validator->addRule()
->validate($file, function($file) use($inpDocMaxFilesize, $inpDocMaxFilesizeUnit) {
if ($inpDocMaxFilesize > 0) {
$totalMaxFileSize = $inpDocMaxFilesize * ($inpDocMaxFilesizeUnit == "MB" ? 1024 * 1024 : 1024);
$fileSize = filesize($file->path);
if ($fileSize > $totalMaxFileSize) {
return true;
}
}
return false;
})
->status(413)
->message(G::LoadTranslation("ID_UPLOAD_INVALID_DOC_MAX_FILESIZE", [$inpDocMaxFilesize . $inpDocMaxFilesizeUnit]))
->log(function($rule) {
Bootstrap::registerMonologPhpUploadExecution('phpUpload', 250, $rule->getMessage(), $rule->getData()->filename);
});
$validator->validate();
if ($validator->fails()) {
throw new ExceptionRestApi($validator->getMessage(), $validator->getStatus());
}
}
for ($i = 0; $i <= count($arrayField) - 1; $i++) { for ($i = 0; $i <= count($arrayField) - 1; $i++) {
if ($arrayFileError[$i] == 0) { if ($arrayFileError[$i] == 0) {
$indocUid = null; $indocUid = null;

View File

@@ -66,7 +66,10 @@ class System
'logging_level' => 'INFO', 'logging_level' => 'INFO',
'smtp_timeout' => 20, 'smtp_timeout' => 20,
'google_map_api_key' => '', 'google_map_api_key' => '',
'google_map_signature' => '' 'google_map_signature' => '',
'logging_level' => 'INFO',
'upload_attempts_limit_per_user' => '60,1',
'files_white_list' => ''
); );
/** /**

View File

@@ -23,6 +23,7 @@ use ProcessMaker\Project\Adapter;
use ProcessMaker\Services\Api; use ProcessMaker\Services\Api;
use ProcessMaker\Services\Api\Project\Activity\Step; use ProcessMaker\Services\Api\Project\Activity\Step;
use ProcessMaker\Util\DateTime; use ProcessMaker\Util\DateTime;
use ProcessMaker\Validation\ExceptionRestApi;
use RBAC; use RBAC;
use stdclass; use stdclass;
use StepPeer; use StepPeer;
@@ -1466,10 +1467,11 @@ class Light extends Api
$userUid = $this->getUserId(); $userUid = $this->getUserId();
$oMobile = new BusinessModelLight(); $oMobile = new BusinessModelLight();
$filesUids = $oMobile->postUidUploadFiles($userUid, $app_uid, $request_data); $filesUids = $oMobile->postUidUploadFiles($userUid, $app_uid, $request_data);
} catch (ExceptionRestApi $e) {
throw new RestException($e->getCode(), $e->getMessage());
} catch (Exception $e) { } catch (Exception $e) {
throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); throw new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage());
} }
return $filesUids; return $filesUids;
} }
@@ -1500,11 +1502,12 @@ class Light extends Api
try { try {
$userUid = $this->getUserId(); $userUid = $this->getUserId();
$oMobile = new BusinessModelLight(); $oMobile = new BusinessModelLight();
$response = $oMobile->documentUploadFiles($userUid, $app_uid, $app_doc_uid, $request_data); $response = $oMobile->documentUploadFiles($userUid, $app_uid, $app_doc_uid);
} catch (ExceptionRestApi $e) {
throw new RestException($e->getCode(), $e->getMessage());
} catch (Exception $e) { } catch (Exception $e) {
throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage())); throw (new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()));
} }
return $response; return $response;
} }

View File

@@ -1,8 +1,11 @@
<?php <?php
namespace ProcessMaker\Services\Api\Project; namespace ProcessMaker\Services\Api\Project;
use \ProcessMaker\Services\Api; use Exception;
use \Luracast\Restler\RestException; use Luracast\Restler\RestException;
use ProcessMaker\BusinessModel\FilesManager as FilesManagerBusinessModel;
use ProcessMaker\Services\Api;
use ProcessMaker\Validation\ExceptionRestApi;
/** /**
* Project\ProjectUsers Api Controller * Project\ProjectUsers Api Controller
@@ -57,11 +60,13 @@ class FilesManager extends Api
$userUid = $this->getUserId(); $userUid = $this->getUserId();
$request_data = (array)($request_data); $request_data = (array)($request_data);
$request_data = array_merge(array('prf_content' => $prf_content ), $request_data); $request_data = array_merge(array('prf_content' => $prf_content ), $request_data);
$filesManager = new \ProcessMaker\BusinessModel\FilesManager(); $filesManager = new FilesManagerBusinessModel();
$arrayData = $filesManager->addProcessFilesManager($prj_uid, $userUid, $request_data); $arrayData = $filesManager->addProcessFilesManager($prj_uid, $userUid, $request_data);
//Response //Response
$response = $arrayData; $response = $arrayData;
} catch (\Exception $e) { } catch (ExceptionRestApi $e) {
throw new RestException($e->getCode(), $e->getMessage());
} catch (Exception $e) {
//response //response
throw new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()); throw new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage());
} }
@@ -85,11 +90,13 @@ class FilesManager extends Api
public function doPostProcessFilesManagerUpload($prj_uid, $prf_uid) public function doPostProcessFilesManagerUpload($prj_uid, $prf_uid)
{ {
try { try {
$filesManager = new \ProcessMaker\BusinessModel\FilesManager(); $filesManager = new FilesManagerBusinessModel();
$sData = $filesManager->uploadProcessFilesManager($prj_uid, $prf_uid); $sData = $filesManager->uploadProcessFilesManager($prj_uid, $prf_uid);
//Response //Response
$response = $sData; $response = $sData;
} catch (\Exception $e) { } catch (ExceptionRestApi $e) {
throw new RestException($e->getCode(), $e->getMessage());
} catch (Exception $e) {
//response //response
throw new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage()); throw new RestException(Api::STAT_APP_EXCEPTION, $e->getMessage());
} }

View File

@@ -0,0 +1,10 @@
<?php
namespace ProcessMaker\Validation;
use Exception;
class ExceptionRestApi extends Exception
{
}

View File

@@ -0,0 +1,137 @@
<?php
namespace ProcessMaker\Validation;
/**
* It contains a validation rule defined by the Closure function that must
* return a boolean value, true if it has failed, and false if it has passed the
* validation rule.
*/
class Rule
{
/**
* Validation data defined by value and field.
* @var object
*/
private $data = null;
/**
* Validation rule.
* @var Closure
*/
private $callback = null;
/**
* Help to register when the rule is not met.
* @var Closure
*/
private $callbackLog = null;
/**
* Return message in case the rule is not met.
* @var string
*/
private $message = "";
/**
* Response status code.
* @var int
*/
private $status = 0;
/**
* Obtain validation data composed of field and value.
* @return object
*/
function getData()
{
return $this->data;
}
/**
* Get the Closure function.
* @return Closure
*/
function getCallback()
{
return $this->callback;
}
/**
* Gets the Closure function that applies the validation rule.
* @return Closure
*/
function getCallbackLog()
{
return $this->callbackLog;
}
/**
* Get the message to be saved in the log if the rule is not fulfilled.
* @return string
*/
function getMessage()
{
return $this->message;
}
/**
* Get status code.
* @return int
*/
function getStatus()
{
return $this->status;
}
/**
* Registers the data and the Closure function that contains the validation
* rule.
* @param array $data
* @param Closure $callback
* @return Rule
*/
public function validate($data, $callback = null)
{
$this->data = (object) $data;
if (is_callable($callback)) {
$this->callback = $callback;
}
return $this;
}
/**
* Registers the customized message in case the validation rule is not met.
* @param string $message
* @return Rule
*/
public function message($message = "")
{
$this->message = $message;
return $this;
}
/**
* Set status code.
* @param int $status
* @return $this
*/
function status($status = 0)
{
$this->status = $status;
return $this;
}
/**
* Registers the Closure function in case the validation rule is not met.
* @param Closure $callback
* @return Rule
*/
public function log($callback = null)
{
if (is_callable($callback)) {
$this->callbackLog = $callback;
}
return $this;
}
}

View File

@@ -0,0 +1,241 @@
<?php
namespace ProcessMaker\Validation;
use Bootstrap;
use G;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\Cache;
use ProcessMaker\Core\System;
use ProcessMaker\Services\OAuth2\Server;
use Symfony\Component\HttpFoundation\File\File;
class ValidationUploadedFiles
{
/**
* Single object instance to be used in the entire environment.
*
* @var object
*/
private static $validationUploadedFiles = null;
/**
* List of evaluated items that have not passed the validation rules.
*
* @var array
*/
private $fails = [];
/**
* Check if the loaded files comply with the validation rules, add here if you
* want more validation rules.
* Accept per argument an array or object that contains a "filename" and "path" values.
* The rules are verified in the order in which they have been added.
*
* @param array|object $file
* @return Validator
*/
public function runRules($file)
{
$validator = new Validator();
//rule: disable_php_upload_execution
$validator->addRule()
->validate($file, function($file) {
$filesystem = new Filesystem();
$extension = $filesystem->extension($file->filename);
return Bootstrap::getDisablePhpUploadExecution() === 1 && $extension === 'php';
})
->status(550)
->message(G::LoadTranslation('ID_THE_UPLOAD_OF_PHP_FILES_WAS_DISABLED'))
->log(function($rule) {
/**
* Levels supported by MonologProvider is:
* 100 "DEBUG"
* 200 "INFO"
* 250 "NOTICE"
* 300 "WARNING"
* 400 "ERROR"
* 500 "CRITICAL"
* 550 "ALERT"
* 600 "EMERGENCY"
*/
Bootstrap::registerMonologPhpUploadExecution('phpUpload', 550, $rule->getMessage(), $rule->getData()->filename);
});
//rule: upload_attempts_limit_per_user
$validator->addRule()
->validate($file, function($file) {
$systemConfiguration = System::getSystemConfiguration('', '', config("system.workspace"));
$filesWhiteList = explode(',', $systemConfiguration['upload_attempts_limit_per_user']);
$userId = Server::getUserId();
$key = config("system.workspace") . '/' . $userId;
$attemps = (int) trim($filesWhiteList[0]);
$minutes = (int) trim($filesWhiteList[1]);
$pastAttemps = Cache::remember($key, $minutes, function() {
return 1;
});
//We only increase when the file path exists, useful when pre-validation is done.
if (isset($file->path)) {
Cache::increment($key, 1);
}
if ($pastAttemps <= $attemps) {
return false;
}
return true;
})
->status(429)
->message(G::LoadTranslation('ID_TOO_MANY_REQUESTS'))
->log(function($rule) {
/**
* Levels supported by MonologProvider is:
* 100 "DEBUG"
* 200 "INFO"
* 250 "NOTICE"
* 300 "WARNING"
* 400 "ERROR"
* 500 "CRITICAL"
* 550 "ALERT"
* 600 "EMERGENCY"
*/
Bootstrap::registerMonologPhpUploadExecution('phpUpload', 250, $rule->getMessage(), $rule->getData()->filename);
});
//rule: mimeType
$validator->addRule()
->validate($file, function($file) {
$path = isset($file->path) ? $file->path : "";
$filesystem = new Filesystem();
if (!$filesystem->exists($path)) {
return false;
}
$extension = $filesystem->extension($file->filename);
$mimeType = $filesystem->mimeType($path);
$file = new File($path);
$guessExtension = $file->guessExtension();
$mimeTypeFile = $file->getMimeType();
//mimeType known
if ($extension === $guessExtension && $mimeType === $mimeTypeFile) {
return false;
}
//mimeType custom
$customMimeTypes = config("customMimeTypes");
$customMimeType = isset($customMimeTypes[$extension]) ? $customMimeTypes[$extension] : null;
if (is_string($customMimeType)) {
if ($customMimeType === $mimeType) {
return false;
}
}
if (is_array($customMimeType)) {
foreach ($customMimeType as $value) {
if ($value === $mimeType) {
return false;
}
}
}
//files_white_list
$systemConfiguration = System::getSystemConfiguration('', '', config("system.workspace"));
$filesWhiteList = explode(',', $systemConfiguration['files_white_list']);
if (in_array($extension, $filesWhiteList)) {
return false;
}
return true;
})
->status(415)
->message(G::LoadTranslation('ID_THE_MIMETYPE_EXTENSION_ERROR'))
->log(function($rule) {
/**
* Levels supported by MonologProvider is:
* 100 "DEBUG"
* 200 "INFO"
* 250 "NOTICE"
* 300 "WARNING"
* 400 "ERROR"
* 500 "CRITICAL"
* 550 "ALERT"
* 600 "EMERGENCY"
*/
Bootstrap::registerMonologPhpUploadExecution('phpUpload', 250, $rule->getMessage(), $rule->getData()->filename);
});
return $validator->validate();
}
/**
* File upload validation.
*
* @return $this
*/
public function runRulesToAllUploadedFiles()
{
$files = $_FILES;
if (!is_array($files)) {
return;
}
$this->fails = [];
foreach ($files as $file) {
$data = (object) $file;
if (!is_array($data->name) || !is_array($data->tmp_name)) {
$data->name = [$data->name];
$data->tmp_name = [$data->tmp_name];
}
foreach ($data->name as $key => $value) {
if (empty($value)) {
continue;
}
if (is_array($value)) {
foreach ($value as $rowKey => $rowValue) {
foreach ($rowValue as $cellKey => $cellValue) {
if (empty($cellValue)) {
continue;
}
$validator = $this->runRules(['filename' => $cellValue, 'path' => $data->tmp_name[$key][$rowKey][$cellKey]]);
if ($validator->fails()) {
$this->fails[] = $validator;
}
}
}
continue;
}
$validator = $this->runRules(['filename' => $value, 'path' => $data->tmp_name[$key]]);
if ($validator->fails()) {
$this->fails[] = $validator;
}
}
}
return $this;
}
/**
* Get the first error and call the argument function.
*
* @param function $callback
* @return $this
*/
public function dispach($callback)
{
if (!empty($this->fails[0])) {
if (!empty($callback) && is_callable($callback)) {
$callback($this->fails[0], $this->fails);
}
}
return $this;
}
/**
* It obtains a single object to be used as a record of the whole environment.
*
* @return object
*/
public static function getValidationUploadedFiles()
{
if (self::$validationUploadedFiles === null) {
self::$validationUploadedFiles = new ValidationUploadedFiles();
}
return self::$validationUploadedFiles;
}
}

View File

@@ -0,0 +1,138 @@
<?php
namespace ProcessMaker\Validation;
use ProcessMaker\Validation\Rule;
/**
* Performs the validation process based on a list of validation rules.
*/
class Validator
{
/**
* List of instances of the class 'Rule'.
* @var array
*/
private $rules = [];
/**
* Error message in the current validation rule.
* @var string
*/
private $message = "";
/**
* Response status code.
* @var int
*/
private $status = 0;
/**
* Current status of the validation, true if the validation has not been overcome.
* @var boolean
*/
private $fails = false;
/**
* Call after the validation process.
* @var Closure
*/
private $callback = null;
/**
* Get the message of the current validation if there was a failure.
* @return string
*/
function getMessage()
{
return $this->message;
}
/**
* Get status code.
* @return int
*/
function getStatus()
{
return $this->status;
}
/**
* Get the Closure function.
* @return Closure
*/
function getCallback()
{
return $this->callback;
}
/**
* Add a validation rule.
* The rules are verified in the order in which they have been added.
*
* @param Rule $rule
* @return Rule
*/
public function addRule($rule = null)
{
if (!$rule instanceof Rule) {
$rule = new Rule();
}
$this->rules[] = $rule;
return $rule;
}
/**
* Process all added validation rules.
* @return Validator
*/
public function validate()
{
$this->message = "";
$this->status = 0;
$this->fails = false;
foreach ($this->rules as $rule) {
$callback = $rule->getCallback();
if (is_callable($callback)) {
if ($callback($rule->getData())) {
$this->message = $rule->getMessage();
$this->status = $rule->getStatus();
$this->fails = true;
$getCallbackLog = $rule->getCallbackLog();
if (is_callable($getCallbackLog)) {
$getCallbackLog($rule);
}
break;
}
}
}
$callbackAfter = $this->getCallback();
if (is_callable($callbackAfter)) {
$callbackAfter($this);
}
return $this;
}
/**
* Get the current status of the validation, the value is true if there was a
* failure and false if all the validation rules have been passed.
* @return boolean
*/
public function fails()
{
return $this->fails;
}
/**
* The Closure function is called when the validation process is finished.
* @param Closure $callback
* @return Validator
*/
public function after($callback)
{
if (is_callable($callback)) {
$this->callback = $callback;
}
return $this;
}
}

View File

@@ -283,7 +283,10 @@ Ext.onReady(function () {
} }
else { else {
var messageError = ""; var messageError = "";
if (obj.failed == "1") { if (obj.failed === true) {
messageError = obj.message;
}
else if (obj.failed == "1") {
//| 1-> Fail in the type of the image //| 1-> Fail in the type of the image
messageError = _('ID_ERROR_UPLOADING_IMAGE_TYPE'); messageError = _('ID_ERROR_UPLOADING_IMAGE_TYPE');
} }

View File

@@ -6,6 +6,7 @@ use ProcessMaker\Core\AppEvent;
use ProcessMaker\ChangeLog\ChangeLog; use ProcessMaker\ChangeLog\ChangeLog;
/*----------------------------------********---------------------------------*/ /*----------------------------------********---------------------------------*/
use ProcessMaker\Plugins\PluginRegistry; use ProcessMaker\Plugins\PluginRegistry;
use ProcessMaker\Validation\ValidationUploadedFiles;
/** /**
* bootstrap - ProcessMaker Bootstrap * bootstrap - ProcessMaker Bootstrap
@@ -818,7 +819,7 @@ if (substr(SYS_COLLECTION, 0, 8) === 'gulliver') {
$isWebEntry = \ProcessMaker\BusinessModel\WebEntry::isWebEntry(SYS_COLLECTION, $phpFile); $isWebEntry = \ProcessMaker\BusinessModel\WebEntry::isWebEntry(SYS_COLLECTION, $phpFile);
if (\Bootstrap::getDisablePhpUploadExecution() === 1 && !$isWebEntry) { if (\Bootstrap::getDisablePhpUploadExecution() === 1 && !$isWebEntry) {
$message = \G::LoadTranslation('THE_PHP_FILES_EXECUTION_WAS_DISABLED'); $message = \G::LoadTranslation('ID_THE_PHP_FILES_EXECUTION_WAS_DISABLED');
\Bootstrap::registerMonologPhpUploadExecution('phpExecution', 550, $message, $phpFile); \Bootstrap::registerMonologPhpUploadExecution('phpExecution', 550, $message, $phpFile);
echo $message; echo $message;
die(); die();
@@ -1085,6 +1086,8 @@ if (!defined('EXECUTE_BY_CRON')) {
$oPluginRegistry->init(); $oPluginRegistry->init();
if ($isControllerCall) { //Instance the Controller object and call the request method if ($isControllerCall) { //Instance the Controller object and call the request method
ValidationUploadedFiles::getValidationUploadedFiles()
->runRulesToAllUploadedFiles();
$controller = new $controllerClass(); $controller = new $controllerClass();
$controller->setHttpRequestData($_REQUEST);//NewRelic Snippet - By JHL $controller->setHttpRequestData($_REQUEST);//NewRelic Snippet - By JHL
transactionLog($controllerAction); transactionLog($controllerAction);
@@ -1105,6 +1108,8 @@ if (!defined('EXECUTE_BY_CRON')) {
->setLanguage(SYS_LANG) ->setLanguage(SYS_LANG)
->getUsrIdByUsrUid(empty($_SESSION['USER_LOGGED']) ? '' : $_SESSION['USER_LOGGED']); ->getUsrIdByUsrUid(empty($_SESSION['USER_LOGGED']) ? '' : $_SESSION['USER_LOGGED']);
/*----------------------------------********---------------------------------*/ /*----------------------------------********---------------------------------*/
ValidationUploadedFiles::getValidationUploadedFiles()
->runRulesToAllUploadedFiles();
require_once $phpFile; require_once $phpFile;
} }