diff --git a/ClamavPlugin.inc.php b/ClamavPlugin.php similarity index 75% rename from ClamavPlugin.inc.php rename to ClamavPlugin.php index 60c7703..4fe4752 100644 --- a/ClamavPlugin.inc.php +++ b/ClamavPlugin.php @@ -11,7 +11,23 @@ * * @brief ClamAV plugin class */ -import('lib.pkp.classes.plugins.GenericPlugin'); + +namespace APP\plugins\generic\clamav; + +use PKP\plugins\GenericPlugin; +use PKP\config\Config; +use PKP\plugins\Hook; +use PKP\linkAction\LinkAction; +use PKP\linkAction\request\AjaxModal; +use PKP\core\JSONMessage; +use PKP\core\PKPApplication; +use PKP\file\TemporaryFileManager; +use Exception; +use APP\core\Application; +use APP\plugins\generic\clamav\ClamavSettingsForm; +use APP\plugins\generic\clamav\ClamavVersionHandler; +use APP\template\TemplateManager; + class ClamScanFailureException extends Exception {}; class ClamavPlugin extends GenericPlugin { @@ -34,9 +50,9 @@ function register($category, $path, $mainContextId = NULL) { return true; if ($success && $this->getEnabled()) { // Enable Clam AV's preprocessing of uploaded files - HookRegistry::register('SubmissionFile::validate', array($this, 'clamscanHandleUpload')); + Hook::add('submissionfilesuploadform::validate', array($this, 'clamscanHandleUpload')); // Create handler for AJAX call - HookRegistry::register('LoadHandler', array($this, 'setPageHandler')); + Hook::add('LoadHandler', array($this, 'setPageHandler')); } return $success; } @@ -65,30 +81,12 @@ function getDescription() { function isSitePlugin() { return true; } - - /** - * Backwards-compatible method to retrieve the current context across - * multiple versions of PKP applicatiosn - * @return - */ - function _getBackwardsCompatibleContext() { - if(method_exists('Application', 'get')) { - // OJS 3.2 and later - $request = Application::get()->getRequest(); - $context = $request->getContext(); - } else { - // OJS 3.1.2 and earlier - $context = Request::getContext(); - } - return $context; - } /** * @copydoc Plugin::getActions() */ function getActions($request, $verb) { $router = $request->getRouter(); - import('lib.pkp.classes.linkAction.request.AjaxModal'); return array_merge( $this->getEnabled() ? array( new LinkAction( @@ -106,14 +104,13 @@ function getActions($request, $verb) { function manage($args, $request) { switch ($request->getUserVar('verb')) { case 'settings': - $contextID = (!is_null($this->_getBackwardsCompatibleContext()) ? $this->_getBackwardsCompatibleContext()->getId() : CONTEXT_SITE); + $context = Application::get()->getRequest()->getContext(); + $contextID = $context->getId(); - AppLocale::requireComponents(LOCALE_COMPONENT_APP_COMMON, LOCALE_COMPONENT_PKP_MANAGER); $templateMgr = TemplateManager::getManager($request); - $templateMgr->register_function('plugin_url', array($this, 'smartyPluginUrl')); + $templateMgr->registerPlugin('function','plugin_url', array($this, 'smartyPluginUrl')); - $this->import('ClamavSettingsForm'); $form = new ClamavSettingsForm($this, $contextID); if ($request->getUserVar('save')) { @@ -138,13 +135,7 @@ function manage($args, $request) { * @copydoc PKPPlugin::getTemplatePath */ function getTemplatePath($inCore = false) { - if(method_exists($this, 'getTemplateResource')) { - // OJS 3.1.2 and later - return parent::getTemplatePath($inCore); - } else { - // OJS 3.1.1 and earlier 3.x releases - return parent::getTemplatePath($inCore) . 'templates' . DIRECTORY_SEPARATOR; - } + return parent::getTemplatePath($inCore); } /** @@ -155,7 +146,7 @@ function getTemplatePath($inCore = false) { * */ function getClamVersion($path = '', $type=self::TYPE_EXECUTABLE) { if ($path === '') { - $path = $this->getSetting(CONTEXT_SITE, 'clamavPath'); + $path = $this->getSetting(PKPApplication::CONTEXT_SITE, 'clamavPath'); } if ($type === self::TYPE_EXECUTABLE && !empty($path) && is_executable($path)) { $version = exec($path . ' --version'); @@ -194,7 +185,7 @@ function _clamscanFile($uploadedFile) { if ($this->getClamVersion() && !empty($uploadedFile)) { $output = ""; $exitCode = ""; - $clamAVPath = $this->getSetting(CONTEXT_SITE, 'clamavPath'); + $clamAVPath = $this->getSetting(PKPApplication::CONTEXT_SITE, 'clamavPath'); $scan = exec($clamAVPath . ' --no-summary -i ' . $uploadedFile, $output, $exitCode); //process the result preg_match('/:(.*)/',$output[0],$matches); @@ -220,7 +211,7 @@ function _clamscanFile($uploadedFile) { * @return boolean|string */ function _clamDaemonFile($uploadedFile) { - $clamavSocketPath = $this->getSetting(CONTEXT_SITE, 'clamavSocketPath'); + $clamavSocketPath = $this->getSetting(PKPApplication::CONTEXT_SITE, 'clamavSocketPath'); $maxInstreamSize = 1024; // TODO: need to universalize this based on a plugin setting $output = ""; $errno = 0; @@ -292,8 +283,8 @@ function _clamDaemonFile($uploadedFile) { function _clamDaemonShortPolling($socket, $delay = 100000000, $intervals = 10) { // author's note: cludge cludge cludge cludge. TODO: look into long polling for unix sockets? $output = ""; - $intervals = $this->getSetting(CONTEXT_SITE, 'clamavSocketTimeout')*10; - $failover = $this->getSetting(CONTEXT_SITE, 'allowUnscannedFiles'); + $intervals = $this->getSetting(PKPApplication::CONTEXT_SITE, 'clamavSocketTimeout')*10; + $failover = $this->getSetting(PKPApplication::CONTEXT_SITE, 'allowUnscannedFiles'); for ($i = 0; $i < $intervals; $i++) { // sleep() does not accept fractional seconds and usleep uses a surprising amount of CPU, leaving us with time_nanosleep(). @@ -315,66 +306,51 @@ function _clamDaemonShortPolling($socket, $delay = 100000000, $intervals = 10) { * @see submissionfilesuploadform::validate() */ function clamscanHandleUpload($hookName, $args) { - $fileId = $args[2]['fileId']; - $props = $args[2]; - $allowedLocales = $args[3]; - $file = Services::get('file')->get($fileId); - $path = $file->path; - $uploadedFile = Config::getVar('files', 'files_dir') . '/' . $path; + $uploadedFile = $_FILES['uploadedFile']['tmp_name']; //scan for viruses if file exists - if (null !== $file) { - $useSocket = $this->getSetting(CONTEXT_SITE, 'clamavUseSocket'); - import('lib.pkp.classes.validation.ValidatorFactory'); - $schemaService = Services::get('schema'); + if (null !== $uploadedFile) { + $useSocket = $this->getSetting(PKPApplication::CONTEXT_SITE, 'clamavUseSocket'); $rejectionMessage = array(); - $validator = \ValidatorFactory::make( - $props, - $schemaService->getValidationRules(SCHEMA_SUBMISSION_FILE, $allowedLocales), - $rejectionMessage - ); try { if ($useSocket === true) { $message = $this->_clamDaemonFile($uploadedFile); } else { - $message = $this->_clamscanFile($uploadedFile); + $tempFileManager = new TemporaryFileManager(); + $request = Application::get()->getRequest(); + $user = $request->getUser(); + $userId = $user->getId(); + $fileId = $tempFileManager->createTempFileFromExisting($uploadedFile, $userId); + $file = $tempFileManager->getFile($fileId, $userId); + $tempFilePath = $file->getFilePath(); + $message = $this->_clamscanFile($tempFilePath); + $tempFileManager->deleteById($fileId, $userId); } //No viruses found! Continue with submission - if ($message === false) { - return false; - } else { + if ($message !== false) { //ClamAV reported a virus or failed to complete the scan //Prepare to notify the user and halt the upload process $rejectionMessage = ["threatname"=>$message]; //If Clam found a virus, it will return the signature name as a string if ($message == true) { //create a user notification - $validator->errors()->add('clamAV::virusDetected', __('plugins.generic.clamav.uploadBlocked',$rejectionMessage)); + $args[0]->addError('clamAV::virusDetected', __('plugins.generic.clamav.uploadBlocked',$rejectionMessage)); } } } //Scanning errors will generate a custom exception catch (ClamScanFailureException $e){ //Couldn't scan, but ClamAV plugin settings are permissive, continue with submission anyway - $setting=$this->getSetting(CONTEXT_SITE, 'allowUnscannedFiles'); - if ( $this->getSetting(CONTEXT_SITE, 'allowUnscannedFiles')===self::UNSCANNED_ALLOW) { - return false; - } else { + $setting=$this->getSetting(PKPApplication::CONTEXT_SITE, 'allowUnscannedFiles'); + if ( $this->getSetting(PKPApplication::CONTEXT_SITE, 'allowUnscannedFiles')!==self::UNSCANNED_ALLOW) { //Otherwise notify the user that there was an error //the user will see the general error message from the locale file - $validator->errors()->add('clamAV::failedToScan', __('plugins.generic.clamav.error')); + $args[0]->addError('clamAV::failedToSCan', __('plugins.generic.clamav.error')); } } //The file is considered unsafe. Interrupt submission process and clean up the working copy/metadata - $errors = $schemaService->formatValidationErrors($validator->errors(), $schemaService->get(SCHEMA_SUBMISSION_FILE), $allowedLocales); - - if ($args[0]===null){ - $args[0]=$errors; - } elseif (is_array($args[0])) { - array_push($args[0],$errors); - } - // returning true aborts processing - return true; + $args[1] = false; + return false; } } @@ -389,9 +365,9 @@ function clamscanHandleUpload($hookName, $args) { public function setPageHandler($hookName, $params) { $page = $params[0]; $op = $params[1]; + $handler = $params[3]; if ($this->getEnabled() && $page === 'clamav' && $op === 'clamavVersion') { - $this->import('ClamavVersionHandler'); - define('HANDLER_CLASS', 'ClamavVersionHandler'); + $params[3] = new ClamavVersionHandler(); return true; } return false; diff --git a/ClamavSettingsForm.inc.php b/ClamavSettingsForm.php similarity index 65% rename from ClamavSettingsForm.inc.php rename to ClamavSettingsForm.php index 3a84095..72556e0 100644 --- a/ClamavSettingsForm.inc.php +++ b/ClamavSettingsForm.php @@ -11,7 +11,16 @@ * * @brief Form for the site admin to modify Clam AV plugin settings */ -import('lib.pkp.classes.form.Form'); + +namespace APP\plugins\generic\clamav; + +use PKP\form\Form; +use PKP\form\validation\FormValidator; +use PKP\form\validation\FormValidatorPost; +use PKP\form\validation\FormValidatorCSRF; +use PKP\core\PKPApplication; +use APP\core\Application; +use APP\template\TemplateManager; class ClamavSettingsForm extends Form { @@ -29,16 +38,10 @@ class ClamavSettingsForm extends Form { function __construct($plugin, $contextId) { $this->_contextId = $contextId; $this->_plugin = $plugin; - - if (method_exists($plugin, 'getTemplateResource')) { - // OJS 3.1.2 and later - parent::__construct($plugin->getTemplateResource('settingsForm.tpl')); - } else { - // OJS 3.1.1 and earlier - parent::__construct($plugin->getTemplatePath() . 'settingsForm.tpl'); - } - - $this->addCheck(new FormValidator($this, 'clamavPath', FORM_VALIDATOR_OPTIONAL_VALUE, 'plugins.generic.clamav.manager.settings.clamavPathRequired')); + + parent::__construct($plugin->getTemplateResource('settingsForm.tpl')); + + $this->addCheck(new FormValidator($this, 'clamavPath', FormValidator::FORM_VALIDATOR_OPTIONAL_VALUE, 'plugins.generic.clamav.manager.settings.clamavPathRequired')); $this->addCheck(new FormValidatorPost($this)); $this->addCheck(new FormValidatorCSRF($this)); } @@ -51,18 +54,18 @@ function initData() { $request = Application::get()->getRequest(); $basePluginUrl = $request->getBaseUrl() . DIRECTORY_SEPARATOR . $plugin->getPluginPath() . DIRECTORY_SEPARATOR; - $this->setData('clamavPath', $plugin->getSetting(CONTEXT_SITE, 'clamavPath')); - $this->setData('clamavUseSocket', $plugin->getSetting(CONTEXT_SITE, 'clamavUseSocket')); - $this->setData('clamavSocketPath', $plugin->getSetting(CONTEXT_SITE, 'clamavSocketPath')); - $this->setData('unscannedFileOption', $plugin->getSetting(CONTEXT_SITE, 'allowUnscannedFiles')); - $this->setData('clamavSocketTimeout', $plugin->getSetting(CONTEXT_SITE, 'clamavSocketTimeout')); + $this->setData('clamavPath', $plugin->getSetting(PKPApplication::CONTEXT_SITE, 'clamavPath')); + $this->setData('clamavUseSocket', $plugin->getSetting(PKPApplication::CONTEXT_SITE, 'clamavUseSocket')); + $this->setData('clamavSocketPath', $plugin->getSetting(PKPApplication::CONTEXT_SITE, 'clamavSocketPath')); + $this->setData('unscannedFileOption', $plugin->getSetting(PKPApplication::CONTEXT_SITE, 'allowUnscannedFiles')); + $this->setData('clamavSocketTimeout', $plugin->getSetting(PKPApplication::CONTEXT_SITE, 'clamavSocketTimeout')); $this->setData('pluginJavascriptURL', $basePluginUrl . 'js' . DIRECTORY_SEPARATOR); $this->setData('pluginStylesheetURL', $basePluginUrl . 'css' . DIRECTORY_SEPARATOR); $this->setData('pluginLoadingImageURL', $basePluginUrl . 'images' . DIRECTORY_SEPARATOR . "spinner.gif"); $this->setData('pluginLoadingImageURL', $basePluginUrl . 'images' . DIRECTORY_SEPARATOR . "spinner.gif"); - $this->setData('pluginAjaxUrl', $request->getDispatcher()->url($request, ROUTE_PAGE, null, 'clamav', 'clamavVersion')); + $this->setData('pluginAjaxUrl', $request->getDispatcher()->url($request, PKPApplication::ROUTE_PAGE, null, 'clamav', 'clamavVersion')); $this->setData('baseUrl', $request->getBaseUrl()); } @@ -106,11 +109,11 @@ function execute(...$functionArgs) { $allowUnscannedFiles = $this->_plugin::UNSCANNED_DEFAULT; } - $this->_plugin->updateSetting(CONTEXT_SITE, 'clamavPath', $this->getData('clamavPath'), 'string'); - $this->_plugin->updateSetting(CONTEXT_SITE, 'clamavUseSocket', $this->getData('clamavUseSocket'), 'bool'); - $this->_plugin->updateSetting(CONTEXT_SITE, 'clamavSocketPath', $this->getData('clamavSocketPath'), 'string'); - $this->_plugin->updateSetting(CONTEXT_SITE, 'clamavSocketTimeout', $clamavSocketTimeout, 'int'); - $this->_plugin->updateSetting(CONTEXT_SITE, 'allowUnscannedFiles', $allowUnscannedFiles, 'string'); + $this->_plugin->updateSetting(PKPApplication::CONTEXT_SITE, 'clamavPath', $this->getData('clamavPath'), 'string'); + $this->_plugin->updateSetting(PKPApplication::CONTEXT_SITE, 'clamavUseSocket', $this->getData('clamavUseSocket'), 'bool'); + $this->_plugin->updateSetting(PKPApplication::CONTEXT_SITE, 'clamavSocketPath', $this->getData('clamavSocketPath'), 'string'); + $this->_plugin->updateSetting(PKPApplication::CONTEXT_SITE, 'clamavSocketTimeout', $clamavSocketTimeout, 'int'); + $this->_plugin->updateSetting(PKPApplication::CONTEXT_SITE, 'allowUnscannedFiles', $allowUnscannedFiles, 'string'); } /** diff --git a/ClamavVersionHandler.inc.php b/ClamavVersionHandler.php similarity index 85% rename from ClamavVersionHandler.inc.php rename to ClamavVersionHandler.php index 1274d21..b646386 100644 --- a/ClamavVersionHandler.inc.php +++ b/ClamavVersionHandler.php @@ -17,7 +17,14 @@ * @brief Handle router requests for the clam AV version for the clam AV plugin. */ -import('classes.handler.Handler'); + +namespace APP\plugins\generic\clamav; + +use PKP\core\JSONMessage; +use PKP\security\Validation; +use PKP\plugins\PluginRegistry; +use APP\template\TemplateManager; +use APP\handler\Handler; class ClamavVersionHandler extends Handler { /** diff --git a/css/clamav.css b/css/clamav.css index 1182864..e41f8aa 100644 --- a/css/clamav.css +++ b/css/clamav.css @@ -63,10 +63,6 @@ content: ""; } -#clamdSocketAdvanced div.full_description { - -} - #clamdSocketAdvancedSettings > div.pkp_helpers_quarter.inline { /* * sets this as a containing block, against which other absolutely- diff --git a/index.php b/index.php deleted file mode 100644 index 460cee3..0000000 --- a/index.php +++ /dev/null @@ -1,22 +0,0 @@ - diff --git a/locale/de_DE/locale.po b/locale/de/locale.po similarity index 100% rename from locale/de_DE/locale.po rename to locale/de/locale.po diff --git a/locale/en_US/locale.po b/locale/en/locale.po similarity index 100% rename from locale/en_US/locale.po rename to locale/en/locale.po diff --git a/locale/en_US/locale.xml b/locale/en/locale.xml similarity index 100% rename from locale/en_US/locale.xml rename to locale/en/locale.xml diff --git a/locale/es_ES/locale.po b/locale/es/locale.po similarity index 100% rename from locale/es_ES/locale.po rename to locale/es/locale.po diff --git a/locale/fr_FR/locale.po b/locale/fr/locale.po similarity index 100% rename from locale/fr_FR/locale.po rename to locale/fr/locale.po diff --git a/locale/it_IT/locale.po b/locale/it/locale.po similarity index 100% rename from locale/it_IT/locale.po rename to locale/it/locale.po diff --git a/locale/pt_PT/locale.po b/locale/pt/locale.po similarity index 100% rename from locale/pt_PT/locale.po rename to locale/pt/locale.po diff --git a/locale/ro_RO/locale.po b/locale/ro/locale.po similarity index 100% rename from locale/ro_RO/locale.po rename to locale/ro/locale.po diff --git a/version.xml b/version.xml index 2eabe37..3535ff4 100644 --- a/version.xml +++ b/version.xml @@ -12,7 +12,7 @@ clamav plugins.generic - 4.0.0.3 + 4.1.0.0 2024-06-10 1 ClamavPlugin