Merge branch 'develop' of github.com:MISP/MISP into feature-workflows

pull/8530/head
Sami Mokaddem 2022-05-11 13:03:03 +02:00
commit c477935752
No known key found for this signature in database
GPG Key ID: 164C473F627A06FA
45 changed files with 630 additions and 629 deletions

View File

@ -7,6 +7,7 @@ App::uses('JsonTool', 'Tools');
/**
* @property Server $Server
* @property Feed $Feed
* @property Warninglist $warninglist
* @property AdminSetting $AdminSetting
*/
class AdminShell extends AppShell
@ -19,6 +20,9 @@ class AdminShell extends AppShell
$parser->addSubcommand('updateJSON', array(
'help' => __('Update the JSON definitions of MISP.'),
));
$parser->addSubcommand('updateWarningLists', array(
'help' => __('Update the JSON definition of warninglists.'),
));
$parser->addSubcommand('setSetting', [
'help' => __('Set setting in PHP config file.'),
'parser' => [
@ -312,7 +316,6 @@ class AdminShell extends AppShell
public function updateWarningLists()
{
$this->ConfigLoad->execute();
$result = $this->Warninglist->update();
$success = count($result['success']);
$fails = count($result['fails']);

View File

@ -10,6 +10,7 @@ require_once 'AppShell.php';
* @property Job $Job
* @property Tag $Tag
* @property Server $Server
* @property Correlation $Correlation
*/
class EventShell extends AppShell
{
@ -44,6 +45,9 @@ class EventShell extends AppShell
$parser->addSubcommand('duplicateTags', [
'help' => __('Show duplicate tags'),
]);
$parser->addSubcommand('generateTopCorrelations', [
'help' => __('Generate top correlations'),
]);
$parser->addSubcommand('mergeTags', [
'help' => __('Merge tags'),
'parser' => [
@ -644,17 +648,20 @@ class EventShell extends AppShell
public function generateTopCorrelations()
{
$this->ConfigLoad->execute();
$jobId = $this->args[0];
$job = $this->Job->read(null, $jobId);
$job['Job']['progress'] = 1;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
$job['Job']['message'] = __('Generating top correlations list.');
$this->Job->save($job);
$result = $this->Correlation->generateTopCorrelations($jobId);
$job['Job']['progress'] = 100;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
$job['Job']['message'] = __('Job done.');
$this->Job->save($job);
$jobId = $this->args[0] ?? null;
if ($jobId) {
$job = $this->Job->read(null, $jobId);
$job['Job']['progress'] = 1;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
$job['Job']['message'] = __('Generating top correlations list.');
$this->Job->save($job);
}
$this->Correlation->generateTopCorrelations($jobId);
if ($jobId) {
$job['Job']['progress'] = 100;
$job['Job']['date_modified'] = date("Y-m-d H:i:s");
$job['Job']['message'] = __('Job done.');
$this->Job->save($job);
}
}
}

View File

@ -34,7 +34,7 @@ class AppController extends Controller
public $helpers = array('OrgImg', 'FontAwesome', 'UserName');
private $__queryVersion = '140';
private $__queryVersion = '141';
public $pyMispVersion = '2.4.157';
public $phpmin = '7.2';
public $phprec = '7.4';
@ -908,11 +908,11 @@ class AppController extends Controller
/**
* generic function to standardise on the collection of parameters. Accepts posted request objects, url params, named url params
* @param array $options
* @param $exception
* @param CakeResponse $exception
* @param array $data
* @return array|false|mixed
* @return array|false
*/
protected function _harvestParameters($options, &$exception = null, $data = array())
protected function _harvestParameters($options, &$exception = null, $data = [])
{
$request = $options['request'] ?? $this->request;
if ($request->is('post')) {
@ -958,14 +958,15 @@ class AppController extends Controller
}
}
}
foreach ($data as $k => $v) {
if (!is_array($data[$k])) {
$data[$k] = trim($data[$k]);
if (strpos($data[$k], '||')) {
$data[$k] = explode('||', $data[$k]);
foreach ($data as &$v) {
if (is_string($v)) {
$v = trim($v);
if (strpos($v, '||')) {
$v = explode('||', $v);
}
}
}
unset($v);
if (!empty($options['additional_delimiters'])) {
if (!is_array($options['additional_delimiters'])) {
$options['additional_delimiters'] = array($options['additional_delimiters']);
@ -975,6 +976,7 @@ class AppController extends Controller
foreach ($options['additional_delimiters'] as $delim) {
if (strpos($v, $delim) !== false) {
$found = true;
break;
}
}
if ($found) {

View File

@ -63,6 +63,10 @@ class AttributesController extends AppController
$this->params->addParams(array('pass' => array($id))); // FIXME find better way to change id variable if uuid is found. params->url and params->here is not modified accordingly now
}
}
if ($this->request->action === 'viewPicture') {
$this->Security->doNotGenerateToken = true;
}
}
public function index()
@ -155,15 +159,15 @@ class AttributesController extends AppController
if (!isset($attributes[0])) {
$attributes = array(0 => $attributes);
}
$fails = array();
$fails = [];
$successes = 0;
$attributeCount = count($attributes);
$inserted_ids = array();
$insertedIds = array();
foreach ($attributes as $k => $attribute) {
$validationErrors = array();
$this->Attribute->captureAttribute($attribute, $event['Event']['id'], $this->Auth->user(), false, false, $event, $validationErrors, $this->params['named']);
if (empty($validationErrors)) {
$inserted_ids[] = $this->Attribute->id;
$insertedIds[] = $this->Attribute->id;
$successes++;
} else {
$fails["attribute_" . $k] = $validationErrors;
@ -176,7 +180,7 @@ class AttributesController extends AppController
if ($successes !== 0) {
$attributes = $this->Attribute->find('all', array(
'recursive' => -1,
'conditions' => array('Attribute.id' => $inserted_ids),
'conditions' => array('Attribute.id' => $insertedIds),
'contain' => array(
'AttributeTag' => array(
'Tag' => array('fields' => array('Tag.id', 'Tag.name', 'Tag.colour', 'Tag.numerical_value'))
@ -201,7 +205,7 @@ class AttributesController extends AppController
}
return $this->RestResponse->viewData($attributes, $this->response->type(), $fails);
} else {
if ($attributeCount == 1) {
if ($attributeCount === 1) {
return $this->RestResponse->saveFailResponse('Attributes', 'add', false, $fails["attribute_0"], $this->response->type());
} else {
return $this->RestResponse->saveFailResponse('Attributes', 'add', false, $fails, $this->response->type());
@ -209,58 +213,52 @@ class AttributesController extends AppController
}
} else {
if (empty($fails)) {
$message = 'Attributes saved.';
$message = __('Attributes saved.');
} else {
if ($attributeCount > 1) {
$failKeys = array_keys($fails);
foreach ($failKeys as $k => $v) {
$v = explode('_', $v);
$failKeys[$k] = intval($v[1]);
}
$failed = 1;
$message = sprintf('Attributes saved, however, %s attributes could not be saved. Click %s for more info', count($fails), '$flashErrorMessage');
} else {
$failed = 1;
$message = 'Attribute could not be saved.';
}
}
if (!empty($failKeys)) {
$flashErrorMessage = array();
$original_values = trim($this->request->data['Attribute']['value']);
$original_values = explode("\n", $original_values);
foreach ($original_values as $k => $original_value) {
$original_value = trim($original_value);
if (in_array($k, $failKeys)) {
$reason = '';
foreach ($fails["attribute_" . $k] as $failKey => $failData) {
$reason = $failKey . ': ' . $failData[0];
$flashErrorMessage = [];
foreach ($attributes as $k => $attribute) {
if (isset($fails["attribute_$k"])) {
$reason = '';
foreach ($fails["attribute_" . $k] as $failKey => $failData) {
$reason = $failKey . ': ' . $failData[0];
}
$flashErrorMessage[] = '<span class="red bold">' . h($attribute["value"]) . '</span> (' . h($reason) . ')';
} else {
$flashErrorMessage[] = '<span class="green bold">' . h($attribute["value"]) . '</span>';
}
$flashErrorMessage[] = '<span class="red bold">' . h($original_value) . '</span> (' . h($reason) . ')';
}
$flashErrorMessage = implode('<br>', $flashErrorMessage);
$this->Session->write('flashErrorMessage', $flashErrorMessage);
if ($successes === 0) {
$message = __('Attributes could not be saved. Click $flashErrorMessage for more info');
} else {
$flashErrorMessage[] = '<span class="green bold">' . h($original_value) . '</span>';
$message = __('Attributes saved, however, %s attributes could not be saved. Click $flashErrorMessage for more info', count($fails));
}
} else {
$message = __('Attribute could not be saved.');
}
}
if ($this->request->is('ajax')) {
if (!empty($successes)) {
$data = ['saved' => true, 'success' => $message];
} else {
$message = $attributeCount > 1 ? $message : $this->Attribute->validationErrors;
$data = ['saved' => false, 'errors' => $message];
if (!empty($flashErrorMessage)) {
$data['full_errors'] = $flashErrorMessage;
}
}
$flashErrorMessage = implode('<br />', $flashErrorMessage);
$this->Session->write('flashErrorMessage', $flashErrorMessage);
return $this->RestResponse->viewData($data, 'json');
}
if (empty($failed)) {
if (empty($fails)) {
$this->Flash->success($message);
} else {
$this->Flash->error($message);
}
if ($this->request->is('ajax')) {
$this->autoRender = false;
$this->layout = false;
$errors = ($attributeCount > 1) ? $message : $this->Attribute->validationErrors;
if (!empty($successes)) {
return new CakeResponse(array('body'=> json_encode(array('saved' => true, 'success' => $message)),'status' => 200, 'type' => 'json'));
} else {
return new CakeResponse(array('body'=> json_encode(array('saved' => false, 'errors' => $errors)),'status' => 200, 'type' => 'json'));
}
} else {
if ($successes > 0) {
$this->redirect(array('controller' => 'events', 'action' => 'view', $event['Event']['id']));
}
if ($successes > 0) {
$this->redirect(array('controller' => 'events', 'action' => 'view', $event['Event']['id']));
}
}
}
@ -272,10 +270,6 @@ class AttributesController extends AppController
$categories = array_keys($this->Attribute->categoryDefinitions);
$categories = $this->_arrayToValuesIndexArray($categories);
$this->set('categories', $categories);
$this->loadModel('Noticelist');
$notice_list_triggers = $this->Noticelist->getTriggerData();
$this->set('notice_list_triggers', json_encode($notice_list_triggers));
$this->__common();
$this->set('title_for_layout', __('Add attribute'));
$this->set('typeDefinitions', $this->Attribute->typeDefinitions);
@ -485,6 +479,11 @@ class AttributesController extends AppController
$this->set('distributionLevels', $distributionData['levels']);
$this->set('initialDistribution', $distributionData['initial']);
$this->set('fieldDesc', $this->__fieldDesc());
$this->set('nonCorrelatingTypes', Attribute::NON_CORRELATING_TYPES);
$this->loadModel('Noticelist');
$notice_list_triggers = $this->Noticelist->getTriggerData();
$this->set('notice_list_triggers', json_encode($notice_list_triggers));
}
/**
@ -872,9 +871,6 @@ class AttributesController extends AppController
$this->set('categories', $categories);
$this->set('categoryDefinitions', $categoryDefinitions);
$this->set('action', $this->action);
$this->loadModel('Noticelist');
$notice_list_triggers = $this->Noticelist->getTriggerData();
$this->set('notice_list_triggers', json_encode($notice_list_triggers));
$this->render('add');
}

View File

@ -10,27 +10,29 @@ class IndexFilterComponent extends Component
public $Controller;
public $isRest = null;
public function initialize(Controller $controller) {
public function initialize(Controller $controller)
{
$this->Controller = $controller;
}
// generic function to standardise on the collection of parameters. Accepts posted request objects, url params, named url params
public function harvestParameters($paramArray, &$exception = array())
public function harvestParameters($paramArray, &$exception = [])
{
$data = array();
if (!empty($this->Controller->request->is('post'))) {
if (empty($this->Controller->request->data)) {
$request = $this->Controller->request;
$data = [];
if ($request->is('post')) {
if (empty($request->data)) {
$exception = $this->Controller->RestResponse->throwException(
400,
__('Either specify the search terms in the url, or POST a json with the filter parameters.'),
'/' . $this->Controller->request->params['controller'] . '/' . $this->Controller->action
'/' . $request->params['controller'] . '/' . $this->Controller->action
);
return false;
} else {
if (isset($this->Controller->request->data['request'])) {
$data = $this->Controller->request->data['request'];
if (isset($request->data['request'])) {
$data = $request->data['request'];
} else {
$data = $this->Controller->request->data;
$data = $request->data;
}
}
}
@ -43,19 +45,20 @@ class IndexFilterComponent extends Component
$data[$p] = $options['ordered_url_params'][$p];
$data[$p] = str_replace(';', ':', $data[$p]);
}
if (isset($this->Controller->params['named'][$p])) {
$data[$p] = str_replace(';', ':', $this->Controller->params['named'][$p]);
if (isset($request->params['named'][$p])) {
$data[$p] = str_replace(';', ':', $request->params['named'][$p]);
}
}
}
foreach ($data as $k => $v) {
if (!is_array($data[$k])) {
$data[$k] = trim($data[$k]);
if (strpos($data[$k], '||')) {
$data[$k] = explode('||', $data[$k]);
foreach ($data as &$v) {
if (is_string($v)) {
$v = trim($v);
if (strpos($v, '||')) {
$v = explode('||', $v);
}
}
}
unset($v);
if (!empty($options['additional_delimiters'])) {
if (!is_array($options['additional_delimiters'])) {
$options['additional_delimiters'] = array($options['additional_delimiters']);
@ -65,6 +68,7 @@ class IndexFilterComponent extends Component
foreach ($options['additional_delimiters'] as $delim) {
if (strpos($v, $delim) !== false) {
$found = true;
break;
}
}
if ($found) {

View File

@ -479,39 +479,70 @@ class RestResponseComponent extends Component
return [];
}
public function saveFailResponse($controller, $action, $id = false, $validationErrors, $format = false, $data = null)
/**
* @param string $controller
* @param string $action
* @param int|false $id
* @param mixed $validationErrors
* @param string|false $format
* @param mixed $data
* @return CakeResponse
* @throws Exception
*/
public function saveFailResponse($controller, $action, $id, $validationErrors, $format = false, $data = null)
{
$response = array();
$action = $this->__dissectAdminRouting($action);
$stringifiedAction = $action['action'];
if (isset(self::CONVERT_ACTION_TO_MESSAGE[$controller][$action['action']])) {
$stringifiedAction = self::CONVERT_ACTION_TO_MESSAGE[$controller][$action['action']];
if (isset(self::CONVERT_ACTION_TO_MESSAGE[$controller][$stringifiedAction])) {
$stringifiedAction = self::CONVERT_ACTION_TO_MESSAGE[$controller][$stringifiedAction];
}
$response['saved'] = false;
$response['name'] = 'Could not ' . $stringifiedAction . ' ' . Inflector::singularize($controller);
$response['message'] = $response['name'];
$message = 'Could not ' . $stringifiedAction . ' ' . Inflector::singularize($controller);
$response = [
'saved' => false,
'name' => $message,
'message' => $message,
'url' => $this->__generateURL($action, $controller, $id),
'errors' => $validationErrors,
];
if ($data !== null) {
$response['data'] = $data;
}
$response['url'] = $this->__generateURL($action, $controller, $id);
$response['errors'] = $validationErrors;
if ($id) {
$response['id'] = $id;
}
return $this->__sendResponse($response, 403, $format);
}
/**
* @param string $controller
* @param string $action
* @param int|false $id
* @param string|false $format
* @param string|false $message
* @param mixed $data
* @return CakeResponse
* @throws Exception
*/
public function saveSuccessResponse($controller, $action, $id = false, $format = false, $message = false, $data = null)
{
$action = $this->__dissectAdminRouting($action);
if (!$message) {
$message = Inflector::singularize($controller) . ' ' . $action['action'] . ((substr($action['action'], -1) == 'e') ? 'd' : 'ed');
$message = Inflector::singularize($controller) . ' ' . $action['action'] . ((substr($action['action'], -1) === 'e') ? 'd' : 'ed');
}
$response['saved'] = true;
$response['success'] = true;
$response['name'] = $message;
$response['message'] = $response['name'];
$response = [
'saved' => true,
'success' => true,
'name' => $message,
'message' => $message,
'url' => $this->__generateURL($action, $controller, $id),
];
if ($data !== null) {
$response['data'] = $data;
}
$response['url'] = $this->__generateURL($action, $controller, $id);
if ($id) {
$response['id'] = $id;
}
return $this->__sendResponse($response, 200, $format);
}
@ -527,7 +558,7 @@ class RestResponseComponent extends Component
*/
private function __sendResponse($response, $code, $format = false, $raw = false, $download = false, $headers = array())
{
$format = strtolower($format);
$format = !empty($format) ? strtolower($format) : 'json';
if ($format === 'application/xml' || $format === 'xml') {
if (!$raw) {
if (isset($response[0])) {
@ -550,11 +581,7 @@ class RestResponseComponent extends Component
} elseif ($format === 'csv' || $format === 'text/csv') {
$type = 'csv';
} else {
if (empty($format)) {
$type = 'json';
} else {
$type = $format;
}
$type = $format;
$dumpSql = !empty($this->Controller->sql_dump) && Configure::read('debug') > 1;
if (!$raw) {
if (is_string($response)) {
@ -601,6 +628,13 @@ class RestResponseComponent extends Component
}
if ($response instanceof TmpFileTool) {
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$etag = '"' . $response->hash('sha1') . '"';
if ($_SERVER['HTTP_IF_NONE_MATCH'] === $etag) {
return new CakeResponse(['status' => 304]);
}
$headers['ETag'] = $etag;
}
if ($this->signContents) {
$this->CryptographicKey = ClassRegistry::init('CryptographicKey');
$data = $response->intoString();
@ -612,7 +646,16 @@ class RestResponseComponent extends Component
$cakeResponse->file($response);
}
} else {
$cakeResponse = new CakeResponse(array('body' => $response, 'status' => $code, 'type' => $type));
// Check if resource was changed when `If-None-Match` header is send and return 304 Not Modified
if (isset($_SERVER['HTTP_IF_NONE_MATCH'])) {
$etag = '"' . sha1($response) . '"';
if ($_SERVER['HTTP_IF_NONE_MATCH'] === $etag) {
return new CakeResponse(['status' => 304]);
}
// Generate etag just when HTTP_IF_NONE_MATCH is set
$headers['ETag'] = $etag;
}
$cakeResponse = new CakeResponse(['body' => $response, 'status' => $code, 'type' => $type]);
if ($this->signContents) {
$headers['x-pgp-signature'] = base64_encode($this->CryptographicKey->signWithInstanceKey($response));
}

View File

@ -122,7 +122,7 @@ class CorrelationExclusionsController extends AppController
} else {
$this->set('title', __('Clean up correlations'));
$this->set('question', __('Execute the cleaning of all correlations that are at odds with the exclusion rules? This will delete all matching correlations.'));
$this->set('actionName', 'clean');
$this->set('actionName', __('Clean'));
$this->layout = false;
$this->render('/genericTemplates/confirm');
}

View File

@ -12,17 +12,20 @@ class DashboardsController extends AppController
public function beforeFilter()
{
parent::beforeFilter();
$this->Security->unlockedActions = array_merge(array('renderWidget', 'getForm'), $this->Security->unlockedActions);
$this->Security->unlockedActions[] = 'renderWidget';
$this->Security->unlockedActions[] = 'getForm';
if ($this->request->action === 'renderWidget') {
$this->Security->doNotGenerateToken = true;
}
}
public $paginate = array(
'limit' => 60,
'maxLimit' => 9999
'limit' => 60,
'maxLimit' => 9999
);
public function index($template_id = false)
{
$this->loadModel('UserSetting');
if (empty($template_id)) {
$params = array(
'conditions' => array(
@ -30,7 +33,7 @@ class DashboardsController extends AppController
'UserSetting.setting' => 'dashboard'
)
);
$userSettings = $this->UserSetting->find('first', $params);
$userSettings = $this->User->UserSetting->find('first', $params);
} else {
$dashboardTemplate = $this->Dashboard->getDashboardTemplate($this->Auth->user(), $template_id);
if (empty($dashboardTemplate)) {
@ -80,7 +83,6 @@ class DashboardsController extends AppController
// continue, we just don't load the widget
}
}
$this->layout = 'dashboard';
$this->set('widgets', $widgets);
}
@ -112,22 +114,20 @@ class DashboardsController extends AppController
public function updateSettings()
{
if ($this->request->is('post')) {
$this->UserSetting = ClassRegistry::init('UserSetting');
if (!isset($this->request->data['Dashboard']['value'])) {
throw new InvalidArgumentException(__('No setting data found.'));
}
$data = array(
'UserSetting' => array(
'user_id' => $this->Auth->user('id'),
'setting' => 'dashboard',
'value' => $this->request->data['Dashboard']['value']
)
);
$result = $this->UserSetting->setSetting($this->Auth->user(), $data);
$result = $this->User->UserSetting->setSetting($this->Auth->user(), $data);
if ($result) {
return $this->RestResponse->saveSuccessResponse('Dashboard', 'updateSettings', false, false, __('Settings updated.'));
}
return $this->RestResponse->saveFailResponse('Dashboard', 'updateSettings', false, $this->UserSetting->validationErrors, $this->response->type());
return $this->RestResponse->saveFailResponse('Dashboard', 'updateSettings', false, $this->User->UserSetting->validationErrors, $this->response->type());
}
}
@ -155,7 +155,7 @@ class DashboardsController extends AppController
}
$user = $this->Auth->user();
@session_write_close(); // allow concurrent AJAX requests (session hold lock by default)
@session_abort(); // allow concurrent AJAX requests (session hold lock by default)
if (empty($this->request->data['data'])) {
$this->request->data = array('data' => $this->request->data);
@ -237,7 +237,6 @@ class DashboardsController extends AppController
public function saveTemplate($update = false)
{
$this->loadModel('UserSetting');
if (!empty($update)) {
$conditions = array('Dashboard.id' => $update);
if (Validation::uuid($update)) {
@ -260,7 +259,7 @@ class DashboardsController extends AppController
}
$data = $this->request->data;
if (empty($update)) { // save the template stored in user setting and make it persistent
$data['value'] = $this->UserSetting->getSetting($this->Auth->user('id'), 'dashboard');
$data['value'] = $this->User->UserSetting->getSetting($this->Auth->user('id'), 'dashboard');
}
$result = $this->Dashboard->saveDashboardTemplate($this->Auth->user(), $data, $update);
if ($this->_isRest()) {
@ -279,7 +278,6 @@ class DashboardsController extends AppController
} else {
$this->layout = false;
}
$this->loadModel('User');
$permFlags = array(0 => __('Unrestricted'));
foreach ($this->User->Role->permFlags as $perm_flag => $perm_data) {
$permFlags[$perm_flag] = $perm_data['text'];

View File

@ -631,21 +631,19 @@ class UsersController extends AppController
if (isset($this->request->data['User']['password'])) {
$this->request->data['User']['confirm_password'] = $this->request->data['User']['password'];
}
$default_publish_alert = Configure::check('MISP.default_publish_alert') ? Configure::read('MISP.default_publish_alert') : 0;
$defaults = array(
'external_auth_required' => 0,
'external_auth_key' => '',
'server_id' => 0,
'gpgkey' => '',
'certif_public' => '',
'autoalert' => $default_publish_alert,
'contactalert' => 0,
'disabled' => 0,
'newsread' => 0,
'change_pw' => 1,
'authkey' => (new RandomTool())->random_str(true, 40),
'termsaccepted' => 0,
'org_id' => $this->Auth->user('org_id')
'external_auth_required' => 0,
'external_auth_key' => '',
'server_id' => 0,
'gpgkey' => '',
'certif_public' => '',
'autoalert' => $this->User->defaultPublishAlert(),
'contactalert' => 0,
'disabled' => 0,
'newsread' => 0,
'change_pw' => 1,
'termsaccepted' => 0,
'org_id' => $this->Auth->user('org_id'),
);
foreach ($defaults as $key => $value) {
if (!isset($this->request->data['User'][$key])) {
@ -654,7 +652,6 @@ class UsersController extends AppController
}
}
$this->request->data['User']['date_created'] = time();
$this->request->data['User']['date_modified'] = time();
if (!array_key_exists($this->request->data['User']['role_id'], $syncRoles)) {
$this->request->data['User']['server_id'] = 0;
}
@ -1491,17 +1488,36 @@ class UsersController extends AppController
$this->Flash->success(__('You accepted the Terms and Conditions.'));
$this->redirect(array('action' => 'routeafterlogin'));
}
$termsFile = Configure::read('MISP.terms_file');
if (empty($termsFile)) {
throw new NotFoundException(__("MISP Terms and Conditions are not defined"));
}
$termsDownload = (bool)Configure::read('MISP.terms_download');
if (!$termsDownload) {
$termsFilePath = APP . 'files' . DS . 'terms' . DS . basename($termsFile);
try {
$termsContent = FileAccessTool::readFromFile($termsFilePath);
} catch (Exception $e) {
$termsContent = false;
}
$this->set("termsContent", $termsContent);
}
$this->set("termsDownload", $termsDownload);
$this->set('termsaccepted', $this->Auth->user('termsaccepted'));
}
public function downloadTerms()
{
if (!Configure::read('MISP.terms_file')) {
$termsFile = APP ."View/Users/terms";
} else {
$termsFile = APP . 'files' . DS . 'terms' . DS . Configure::read('MISP.terms_file');
$termsFile = Configure::read('MISP.terms_file');
if (empty($termsFile)) {
throw new NotFoundException(__("MISP Terms and Conditions are not defined"));
}
$this->response->file($termsFile, array('download' => true, 'name' => Configure::read('MISP.terms_file')));
$termsFilePath = APP . 'files' . DS . 'terms' . DS . basename($termsFile);
$this->response->file($termsFilePath, ['download' => true, 'name' => $termsFile]);
return $this->response;
}

View File

@ -360,9 +360,7 @@ class WarninglistsController extends AppController
public function import()
{
if (!$this->request->is('post')) {
throw new MethodNotAllowedException(__('This function only accepts POST requests.'));
}
$this->request->allowMethod(['post']);
if (empty($this->request->data)) {
throw new BadRequestException(__('No valid data received.'));
@ -378,11 +376,11 @@ class WarninglistsController extends AppController
throw new BadRequestException(__('No valid data received: `list` field is not array'));
}
$id = $this->Warninglist->import($this->request->data);
if (is_int($id)) {
try {
$id = $this->Warninglist->import($this->request->data);
return $this->RestResponse->saveSuccessResponse('Warninglist', 'import', $id, false, __('Warninglist imported'));
} else {
return $this->RestResponse->saveFailResponse('Warninglist', 'import', false, $id);
} catch (Exception $e) {
return $this->RestResponse->saveFailResponse('Warninglist', 'import', false, $e->getMessage());
}
}

View File

@ -460,7 +460,8 @@ class AttachmentTool
*/
public function attachmentDirIsS3()
{
return substr(Configure::read('MISP.attachments_dir'), 0, 2) === "s3";
$attachmentsDir = Configure::read('MISP.attachments_dir');
return $attachmentsDir && substr($attachmentsDir, 0, 2) === "s3";
}
/**

View File

@ -192,6 +192,19 @@ class TmpFileTool
return fstat($this->tmpfile)['size'];
}
/**
* @param string $algo
* @return string
* @throws Exception
*/
public function hash($algo)
{
$this->rewind();
$hash = hash_init($algo);
hash_update_stream($hash, $this->tmpfile);
return hash_final($hash);
}
/**
* @return string
* @throws Exception

View File

@ -90,6 +90,7 @@ class AppModel extends Model
69 => false, 70 => false, 71 => true, 72 => true, 73 => false, 74 => false,
75 => false, 76 => true, 77 => false, 78 => false, 79 => false, 80 => false,
81 => false, 82 => false, 83 => false, 84 => false, 85 => false, 86 => false,
87,
);
public $advanced_updates_description = array(
@ -1685,6 +1686,9 @@ class AppModel extends Model
$this->__addIndex('cryptographic_keys', 'fingerprint');
break;
case 86:
$this->__addIndex('attributes', 'timestamp');
break;
case 87:
$sqlArray[] = "CREATE TABLE IF NOT EXISTS `workflows` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uuid` varchar(40) COLLATE utf8_bin NOT NULL ,
@ -2568,7 +2572,7 @@ class AppModel extends Model
$pass = Configure::read('MISP.redis_password');
$redis = new Redis();
if (!$redis->connect($host, $port)) {
if (!$redis->connect($host, (int) $port)) {
throw new Exception("Could not connect to Redis: {$redis->getLastError()}");
}
if (!empty($pass)) {

View File

@ -624,11 +624,11 @@ class Correlation extends AppModel
} catch (Exception $e) {
throw new NotFoundException(__('No redis connection found.'));
}
$max_id = $this->find('first', [
$maxId = $this->find('first', [
'fields' => ['MAX(id) AS max_id'],
'recursive' => -1
'recursive' => -1,
]);
if (empty($max_id)) {
if (empty($maxId)) {
return false;
}
if ($jobId) {
@ -643,19 +643,20 @@ class Correlation extends AppModel
$jobId = false;
}
}
$max_id = $max_id[0]['max_id'];
$maxId = $maxId[0]['max_id'];
$redis->del(self::CACHE_NAME);
$redis->set(self::CACHE_AGE, time());
$chunk_size = 1000000;
$max = ceil($max_id / $chunk_size);
for ($i = 0; $i < $max; $i++) {
$chunkSize = 1000000;
$maxPage = ceil($maxId / $chunkSize);
for ($page = 0; $page < $maxPage; $page++) {
$correlations = $this->find('column', [
'fields' => ['value'],
'conditions' => [
'id >' => $i * $chunk_size,
'id <=' => (($i + 1) * $chunk_size)
]
'id >' => $page * $chunkSize,
'id <=' => ($page + 1) * $chunkSize
],
'callbacks' => false, // when callbacks are enabled, memory is leaked
]);
$newElements = count($correlations);
$correlations = array_count_values($correlations);
@ -665,8 +666,7 @@ class Correlation extends AppModel
}
$pipeline->exec();
if ($jobId) {
$this->Job->saveProgress($jobId, __('Generating top correlations. Processed %s IDs.', ($i * $chunk_size) + $newElements), floor(100 * $i / $max));
return $jobId;
$this->Job->saveProgress($jobId, __('Generating top correlations. Processed %s IDs.', ($page * $chunkSize) + $newElements), floor(100 * $page / $maxPage));
}
}
return true;

View File

@ -1,6 +1,5 @@
<?php
App::uses('AppModel', 'Model');
App::uses('RandomTool', 'Tools');
class CorrelationExclusion extends AppModel
{

View File

@ -359,7 +359,14 @@ class MispObject extends AppModel
}
}
public function checkForDuplicateObjects($object, $eventId, &$duplicatedObjectID, &$duplicateObjectUuid)
/**
* @param array $object
* @param int $eventId
* @param int $duplicatedObjectId
* @param string $duplicateObjectUuid
* @return bool
*/
private function checkForDuplicateObjects($object, $eventId, &$duplicatedObjectId, &$duplicateObjectUuid)
{
$newObjectAttributes = array();
if (isset($object['Object']['Attribute'])) {
@ -383,7 +390,7 @@ class MispObject extends AppModel
foreach ($this->__objectDuplicationCheckCache['new'][$object['Object']['template_uuid']] as $previousNewObject) {
if ($newObjectAttributeCount === count($previousNewObject)) {
if (empty(array_diff($previousNewObject, $newObjectAttributes))) {
$duplicatedObjectID = $previousNewObject['Object']['id'];
$duplicatedObjectId = $previousNewObject['Object']['id'];
$duplicateObjectUuid = $previousNewObject['Object']['uuid'];
return true;
}
@ -412,7 +419,7 @@ class MispObject extends AppModel
$temp[] = sha1($existingAttribute['object_relation'] . $existingAttribute['category'] . $existingAttribute['type'] . $existingAttribute['value'], true);
}
if (empty(array_diff($temp, $newObjectAttributes))) {
$duplicatedObjectID = $existingObject['Object']['id'];
$duplicatedObjectId = $existingObject['Object']['id'];
return true;
}
}
@ -442,11 +449,11 @@ class MispObject extends AppModel
}
$object['Object']['event_id'] = $eventId;
if ($breakOnDuplicate) {
$duplicatedObjectID = null;
$duplicatedObjectId = null;
$duplicateObjectUuid = null;
$duplicate = $this->checkForDuplicateObjects($object, $eventId, $duplicatedObjectID, $dupicateObjectUuid);
$duplicate = $this->checkForDuplicateObjects($object, $eventId, $duplicatedObjectId, $duplicateObjectUuid);
if ($duplicate) {
return array('value' => array(__('Duplicate object found (id: %s, uuid: %s). Since breakOnDuplicate is set the object will not be added.', $duplicatedObjectID, $dupicateObjectUuid)));
return array('value' => array(__('Duplicate object found (id: %s, uuid: %s). Since breakOnDuplicate is set the object will not be added.', $duplicatedObjectId, $duplicateObjectUuid)));
}
}
$this->create();
@ -971,12 +978,12 @@ class MispObject extends AppModel
$object = array('Object' => $object);
}
if (!empty($object['Object']['breakOnDuplicate']) || $breakOnDuplicate) {
$duplicatedObjectID = null;
$duplicatedObjectId = null;
$duplicateObjectUuid = null;
$duplicate = $this->checkForDuplicateObjects($object, $eventId, $duplicatedObjectID, $duplicateObjectUuid);
$duplicate = $this->checkForDuplicateObjects($object, $eventId, $duplicatedObjectId, $duplicateObjectUuid);
if ($duplicate) {
$this->loadLog()->createLogEntry($user, 'add', 'Object', 0,
__('Object dropped due to it being a duplicate (ID: %s, UUID: %s) and breakOnDuplicate being requested for Event %s', $duplicatedObjectID, $dupicateObjectUuid, $eventId),
__('Object dropped due to it being a duplicate (ID: %s, UUID: %s) and breakOnDuplicate being requested for Event %s', $duplicatedObjectId, $duplicateObjectUuid, $eventId),
'Duplicate object found.'
);
return true;

View File

@ -3407,18 +3407,18 @@ class Server extends AppModel
$currentUser = ProcessTool::whoami();
$procAccessible = file_exists('/proc');
foreach ($workers as $pid => $worker) {
$entry = ($worker['type'] == 'regular') ? $worker['queue'] : $worker['type'];
$correct_user = ($currentUser === $worker['user']);
if (!is_numeric($pid)) {
throw new MethodNotAllowedException('Non numeric PID found.');
}
$entry = $worker['type'] === 'regular' ? $worker['queue'] : $worker['type'];
$correctUser = ($currentUser === $worker['user']);
if ($procAccessible) {
$alive = $correct_user ? (file_exists('/proc/' . addslashes($pid))) : false;
$alive = $correctUser && file_exists("/proc/$pid");
} else {
$alive = 'N/A';
}
$ok = true;
if (!$alive || !$correct_user) {
if (!$alive || !$correctUser) {
$ok = false;
$workerIssueCount++;
}
@ -3426,19 +3426,19 @@ class Server extends AppModel
'pid' => $pid,
'user' => $worker['user'],
'alive' => $alive,
'correct_user' => $correct_user,
'correct_user' => $correctUser,
'ok' => $ok
);
}
foreach ($worker_array as $k => $queue) {
if (isset($worker_array[$k]['workers'])) {
foreach($worker_array[$k]['workers'] as $worker) {
if (isset($queue['workers'])) {
foreach ($queue['workers'] as $worker) {
if ($worker['ok']) {
$worker_array[$k]['ok'] = true; // If at least one worker is up, the queue can be considered working
}
}
}
if ($k != 'scheduler') {
if ($k !== 'scheduler') {
$worker_array[$k]['jobCount'] = $this->getBackgroundJobsTool()->getQueueSize($k);
}
if (!isset($queue['workers'])) {

View File

@ -57,7 +57,6 @@ class User extends AppModel
//'on' => 'create', // Limit validation to 'create' or 'update' operations
),
),
'org_id' => array(
'valueNotEmpty' => array(
'rule' => array('valueNotEmpty'),
@ -227,6 +226,9 @@ class User extends AppModel
'Containable'
);
/** @var CryptGpgExtended|null|false */
private $gpg;
public function __construct($id = false, $table = null, $ds = null)
{
parent::__construct($id, $table, $ds);
@ -239,28 +241,23 @@ class User extends AppModel
}
}
/** @var CryptGpgExtended|null|false */
private $gpg;
public function beforeValidate($options = array())
{
if (!isset($this->data['User']['id'])) {
if ((isset($this->data['User']['enable_password']) && (!$this->data['User']['enable_password'])) || (empty($this->data['User']['password']) && empty($this->data['User']['confirm_password']))) {
$this->data['User']['password'] = $this->generateRandomPassword();
$this->data['User']['confirm_password'] = $this->data['User']['password'];
$user = &$this->data['User'];
if (!isset($user['id'])) {
if ((isset($user['enable_password']) && !$user['enable_password']) || (empty($user['password']) && empty($user['confirm_password']))) {
$user['password'] = $this->generateRandomPassword();
$user['confirm_password'] = $user['password'];
}
}
if (!isset($this->data['User']['certif_public']) || empty($this->data['User']['certif_public'])) {
$this->data['User']['certif_public'] = '';
if (empty($user['certif_public'])) {
$user['certif_public'] = '';
}
if (!isset($this->data['User']['authkey']) || empty($this->data['User']['authkey'])) {
$this->data['User']['authkey'] = $this->generateAuthKey();
if (empty($user['authkey'])) {
$user['authkey'] = $this->generateAuthKey();
}
if (!isset($this->data['User']['nids_sid']) || empty($this->data['User']['nids_sid'])) {
$this->data['User']['nids_sid'] = mt_rand(1000000, 9999999);
}
if (isset($this->data['User']['newsread']) && $this->data['User']['newsread'] === null) {
$this->data['User']['newsread'] = 0;
if (empty($user['nids_sid'])) {
$user['nids_sid'] = mt_rand(1000000, 9999999);
}
return true;
}
@ -414,21 +411,14 @@ class User extends AppModel
public function identicalFieldValues($field = array(), $compareField = null)
{
foreach ($field as $key => $value) {
$v1 = $value;
$v2 = $this->data[$this->name][$compareField];
if ($v1 !== $v2) {
return false;
} else {
continue;
}
}
return true;
$v1 = array_values($field)[0];
$v2 = $this->data[$this->name][$compareField];
return $v1 === $v2;
}
public function generateAuthKey()
{
return (new RandomTool())->random_str(true, 40);
return RandomTool::random_str(true, 40);
}
/**
@ -436,19 +426,19 @@ class User extends AppModel
*
* @param int $passwordLength
* @return string
* @throws Exception
*/
public function generateRandomPassword($passwordLength = 40)
{
// makes sure, the password policy isn't undermined by setting a manual passwordLength
$policyPasswordLength = Configure::read('Security.password_policy_length') ? Configure::read('Security.password_policy_length') : false;
$policyPasswordLength = Configure::read('Security.password_policy_length') ?: false;
if (is_int($policyPasswordLength) && $policyPasswordLength > $passwordLength) {
$passwordLength = $policyPasswordLength;
}
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-+=!@#$%^&*()<>/?';
return (new RandomTool())->random_str(true, $passwordLength, $characters);
return RandomTool::random_str(true, $passwordLength, $characters);
}
public function checkAndCorrectPgps()
{
$fails = array();
@ -462,15 +452,6 @@ class User extends AppModel
return $fails;
}
public function getOrgs()
{
$orgs = $this->Organisation->find('list', array(
'recursive' => -1,
'fields' => array('name'),
));
return $orgs;
}
public function getOrgMemberCount($org)
{
return $this->find('count', array(
@ -1303,20 +1284,21 @@ class User extends AppModel
return $data;
}
public function registerUser($added_by, $registration, $org_id, $role_id) {
public function registerUser($added_by, $registration, $org_id, $role_id)
{
$user = array(
'email' => $registration['data']['email'],
'gpgkey' => empty($registration['data']['pgp']) ? '' : $registration['data']['pgp'],
'disabled' => 0,
'newsread' => 0,
'change_pw' => 1,
'authkey' => $this->generateAuthKey(),
'termsaccepted' => 0,
'org_id' => $org_id,
'role_id' => $role_id,
'invited_by' => $added_by['id'],
'contactalert' => 1,
'autoalert' => Configure::check('MISP.default_publish_alert') ? Configure::read('MISP.default_publish_alert') : 1
'email' => $registration['data']['email'],
'gpgkey' => empty($registration['data']['pgp']) ? '' : $registration['data']['pgp'],
'disabled' => 0,
'newsread' => 0,
'change_pw' => 1,
'authkey' => $this->generateAuthKey(),
'termsaccepted' => 0,
'org_id' => $org_id,
'role_id' => $role_id,
'invited_by' => $added_by['id'],
'contactalert' => 1,
'autoalert' => $this->defaultPublishAlert(),
);
$this->create();
$this->Log = ClassRegistry::init('Log');
@ -1528,6 +1510,14 @@ class User extends AppModel
return $banStatus;
}
/**
* @return bool
*/
public function defaultPublishAlert()
{
return (bool)Configure::read('MISP.default_publish_alert');
}
/**
* @param array $user
* @return bool

View File

@ -267,7 +267,7 @@ class Warninglist extends AppModel
public function update()
{
// Existing default warninglists
// Fetch existing default warninglists
$existingWarninglist = $this->find('all', [
'fields' => ['id', 'name', 'version', 'enabled'],
'recursive' => -1,
@ -276,7 +276,7 @@ class Warninglist extends AppModel
$existingWarninglist = array_column(array_column($existingWarninglist, 'Warninglist'), null, 'name');
$directories = glob(APP . 'files' . DS . 'warninglists' . DS . 'lists' . DS . '*', GLOB_ONLYDIR);
$updated = array('success' => [], 'fails' => []);
$result = ['success' => [], 'fails' => []];
foreach ($directories as $dir) {
$list = FileAccessTool::readJsonFromFile($dir . DS . 'list.json');
if (!isset($list['version'])) {
@ -289,19 +289,19 @@ class Warninglist extends AppModel
}
if (!isset($existingWarninglist[$list['name']]) || $list['version'] > $existingWarninglist[$list['name']]['version']) {
$current = isset($existingWarninglist[$list['name']]) ? $existingWarninglist[$list['name']] : [];
$result = $this->__updateList($list, $current);
if (is_numeric($result)) {
$updated['success'][$result] = array('name' => $list['name'], 'new' => $list['version']);
try {
$result = $this->__updateList($list, $current);
$result['success'][$result] = ['name' => $list['name'], 'new' => $list['version']];
if (!empty($current)) {
$updated['success'][$result]['old'] = $current['version'];
$result['success'][$result]['old'] = $current['version'];
}
} else {
$updated['fails'][] = array('name' => $list['name'], 'fail' => json_encode($result));
} catch (Exception $e) {
$result['fails'][] = ['name' => $list['name'], 'fail' => $e->getMessage()];
}
}
}
$this->regenerateWarninglistCaches();
return $updated;
return $result;
}
public function quickDelete($id)
@ -325,7 +325,7 @@ class Warninglist extends AppModel
/**
* Import single warninglist
* @param array $list
* @return array|int|string
* @return int Warninglist ID
* @throws Exception
*/
public function import(array $list)
@ -341,29 +341,30 @@ class Warninglist extends AppModel
}
$id = $this->__updateList($list, $existingWarninglist ? $existingWarninglist['Warninglist']: [], false);
if (is_int($id)) {
$this->regenerateWarninglistCaches($id);
}
$this->regenerateWarninglistCaches($id);
return $id;
}
/**
* @param array $list
* @param array $current
* @param array $existing
* @param bool $default
* @return array|int|string
* @return int Warninglist ID
* @throws Exception
*/
private function __updateList(array $list, array $current, $default = true)
private function __updateList(array $list, array $existing, $default = true)
{
$list['enabled'] = 0;
$warninglist = array();
if (!empty($current)) {
if ($current['enabled']) {
$warninglist = [];
if (!empty($existing)) {
if ($existing['enabled']) {
$list['enabled'] = 1;
}
$warninglist['Warninglist']['id'] = $current['id']; // keep list ID
$this->quickDelete($current['id']);
$warninglist['Warninglist']['id'] = $existing['id']; // keep list ID
// Delete all dependencies
$this->WarninglistEntry->deleteAll(['WarninglistEntry.warninglist_id' => $existing['id']], false);
$this->WarninglistType->deleteAll(['WarninglistType.warninglist_id' => $existing['id']], false);
}
$fieldsToSave = array('name', 'version', 'description', 'type', 'enabled');
foreach ($fieldsToSave as $fieldToSave) {
@ -374,7 +375,7 @@ class Warninglist extends AppModel
}
$this->create();
if (!$this->save($warninglist)) {
return $this->validationErrors;
throw new Exception("Could not save warninglist because of validation errors: " . json_encode($this->validationErrors));
}
$db = $this->getDataSource();
@ -404,13 +405,13 @@ class Warninglist extends AppModel
}
}
if (!$result) {
return 'Could not insert values.';
throw new Exception('Could not insert values.');
}
if (empty($list['matching_attributes'])) {
$list['matching_attributes'] = ['ALL'];
}
$values = array();
$values = [];
foreach ($list['matching_attributes'] as $type) {
$values[] = array('type' => $type, 'warninglist_id' => $warninglistId);
}

View File

@ -115,13 +115,15 @@ class Oidc
$this->log($mispUsername, 'Not found in database.');
$time = time();
$userData = [
'email' => $mispUsername,
'org_id' => $organisationId,
'newsread' => time(),
'newsread' => $time,
'autoalert' => $this->User->defaultPublishAlert(),
'role_id' => $roleId,
'change_pw' => 0,
'date_created' => time(),
'date_created' => $time,
'sub' => $sub,
];

View File

@ -97,30 +97,13 @@
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'event', 'menuItem' => 'addAttribute', 'event' => $event));
}
?>
<script type="text/javascript">
<script>
var non_correlating_types = <?= json_encode($nonCorrelatingTypes) ?>;
var notice_list_triggers = <?php echo $notice_list_triggers; ?>;
var category_type_mapping = <?= json_encode(array_map(function(array $value) {
return $value['types'];
}, $categoryDefinitions)); ?>;
$('#AttributeDistribution').change(function() {
checkSharingGroup('Attribute');
});
$('#AttributeCategory').change(function() {
formCategoryChanged('Attribute');
$('#AttributeType').chosen('destroy').chosen();
if ($(this).val() === 'Internal reference') {
$("#AttributeDistribution").val('0');
checkSharingGroup('Attribute');
}
});
$("#AttributeCategory, #AttributeType").change(function() {
checkNoticeList('attribute');
});
$(function() {
<?php
if ($action == 'edit'):
@ -131,8 +114,31 @@
?>
checkSharingGroup('Attribute');
$('#AttributeType').closest('form').submit(function( event ) {
if ($('#AttributeType').val() === 'datetime') {
var $attributeType = $('#AttributeType');
var $attributeCategory = $('#AttributeCategory');
$('#AttributeDistribution').change(function() {
checkSharingGroup('Attribute');
});
$attributeCategory.change(function() {
formCategoryChanged('Attribute');
$attributeType.trigger('chosen:updated');
if ($(this).val() === 'Internal reference') {
$("#AttributeDistribution").val('0');
checkSharingGroup('Attribute');
}
checkNoticeList('attribute');
});
$attributeType.change(function () {
formTypeChanged('Attribute');
checkNoticeList('attribute');
});
formTypeChanged('Attribute');
$attributeType.closest('form').submit(function( event ) {
if ($attributeType.val() === 'datetime') {
// add timezone of the browser if not set
var allowLocalTZ = true;
var $valueInput = $('#AttributeValue')
@ -157,12 +163,12 @@
});
<?php if (!$ajax): ?>
$('#AttributeType').chosen();
$('#AttributeCategory').chosen();
$attributeType.chosen();
$attributeCategory.chosen();
<?php else: ?>
$('#genericModal').on('shown', function() {
$('#AttributeType').chosen();
$('#AttributeCategory').chosen();
$attributeType.chosen();
$attributeCategory.chosen();
})
<?php endif; ?>
});

View File

@ -11,15 +11,10 @@
'children' => [
'data' => [
'type' => 'simple',
'fa-icon' => 'plus',
'text' => __('Add correlation exclusion entry'),
'class' => 'btn btn-primary',
'onClick' => 'openGenericModal',
'onClickParams' => [
sprintf(
'%s/correlation_exclusions/add',
$baseurl
)
]
'class' => 'btn btn-primary modal-open',
'url' => "$baseurl/correlation_exclusions/add",
]
]
],
@ -29,14 +24,8 @@
'data' => [
'type' => 'simple',
'text' => __('Clean up correlations'),
'class' => 'btn btn-primary',
'onClick' => 'openGenericModal',
'onClickParams' => [
sprintf(
'%s/correlation_exclusions/clean',
$baseurl
)
]
'class' => 'btn btn-primary modal-open',
'url' => "$baseurl/correlation_exclusions/clean",
]
]
],
@ -45,6 +34,11 @@
'button' => __('Filter'),
'placeholder' => __('Enter value to search'),
'searchKey' => 'quickFilter',
'cancel' => [
'fa-icon' => 'times',
'title' => __('Remove filters'),
'onClick' => 'cancelSearch',
],
]
]
],
@ -102,7 +96,7 @@
echo $this->element('/genericElements/SideMenu/side_menu', $menuData);
}
?>
<script type="text/javascript">
<script>
var passedArgsArray = <?php echo $passedArgs; ?>;
$(function() {
$('#quickFilterButton').click(function() {

View File

@ -1,24 +1,24 @@
<?php
// Include addation CSS and scripts to layout
$this->viewVars["additionalCss"] = ["gridstack.min"];
$this->viewVars["additionalJs"] = ["gridstack.all"];
?>
<div class="index">
<div class="grid-stack" data-gs-min-row:"10">
<div class="grid-stack">
<?php
$layout = '';
foreach ($widgets as $k => $widget) {
$layout .= $this->element('/dashboard/widget', array('widget' => $widget, 'k' => $k));
echo $this->element('/dashboard/widget', array('widget' => $widget, 'k' => $k));
}
echo $layout;
?>
</div>
<div class="hidden" id="last-element-counter" data-element-counter="<?= h($k) ?>"></div>
</div>
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'dashboard', 'menuItem' => 'dashboardIndex'));
?>
<script type="text/javascript">
<?= $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'dashboard', 'menuItem' => 'dashboardIndex')); ?>
<script>
var grid = false;
$(document).ready(function () {
$(function () {
grid = GridStack.init({verticalMargin: 2});
resetDashboardGrid(grid);
resetDashboardGrid(grid, false);
grid.on('change', function(event, items) {
saveDashboardState();
});

View File

@ -3,17 +3,15 @@
$scopedHtml = $this->ScopedCSS->createScopedCSS($widgetHtml);
?>
<div id="widgetContentInner_<?= h($widget_id) ?>" class="widgetContentInner">
<?php
echo $scopedHtml['bundle'];
?>
<?= $scopedHtml['bundle']; ?>
</div>
<?php if ($config['autoRefreshDelay']): ?>
<script type="text/javascript">
$(function() {
if (<?= $config['autoRefreshDelay'] ? 'true' : 'false' ?>) {
setTimeout( function(){
updateDashboardWidget("#widget_<?= h($widget_id) ?>")},
<?= $config['autoRefreshDelay'] ? $config['autoRefreshDelay'] : 1 ?> * 1000
);
}
setTimeout(function() {
updateDashboardWidget("#widget_<?= h($widget_id) ?>")},
<?= $config['autoRefreshDelay'] ? $config['autoRefreshDelay'] : 1 ?> * 1000
);
});
</script>
<?php endif; ?>

View File

@ -33,6 +33,12 @@ if (!empty($k)) {
$objectId = (int) $object['id'];
$isNonCorrelatingType = in_array($object['type'], Attribute::NON_CORRELATING_TYPES, true);
$correlationDisabled = $object['disable_correlation'] || $isNonCorrelatingType;
$correlationButtonEnabled = $mayChangeCorrelation &&
empty($event['Event']['disable_correlation']) &&
!$isNonCorrelatingType;
$quickEdit = function($fieldName) use ($mayModify, $object) {
if (!$mayModify) {
return ''; // currently it is not supported to create proposals trough quick edit
@ -173,8 +179,8 @@ $quickEdit = function($fieldName) use ($mayModify, $object) {
title="<?php echo __('Toggle correlation');?>"
type="checkbox"
<?php
echo $object['disable_correlation'] ? '' : ' checked';
echo ($mayChangeCorrelation && empty($event['Event']['disable_correlation'])) ? '' : ' disabled';
echo $correlationDisabled ? '' : ' checked';
echo $correlationButtonEnabled ? '' : ' disabled';
?>
>
</td>

View File

@ -2,8 +2,9 @@
<button type="button" class="close" data-dismiss="alert">&times;</button>
<?php
$message = h($message);
if (strpos('$flashErrorMessage', $message) >= 0) {
$message = str_replace('$flashErrorMessage', '<span class="useCursorPointer underline bold" onClick="flashErrorPopover();">here</span>', $message);
if (strpos('$flashErrorMessage', $message) >= 0 && $this->Session->read('flashErrorMessage')) {
$toReplace = sprintf('<a href="#" data-content="%s" data-toggle="popover" class="bold">%s</a>', h($this->Session->read('flashErrorMessage')), __("here"));
$message = str_replace('$flashErrorMessage', $toReplace, $message);
}
echo $message;
if (isset($params['url'])) {
@ -13,8 +14,5 @@
echo '<a href="' . h($params['url']) . '">' . h($params['url']) . '</a>';
}
}
if ($this->Session->read('flashErrorMessage')) {
echo sprintf('<div class="hidden" id="flashErrorMessage">%s</div>', $this->element('flashErrorMessage', array('message' => $this->Session->read('flashErrorMessage'))));
}
?>
</div>

View File

@ -174,6 +174,11 @@ attributes or the appropriate distribution level. If you think there is a mistak
?>
</div>
<?php endif;?>
<p>
<?= $this->Paginator->counter([
'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
]); ?>
</p>
<div class="pagination">
<ul>
<?= $paginatorLinks ?>

View File

@ -1,7 +0,0 @@
<div class="confirmation">
<legend><?php echo __('Errors');?></legend>
<div style="padding-left:5px;padding-right:5px;padding-bottom:5px;">
<div id="flashErrorMessageContent" style="overflow-y: auto;"><?php echo h($message); ?></div>
<span role="button" tabindex="0" aria-label="<?php echo __('Cancel');?>" title="<?php echo __('Cancel');?>" class="btn btn-inverse" id="PromptNoButton" onClick="cancelPopoverForm();"><?php echo __('Close');?></span>
</div>
</div>

View File

@ -67,9 +67,7 @@ if (!empty($data['fields'])) {
}
$metaFieldString = '';
if (!empty($data['metaFields'])) {
foreach ($data['metaFields'] as $metaField) {
$metaFieldString .= $metaField;
}
$metaFieldString = implode('', $data['metaFields']);
}
$submitButtonData = array('model' => $modelForForm);
if (!empty($data['submit'])) {

View File

@ -1,22 +1,25 @@
<?php
$object = Hash::extract($row, $field['data']['object']['value_path']);
$event = Hash::extract($row, 'Event');
$event = $row['Event'];
$mayModify = ($isSiteAdmin || ($isAclModify && $event['user_id'] == $me['id'] && $event['orgc_id'] == $me['org_id']) || ($isAclModifyOrg && $event['orgc_id'] == $me['org_id']));
$mayChangeCorrelation = !Configure::read('MISP.completely_disable_correlation') && ($isSiteAdmin || ($mayModify && Configure::read('MISP.allow_disabling_correlation')));
$objectId = h($object['id']);
$objectId = intval($object['id']);
$isNonCorrelatingType = in_array($object['type'], Attribute::NON_CORRELATING_TYPES, true);
$correlationDisabled = $object['disable_correlation'] || $isNonCorrelatingType;
$correlationButtonEnabled = $mayChangeCorrelation &&
empty($event['disable_correlation']) &&
!$isNonCorrelatingType;
?>
<input
id="correlation_toggle_<?= $objectId ?>"
class="correlation-toggle"
aria-label="<?php echo __('Toggle correlation');?>"
title="<?php echo __('Toggle correlation');?>"
type="checkbox"
data-attribute-id="<?= $objectId ?>"
<?php
echo $object['disable_correlation'] ? '' : ' checked';
echo ($mayChangeCorrelation && empty($event['disable_correlation'])) ? '' : ' disabled';
echo $correlationDisabled ? '' : ' checked';
echo $correlationButtonEnabled ? '' : ' disabled';
?>
/>
>

View File

@ -141,19 +141,19 @@
<span id="lastModifiedField" title="<?= __('Last updated') ?>" class="label"></span>
<span>
<span title="<?= __('Toggle autocompletion while typing'); ?>">
<input type="checkbox" id="autocompletionCB" style="margin: 0 2px 0 0" checked="checked"></input>
<input type="checkbox" id="autocompletionCB" style="margin: 0 2px 0 0" checked="checked">
<span class="<?= $this->FontAwesome->getClass('magic') ?> useCursorPointer icon" onclick="$autocompletionCB[0].checked = !$autocompletionCB[0].checked"></span>
</span>
</span>
<span>
<span title="<?= __('Synchronize scrolling'); ?>">
<input type="checkbox" id="syncScrollCB" style="margin: 0 2px 0 0" checked="checked"></input>
<input type="checkbox" id="syncScrollCB" style="margin: 0 2px 0 0" checked="checked">
<span class="<?= $this->FontAwesome->getClass('link') ?> useCursorPointer icon" onclick="$syncScrollCB[0].checked = !$syncScrollCB[0].checked"></span>
</span>
</span>
<span>
<span title="<?= __('Automatically render markdown when typing'); ?>">
<input type="checkbox" id="autoRenderMarkdownCB" style="margin: 0 2px 0 0" checked="checked"></input>
<input type="checkbox" id="autoRenderMarkdownCB" style="margin: 0 2px 0 0" checked="checked">
<span class="<?= $this->FontAwesome->getClass('markdown') ?> useCursorPointer icon" onclick="$autoRenderMarkdownCB[0].checked = !$autoRenderMarkdownCB[0].checked"></span>
</span>
</span>
@ -189,6 +189,7 @@
<?php
echo $this->element('genericElements/assetLoader', array(
'js' => array(
'jquery-ui.min',
'doT',
'markdown-it',
'highlight.min',

View File

@ -119,13 +119,14 @@ if (!empty($extendedByHtml)) {
?>
<div id="elements_content"></div>
</div>
<?= $this->element('genericElements/assetLoader', array(
'js' => array(
<?= $this->element('genericElements/assetLoader', [
'js' => [
'markdown-it',
),
));
'jquery-ui.min',
],
]);
?>
<script type="text/javascript">
<script>
$(function () {
$.get("<?= $baseurl ?>/galaxy_elements/index/<?php echo $cluster['GalaxyCluster']['id']; ?>", function(data) {
$("#elements_content").html(data);

View File

@ -1,121 +0,0 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<?php echo $this->Html->charset(); ?>
<meta name="viewport" content="width=device-width" />
<title>
<?php echo $title_for_layout, ' - '. h(Configure::read('MISP.title_text') ? Configure::read('MISP.title_text') : 'MISP'); ?>
</title>
<?php
$css_collection = array(
'bootstrap',
//'bootstrap4',
'bootstrap-datepicker',
'bootstrap-colorpicker',
'font-awesome',
'chosen.min',
'main',
'gridstack.min',
array('print', array('media' => 'print'))
);
if (Configure::read('MISP.custom_css')) {
$css_collection[] = preg_replace('/\.css$/i', '', Configure::read('MISP.custom_css'));
}
$js_collection = array(
'jquery',
'misp-touch',
'chosen.jquery.min',
'gridstack.all'
);
echo $this->element('genericElements/assetLoader', array(
'css' => $css_collection,
'js' => $js_collection,
'meta' => 'icon'
));
?>
</head>
<body>
<div id="popover_form" class="ajax_popover_form"></div>
<div id="popover_form_large" class="ajax_popover_form ajax_popover_form_large"></div>
<div id="popover_form_x_large" class="ajax_popover_form ajax_popover_form_x_large"></div>
<div id="popover_matrix" class="ajax_popover_form ajax_popover_matrix"></div>
<div id="popover_box" class="popover_box"></div>
<div id="screenshot_box" class="screenshot_box"></div>
<div id="confirmation_box"></div>
<div id="gray_out"></div>
<div id="container">
<?php
echo $this->element('global_menu');
$topPadding = '50';
if (!empty($debugMode) && $debugMode != 'debugOff') {
$topPadding = '0';
}
?>
</div>
<div id="flashContainer" style="padding-top:<?php echo $topPadding; ?>px; !important;">
<div id="main-view-container" class="container-fluid ">
<?php
echo $this->Flash->render();
?>
</div>
</div>
<div>
<?php
echo $this->fetch('content');
?>
</div>
<?php
echo $this->element('genericElements/assetLoader', array(
'js' => array(
'bootstrap',
'bootstrap-timepicker',
'bootstrap-datepicker',
'bootstrap-colorpicker',
'misp',
'keyboard-shortcuts-definition',
'keyboard-shortcuts'
)
));
echo $this->element('footer');
echo $this->element('sql_dump');
?>
<div id = "ajax_success_container" class="ajax_container">
<div id="ajax_success" class="ajax_result ajax_success"></div>
</div>
<div id = "ajax_fail_container" class="ajax_container">
<div id="ajax_fail" class="ajax_result ajax_fail"></div>
</div>
<div class="loading">
<div class="spinner"></div>
<div class="loadingText"><?php echo __('Loading');?></div>
</div>
<script type="text/javascript">
<?php
if (!isset($debugMode)):
?>
$(window).scroll(function(e) {
$('.actions').css('left',-$(window).scrollLeft());
});
<?php
endif;
?>
var baseurl = '<?php echo $baseurl; ?>';
var here = '<?php
if (substr($this->params['action'], 0, 6) === 'admin_') {
echo $baseurl . '/admin/' . h($this->params['controller']) . '/' . h(substr($this->params['action'], 6));
} else {
echo $baseurl . '/' . h($this->params['controller']) . '/' . h($this->params['action']);
}
?>';
<?php
if (!Configure::read('MISP.disable_auto_logout') and $me):
?>
//checkIfLoggedIn();
<?php
endif;
?>
</script>
</body>
</html>

View File

@ -1,12 +1,13 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?= Configure::read('Config.language') === 'eng' ? 'en' : Configure::read('Config.language') ?>">
<html xmlns="http://www.w3.org/1999/xhtml" lang="<?= Configure::read('Config.language') === 'eng' ? 'en' : Configure::read('Config.language') ?>">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<?php echo $this->Html->charset(); ?>
<meta name="viewport" content="width=device-width">
<link rel="shortcut icon" href="<?= $baseurl ?>/img/favicon.png">
<title><?= $title_for_layout, ' - ', h(Configure::read('MISP.title_text') ?: 'MISP') ?></title>
<?php
$css_collection = array(
$css = [
'bootstrap',
//'bootstrap4',
'bootstrap-datepicker',
@ -14,21 +15,26 @@
'font-awesome',
'chosen.min',
'main',
array('print', array('media' => 'print'))
);
['print', ['media' => 'print']],
];
if (Configure::read('MISP.custom_css')) {
$css_collection[] = preg_replace('/\.css$/i', '', Configure::read('MISP.custom_css'));
$css[] = preg_replace('/\.css$/i', '', Configure::read('MISP.custom_css'));
}
$js_collection = array(
$js = [
'jquery',
'misp-touch',
'chosen.jquery.min',
);
echo $this->element('genericElements/assetLoader', array(
'css' => $css_collection,
'js' => $js_collection,
'meta' => 'icon'
));
];
if (!empty($additionalCss)) {
$css = array_merge($css, $additionalCss);
}
if (!empty($additionalJs)) {
$js = array_merge($js, $additionalJs);
}
echo $this->element('genericElements/assetLoader', [
'css' => $css,
'js' => $js,
]);
?>
</head>
<body data-controller="<?= h($this->params['controller']) ?>" data-action="<?= h($this->params['action']) ?>">
@ -81,12 +87,11 @@
<div id="ajax_fail_container" class="ajax_container">
<div id="ajax_fail" class="ajax_result ajax_fail"></div>
</div>
<div id="ajax_hidden_container" class="hidden"></div>
<div class="loading">
<div class="spinner"></div>
<div class="loadingText"><?php echo __('Loading');?></div>
</div>
<script type="text/javascript">
<script>
<?php
if (!isset($debugMode)):
?>

View File

@ -81,7 +81,7 @@
?>
<div class="user-edit-checkboxes" style="margin-bottom: 1em">
<?php
$default_publish_alert = Configure::check('MISP.default_publish_alert') ? Configure::read('MISP.default_publish_alert') : true;
$default_publish_alert = Configure::read('MISP.default_publish_alert') ?: true;
echo $this->Form->input('autoalert', array(
'label' => __('Receive email alerts when events are published'),
'type' => 'checkbox',

View File

@ -1,35 +1,21 @@
<div class="users form">
<h2><?php echo __('MISP Terms and Conditions');?></h2>
<?php
$embedableExtensions = array('pdf');
if (!Configure::read('MISP.terms_file')) {
$termsFile = APP ."View/Users/terms";
} else {
$customTermsFile = basename(realpath(Configure::read('MISP.terms_file')));
$termsFile = APP . 'files' . DS . 'terms' . DS . $customTermsFile;
}
if (!(file_exists($termsFile))) {
echo "<p>" . __("Terms and Conditions file not found.") . "</p>";
} else {
if (!Configure::read('MISP.terms_download')) {
$terms = new File($termsFile, false);
echo $terms->read(true,'r');
$terms->close();
} else {
?>
<a href="<?php echo $baseurl;?>/users/downloadTerms" class="btn btn-inverse"><?php echo __('Download Terms and Conditions');?></a>
<?php
}
}
<?php if ($termsDownload): ?>
<a href="<?= $baseurl ?>/users/downloadTerms" class="btn btn-inverse"><?= __('Download Terms and Conditions');?></a>
<?php elseif (!$termsContent): ?>
<p><?= __("Terms and Conditions file not found.") ?></p>
<?php else: ?>
<?= $termsContent ?>
<?php endif; ?>
<?php
if (!$termsaccepted) {
echo "<br /><br />";
echo "<br><br>";
echo $this->Form->create('User');
echo $this->Form->hidden('termsaccepted', array('default' => '1'));
echo $this->Form->submit(__('Accept Terms'), array('class' => 'btn btn-primary'));
echo $this->Form->end();
}
?>
?>
</div>
<?php
echo $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'globalActions', 'menuItem' => 'terms'));
?>
<?= $this->element('/genericElements/SideMenu/side_menu', array('menuList' => 'globalActions', 'menuItem' => 'terms'));

@ -1 +1 @@
Subproject commit 33476bec819e8e548c0e87796baef30d8ed78304
Subproject commit fcdc6c86e6e88ca8af39fa950885c7b5b496e840

View File

@ -1,6 +1,5 @@
openapi: 3.0.0
info:
version: 2.4.148
title: MISP Automation API
description: |

BIN
app/webroot/img/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -20,7 +20,7 @@ var relationship_type_mapping = {
'followed-by': 'after',
'preceding-by': 'before',
}
var shortcut_text = "<b>ALT+Mouse_Wheel</b> Zoom IN/OUT"
var shortcut_text_timeline = "<b>ALT+Mouse_Wheel</b> Zoom IN/OUT"
+ "\n<b>CTRL</b> Multi select"
var options = {
template: function (item, element, data) {
@ -604,7 +604,7 @@ function enable_timeline() {
$('.timeline-help').popover({
container: 'body',
title: 'Shortcuts',
content: shortcut_text,
content: shortcut_text_timeline,
placement: 'left',
trigger: 'hover',
template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content preWarp"></div></div>',

File diff suppressed because one or more lines are too long

View File

@ -12,6 +12,15 @@ if (!String.prototype.startsWith) {
};
}
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
function copyToClipboard(element) {
var $temp = $("<input>");
$("body").append($temp);
@ -1189,7 +1198,7 @@ function openGenericModalPost(url, body) {
}
function submitPopoverForm(context_id, referer, update_context_id, modal, popover_dismiss_id_to_close) {
var url = null;
var $form;
var context = 'event';
var contextNamingConvention = 'Attribute';
var closePopover = true;
@ -1227,18 +1236,17 @@ function submitPopoverForm(context_id, referer, update_context_id, modal, popove
}
var $submitButton = $("#submitButton");
if ($submitButton.parent().hasClass('modal-footer')) {
var $form = $submitButton.parent().parent().find('.modal-body form');
url = $form.attr('action');
$form = $submitButton.parent().parent().find('.modal-body form');
} else {
var $form = $submitButton.closest("form");
url = $form.attr('action');
$form = $submitButton.closest("form");
}
var url = $form.attr('action');
// Prepend URL with baseurl if URL is relative
if (!url.startsWith('http')) {
url = baseurl + url;
}
$.ajax({
beforeSend: function (XMLHttpRequest) {
beforeSend: function () {
if (modal) {
if (closePopover) {
$('#genericModal').modal('hide');
@ -1255,16 +1263,15 @@ function submitPopoverForm(context_id, referer, update_context_id, modal, popove
}
},
data: $form.serialize(),
success: function (data, textStatus) {
var result;
success: function (data) {
if (closePopover) {
if (modal) {
result = handleAjaxModalResponse(data, context_id, url, referer, context, contextNamingConvention);
handleAjaxModalResponse(data, context_id, url, referer, context, contextNamingConvention);
} else {
result = handleAjaxPopoverResponse(data, context_id, url, referer, context, contextNamingConvention);
handleAjaxPopoverResponse(data, context_id, url, referer, context, contextNamingConvention);
}
}
if (referer == 'addSighting') {
if (referer === 'addSighting') {
updateIndex(update_context_id, 'event');
$.get(baseurl + "/sightings/listSightings/" + id + "/attribute", function(data) {
$("#sightingsData").html(data);
@ -1274,8 +1281,7 @@ function submitPopoverForm(context_id, referer, update_context_id, modal, popove
$('#sightingsListAllToggle').removeClass('btn-inverse');
$('#sightingsListAllToggle').addClass('btn-primary');
}
if (referer == 'addEventReport' && typeof window.reloadEventReportTable === 'function') {
context == 'eventReport'
if (referer === 'addEventReport' && typeof window.reloadEventReportTable === 'function') {
reloadEventReportTable()
eventUnpublish()
}
@ -1288,9 +1294,7 @@ function submitPopoverForm(context_id, referer, update_context_id, modal, popove
eventUnpublish();
}
},
error: function (jqXHR, textStatus, errorThrown) {
showMessage('fail', textStatus + ": " + errorThrown);
},
error: xhrFailCallback,
complete: function () {
$(".loading").hide();
},
@ -1301,47 +1305,38 @@ function submitPopoverForm(context_id, referer, update_context_id, modal, popove
}
function handleAjaxModalResponse(response, context_id, url, referer, context, contextNamingConvention) {
responseArray = response;
var message = null;
var result = "fail";
var responseArray = response;
if (responseArray.saved) {
updateIndex(context_id, context);
if (responseArray.success) {
showMessage("success", responseArray.success);
result = "success";
}
if (responseArray.errors) {
var message = "message" in responseArray ? responseArray.message : responseArray.success;
showMessage("success", message);
} else if (responseArray.errors) {
showMessage("fail", responseArray.errors);
}
} else {
if (responseArray.errors) {
showMessage("fail", responseArray.errors);
if (responseArray.errors && typeof responseArray.errors === 'string') {
var fullErrors = "full_errors" in responseArray ? responseArray.full_errors : '';
showMessage("fail", responseArray.errors, fullErrors);
} else {
var savedArray = saveValuesForPersistance();
$.ajax({
dataType: "html",
success: function (data) {
$('#genericModal').remove();
$('body').append(data);
$('#genericModal').modal();
handleValidationErrors(responseArray.errors, context, contextNamingConvention);
recoverValuesFromPersistance(savedArray);
},
error: xhrFailCallback,
complete: function () {
$(".loading").hide();
},
url: url
});
}
var savedArray = saveValuesForPersistance();
$.ajax({
dataType:"html",
success:function (data, textStatus) {
$('#genericModal').remove();
$('body').append(data);
$('#genericModal').modal();
var error_context = context.charAt(0).toUpperCase() + context.slice(1);
handleValidationErrors(responseArray.errors, context, contextNamingConvention);
result = "success";
if (!$.isEmptyObject(responseArray)) {
result = "fail";
}
recoverValuesFromPersistance(savedArray);
},
error: function (jqXHR, textStatus, errorThrown) {
showMessage('fail', textStatus + ": " + errorThrown);
},
complete: function () {
$(".loading").hide();
},
url:url
});
}
return result;
}
function handleAjaxPopoverResponse(response, context_id, url, referer, context, contextNamingConvention) {
@ -1399,8 +1394,9 @@ function recoverValuesFromPersistance(formPersistanceArray) {
function handleValidationErrors(responseArray, context, contextNamingConvention) {
for (var k in responseArray) {
var elementName = k.charAt(0).toUpperCase() + k.slice(1);
$("#" + contextNamingConvention + elementName).parent().addClass("error");
$("#" + contextNamingConvention + elementName).parent().append("<div class=\"error-message\">" + responseArray[k] + "</div>");
var $element = $("#" + contextNamingConvention + elementName);
$element.parent().addClass("error");
$element.parent().append("<div class=\"error-message\">" + responseArray[k] + "</div>");
}
}
@ -1426,15 +1422,16 @@ function updateHistogram(selected) {
});
}
function showMessage(success, message, context) {
if (typeof context !== "undefined") {
$("#ajax_" + success, window.parent.document).html(message);
var duration = 1000 + (message.length * 40);
$("#ajax_" + success + "_container", window.parent.document).fadeIn("slow");
$("#ajax_" + success + "_container", window.parent.document).delay(duration).fadeOut("slow");
}
$("#ajax_" + success).html(message);
function showMessage(success, message, fullError) {
var duration = 1000 + (message.length * 40);
if (message.indexOf("$flashErrorMessage") >= 0) {
var flashMessageLink = '<a href="#" class="bold" data-content="' + escapeHtml(fullError) + '" data-html="true" onclick="event.preventDefault();$(this).popover(\'show\')">here</a>';
message = message.replace("$flashErrorMessage", flashMessageLink);
duration = 5000;
}
$("#ajax_" + success).html(message);
$("#ajax_" + success + "_container").fadeIn("slow").delay(duration).fadeOut("slow");
}
@ -2644,8 +2641,9 @@ function popoverStartup() {
$('[data-toggle="popover"]').not(e.target).popover('hide');
});
$(document).click(function (e) {
if (!$('[data-toggle="popover"]').is(e.target)) {
$('[data-toggle="popover"]').popover('hide');
var $popovers = $('[data-toggle="popover"]');
if (!$popovers.is(e.target)) {
$popovers.popover('hide');
}
});
}
@ -3976,15 +3974,6 @@ $(document).on("click", ".eventViewAttributePopup", function() {
}
});
function flashErrorPopover() {
$('#popover_form').css( "minWidth", "200px");
$('#popover_form').html($('#flashErrorMessage').html());
$('#popover_form').show();
var left = ($(window).width() / 2) - ($('#popover_form').width() / 2);
$('#popover_form').css({'left': left + 'px'});
$("#gray_out").fadeIn();
}
$(document.body).on('click', function (e) {
$('[data-toggle=popover]').each(function () {
// hide any open popovers when the anywhere else in the body is clicked
@ -4046,7 +4035,8 @@ function formCategoryChanged(id) {
if (selectedCategory === "") { // if no category is selected, insert all attribute types
optionsToPush = {};
for (var category in category_type_mapping) {
for (var type in category_type_mapping[category]) {
for (var index in category_type_mapping[category]) {
var type = category_type_mapping[category][index];
optionsToPush[type] = type;
}
}
@ -4065,6 +4055,15 @@ function formCategoryChanged(id) {
$type.prop('disabled', false);
}
function formTypeChanged(idPrefix) {
var $type = $('#' + idPrefix + 'Type');
var currentType = $type.val();
// Check if current type is correlatable and disable checkbox if yes
var nonCorrelatingType = non_correlating_types.indexOf(currentType) !== -1;
$('#' + idPrefix + 'DisableCorrelation').prop('disabled', nonCorrelatingType);
}
function malwareCheckboxSetter(context) {
var value = $("#" + context + "Category").val(); // get the selected value
// set the malware checkbox if the category is in the zip types
@ -4570,16 +4569,16 @@ function checkNoticeList(type) {
var fields_to_check = {
"attribute": ["category", "type"]
}
var warnings = [];
$('#notice_message').html('<h4>Notices:</h4>');
$('#notice_message').hide();
var $noticeMessage = $('#notice_message');
$noticeMessage.html('<h4>Notices:</h4>');
$noticeMessage.hide();
fields_to_check[type].forEach(function(field_name) {
if (field_name in notice_list_triggers) {
var field_value = $('#' + type.ucfirst() + field_name.ucfirst()).val();
if (field_value in notice_list_triggers[field_name]) {
notice_list_triggers[field_name][field_value].forEach(function(notice) {
$('#notice_message').show();
$('#notice_message').append(
$noticeMessage.show();
$noticeMessage.append(
$('<div/>')
.append($('<span/>').text('['))
.append($('<a/>', {href: baseurl + '/noticelists/view/' + notice['list_id'], class:'bold'}).text(notice['list_name']))
@ -4683,11 +4682,6 @@ $(function() {
}).on('shown', function() {
$('.tooltip').not(":last").remove();
});
if ($('.alert').text().indexOf("$flashErrorMessage") >= 0) {
var flashMessageLink = '<span class="useCursorPointer underline bold" onClick="flashErrorPopover();">here</span>';
$('.alert').html(($('.alert').html().replace("$flashErrorMessage", flashMessageLink)));
}
});
// Correlation box for events
@ -5207,7 +5201,7 @@ function submitDashboardAddWidget() {
function saveDashboardState() {
var dashBoardSettings = [];
$('.grid-stack-item').each(function(index) {
$('.grid-stack-item').each(function() {
if ($(this).attr('config') !== undefined && $(this).attr('widget') !== undefined) {
var config = $(this).attr('config');
config = JSON.parse(config);
@ -5231,12 +5225,9 @@ function saveDashboardState() {
var $theForm = $formContainer.find('form')
xhr({
data: $theForm.serialize(),
success:function (data) {
success:function () {
showMessage('success', 'Dashboard settings saved.');
},
error:function(jqXHR, textStatus, errorThrown) {
showMessage('fail', textStatus + ": " + errorThrown);
},
beforeSend:function() {
},
type:"post",
@ -5262,21 +5253,23 @@ function updateDashboardWidget(element) {
config: $element.attr('config'),
widget: $element.attr('widget')
},
success:function (data, textStatus) {
success:function (data) {
container.html(data);
}
});
}
}
function resetDashboardGrid(grid) {
function resetDashboardGrid(grid, save = true) {
$('.grid-stack-item').each(function() {
updateDashboardWidget(this);
});
saveDashboardState();
if (save) {
saveDashboardState();
}
$('.edit-widget').click(function() {
el = $(this).closest('.grid-stack-item');
data = {
var el = $(this).closest('.grid-stack-item');
var data = {
id: el.attr('id'),
config: JSON.parse(el.attr('config')),
widget: el.attr('widget'),
@ -5285,7 +5278,7 @@ function resetDashboardGrid(grid) {
openGenericModalPost(baseurl + '/dashboards/getForm/edit', data);
});
$('.remove-widget').click(function() {
el = $(this).closest('.grid-stack-item');
var el = $(this).closest('.grid-stack-item');
grid.removeWidget(el);
saveDashboardState();
});
@ -5296,14 +5289,14 @@ function setHomePage() {
type: 'GET',
url: baseurl + '/userSettings/setHomePage',
success: function (data) {
$('#ajax_hidden_container').html(data);
var $tmp = $(data);
var currentPage = $('#setHomePage').data('current-page');
$('#UserSettingPath').val(currentPage);
$tmp.find('#UserSettingPath').val(currentPage);
$.ajax({
type: 'POST',
url: baseurl + '/userSettings/setHomePage',
data: $('#UserSettingSetHomePageForm').serialize(),
success:function (data) {
data: $tmp.serialize(),
success: function () {
showMessage('success', 'Homepage set.');
$('#setHomePage').addClass('orange');
},

View File

@ -8031,7 +8031,8 @@
"category": false,
"sharing_group_id": false,
"first_seen": false,
"last_seen": false
"last_seen": false,
"timestamp": false
},
"attribute_tags": {
"id": true,
@ -8469,5 +8470,5 @@
"id": true
}
},
"db_version": "85"
"db_version": "86"
}

View File

@ -3,7 +3,7 @@
modulesCAKE () {
# Enable Enrichment, set better timeouts
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_services_enable" true
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_hover_enable" true
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_hover_enable" false
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_hover_popover_only" false
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_hover_timeout" 150
${SUDO_WWW} ${RUN_PHP} -- ${CAKE} Admin setSetting "Plugin.Enrichment_timeout" 300

View File

@ -4,6 +4,7 @@ import json
import uuid
import subprocess
import unittest
import requests
from xml.etree import ElementTree as ET
from io import BytesIO
import urllib3 # type: ignore
@ -689,6 +690,10 @@ class TestComprehensive(unittest.TestCase):
wl = request(self.admin_misp_connector, 'POST', 'warninglists/add', data=warninglist)
check_response(wl)
exported = request(self.admin_misp_connector, 'GET', f'warninglists/export/{wl["Warninglist"]["id"]}')
self.assertIn('name', exported)
self.assertEqual('Test', exported['name'])
check_response(self.admin_misp_connector.enable_warninglist(wl["Warninglist"]["id"]))
response = self.admin_misp_connector.values_in_warninglist("1.2.3.4")
@ -716,9 +721,21 @@ class TestComprehensive(unittest.TestCase):
response = self.admin_misp_connector.values_in_warninglist("2.3.4.5")
self.assertEqual(0, len(response))
# Update by importing
response = request(self.admin_misp_connector, 'POST', f'warninglists/import', exported)
check_response(response)
response = request(self.admin_misp_connector, 'POST', f'warninglists/delete/{wl["Warninglist"]["id"]}')
check_response(response)
# Create new warninglist by importing under different name
exported["name"] = "Test2"
response = request(self.admin_misp_connector, 'POST', f'warninglists/import', exported)
check_response(response)
response = request(self.admin_misp_connector, 'POST', f'warninglists/delete/{response["id"]}')
check_response(response)
def test_protected_event(self):
event = create_simple_event()
event = check_response(self.admin_misp_connector.add_event(event))
@ -746,6 +763,40 @@ class TestComprehensive(unittest.TestCase):
self.assertEqual(200, response.status_code, response)
response.json()
def test_etag(self):
headers = {
'Authorization': self.admin_misp_connector.key,
'Accept': 'application/json',
'User-Agent': 'PyMISP',
'If-None-Match': '',
}
response = requests.get(self.admin_misp_connector.root_url + '/attributes/describeTypes.json', headers=headers)
self.assertEqual(200, response.status_code)
self.assertIn('Etag', response.headers)
self.assertTrue(len(response.headers['Etag']) > 0, response.headers['Etag'])
headers['If-None-Match'] = response.headers['Etag']
response = requests.get(self.admin_misp_connector.root_url + '/attributes/describeTypes.json', headers=headers)
self.assertEqual(304, response.status_code, response.headers)
def test_event_alert_default_enabled(self):
user = MISPUser()
user.email = 'testusr_alert_disabled@user.local'
user.org_id = self.test_org.id
created_user = check_response(self.admin_misp_connector.add_user(user))
self.assertFalse(created_user.autoalert, created_user)
self.admin_misp_connector.delete_user(created_user)
with MISPSetting(self.admin_misp_connector, {"MISP.default_publish_alert": True}):
user = MISPUser()
user.email = 'testusr_alert_enabled@user.local'
user.org_id = self.test_org.id
created_user = check_response(self.admin_misp_connector.add_user(user))
self.assertTrue(created_user.autoalert, created_user)
self.admin_misp_connector.delete_user(created_user)
def _search(self, query: dict):
response = self.admin_misp_connector._prepare_request('POST', 'events/restSearch', data=query)
response = self.admin_misp_connector._check_response(response)