2013-01-25 08:51:20 +01:00
< ? php
App :: uses ( 'AppController' , 'Controller' );
App :: uses ( 'Xml' , 'Utility' );
2016-08-25 11:38:37 +02:00
2020-06-30 09:01:55 +02:00
/**
* @ property Event $Event
2020-07-22 19:06:00 +02:00
* @ property User $User
2020-06-30 09:01:55 +02:00
*/
2018-07-19 11:48:22 +02:00
class EventsController extends AppController
{
public $components = array (
2021-11-23 14:53:27 +01:00
'RequestHandler' ,
'IOCImport' ,
2018-07-19 11:48:22 +02:00
);
public $paginate = array (
'limit' => 60 ,
2019-02-10 13:08:12 +01:00
'maxLimit' => 9999 , // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
2018-07-19 11:48:22 +02:00
'order' => array (
'Event.timestamp' => 'DESC'
),
'contain' => array (
'Org' => array ( 'fields' => array ( 'id' , 'name' , 'uuid' )),
'Orgc' => array ( 'fields' => array ( 'id' , 'name' , 'uuid' )),
'SharingGroup' => array ( 'fields' => array ( 'id' , 'name' , 'uuid' ))
)
);
2021-10-19 18:40:20 +02:00
// private
const ACCEPTED_FILTERING_NAMED_PARAMS = array (
2021-10-19 18:38:07 +02:00
'sort' , 'direction' , 'focus' , 'extended' , 'overrideLimit' , 'filterColumnsOverwrite' , 'attributeFilter' , 'page' ,
2019-11-06 21:20:04 +01:00
'searchFor' , 'proposal' , 'correlation' , 'warning' , 'deleted' , 'includeRelatedTags' , 'includeDecayScore' , 'distribution' ,
2021-10-19 18:38:07 +02:00
'taggedAttributes' , 'galaxyAttachedAttributes' , 'objectType' , 'attributeType' , 'feed' , 'server' , 'toIDS' ,
2023-09-24 19:29:43 +02:00
'sighting' , 'includeSightingdb' , 'warninglistId' , 'correlationId' , 'email' , 'eventid' , 'datefrom' , 'dateuntil'
2019-02-13 11:30:05 +01:00
);
2021-10-23 16:38:27 +02:00
// private
const DEFAULT_FILTERING_RULE = array (
2019-02-13 14:59:49 +01:00
'searchFor' => '' ,
'attributeFilter' => 'all' ,
'proposal' => 0 ,
'correlation' => 0 ,
'warning' => 0 ,
2021-10-23 16:38:27 +02:00
'deleted' => 0 ,
2019-02-13 14:59:49 +01:00
'includeRelatedTags' => 0 ,
2019-08-12 16:34:26 +02:00
'includeDecayScore' => 0 ,
2019-02-15 16:28:04 +01:00
'toIDS' => 0 ,
2019-02-13 14:59:49 +01:00
'feed' => 0 ,
'server' => 0 ,
'distribution' => array ( 0 , 1 , 2 , 3 , 4 , 5 ),
2019-03-01 11:54:29 +01:00
'sighting' => 0 ,
2019-02-13 14:59:49 +01:00
'taggedAttributes' => '' ,
2021-09-02 10:19:06 +02:00
'galaxyAttachedAttributes' => '' ,
'warninglistId' => '' ,
2022-04-29 14:36:06 +02:00
'correlationId' => '' ,
2019-02-13 14:59:49 +01:00
);
2021-12-06 14:27:29 +01:00
// private
const DEFAULT_HIDDEN_INDEX_COLUMNS = [
2022-04-29 19:55:12 +02:00
'timestamp' ,
2021-12-06 14:27:29 +01:00
'publish_timestamp'
];
2018-07-19 11:48:22 +02:00
public $paginationFunctions = array ( 'index' , 'proposalEventIndex' );
public function beforeFilter ()
{
parent :: beforeFilter ();
// what pages are allowed for non-logged-in users
$this -> Auth -> allow ( 'xml' );
$this -> Auth -> allow ( 'csv' );
$this -> Auth -> allow ( 'nids' );
$this -> Auth -> allow ( 'hids_md5' );
$this -> Auth -> allow ( 'hids_sha1' );
$this -> Auth -> allow ( 'text' );
$this -> Auth -> allow ( 'restSearch' );
$this -> Auth -> allow ( 'stix' );
$this -> Auth -> allow ( 'stix2' );
2019-01-31 14:39:24 +01:00
$this -> Security -> unlockedActions [] = 'viewEventAttributes' ;
2018-07-19 11:48:22 +02:00
// TODO Audit, activate logable in a Controller
if ( count ( $this -> uses ) && $this -> { $this -> modelClass } -> Behaviors -> attached ( 'SysLogLogable' )) {
$this -> { $this -> modelClass } -> setUserData ( $this -> activeUser );
}
// convert uuid to id if present in the url, and overwrite id field
2021-09-14 15:24:30 +02:00
if ( isset ( $this -> request -> params -> query [ 'uuid' ])) {
2018-07-19 11:48:22 +02:00
$params = array (
'conditions' => array ( 'Event.uuid' => $this -> params -> query [ 'uuid' ]),
'recursive' => 0 ,
'fields' => 'Event.id'
);
$result = $this -> Event -> find ( 'first' , $params );
if ( isset ( $result [ 'Event' ]) && isset ( $result [ 'Event' ][ 'id' ])) {
$id = $result [ 'Event' ][ 'id' ];
$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 not admin or own org, check private as well..
2021-09-14 15:24:30 +02:00
if ( ! $this -> _isSiteAdmin () && in_array ( $this -> request -> action , $this -> paginationFunctions , true )) {
2020-08-21 15:04:19 +02:00
$conditions = $this -> Event -> createEventConditions ( $this -> Auth -> user ());
2018-07-19 11:48:22 +02:00
if ( $this -> userRole [ 'perm_sync' ] && $this -> Auth -> user ( 'Server' )[ 'push_rules' ]) {
$conditions [ 'AND' ][] = $this -> Event -> filterRulesToConditions ( $this -> Auth -> user ( 'Server' )[ 'push_rules' ]);
}
$this -> paginate = Set :: merge ( $this -> paginate , array ( 'conditions' => $conditions ));
}
2021-11-23 14:53:27 +01:00
2022-05-15 11:29:12 +02:00
if ( in_array ( $this -> request -> action , [ 'checkLocks' , 'getDistributionGraph' ], true )) {
2021-11-23 14:53:27 +01:00
$this -> Security -> doNotGenerateToken = true ;
}
2023-04-12 11:18:27 +02:00
if ( Configure :: read ( 'Plugin.CustomAuth_enable' ) && in_array ( $this -> request -> action , [ 'saveFreeText' ], true )) {
$this -> Security -> csrfCheck = false ;
}
2018-07-19 11:48:22 +02:00
}
2020-09-02 16:49:45 +02:00
/**
* @ param string $value
* @ return array []
*/
2018-07-19 11:48:22 +02:00
private function __filterOnAttributeValue ( $value )
{
// dissect the value
$include = array ();
$exclude = array ();
2020-11-16 16:17:47 +01:00
$includeIDs = [];
$excludeIDs = [];
if ( ! empty ( $value )) {
if ( ! is_array ( $value )) {
2021-10-15 17:02:20 +02:00
$pieces = explode ( '|' , mb_strtolower ( $value ));
2018-07-19 11:48:22 +02:00
} else {
2020-11-16 16:17:47 +01:00
$pieces = $value ;
2018-07-19 11:48:22 +02:00
}
2020-09-02 16:49:45 +02:00
2020-11-16 16:17:47 +01:00
foreach ( $pieces as $piece ) {
if ( $piece [ 0 ] === '!' ) {
$exclude [] = '%' . substr ( $piece , 1 ) . '%' ;
} else {
$include [] = " % $piece % " ;
}
2018-07-19 11:48:22 +02:00
}
2020-11-16 16:17:47 +01:00
if ( ! empty ( $include )) {
$includeConditions = [];
foreach ( $include as $i ) {
2021-10-15 17:02:20 +02:00
$includeConditions [ 'OR' ][] = array ( 'Attribute.value1 LIKE' => $i );
$includeConditions [ 'OR' ][] = array ( 'Attribute.value2 LIKE' => $i );
2020-11-16 16:17:47 +01:00
}
2018-07-19 11:48:22 +02:00
2020-12-23 12:50:19 +01:00
$includeIDs = $this -> Event -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array (
2020-11-16 16:17:47 +01:00
'conditions' => $includeConditions ,
'flatten' => true ,
'event_ids' => true ,
'list' => true ,
2020-12-23 12:50:19 +01:00
));
2018-07-19 11:48:22 +02:00
}
2020-11-16 16:17:47 +01:00
if ( ! empty ( $exclude )) {
$excludeConditions = [];
foreach ( $exclude as $e ) {
2021-10-15 17:02:20 +02:00
$excludeConditions [ 'OR' ][] = array ( 'Attribute.value1 LIKE' => $e );
$excludeConditions [ 'OR' ][] = array ( 'Attribute.value2 LIKE' => $e );
2020-11-16 16:17:47 +01:00
}
2020-12-23 12:50:19 +01:00
$excludeIDs = $this -> Event -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array (
2020-11-16 16:17:47 +01:00
'conditions' => $excludeConditions ,
'flatten' => true ,
'event_ids' => true ,
'list' => true ,
2020-12-23 12:50:19 +01:00
));
2020-11-16 16:17:47 +01:00
}
2018-07-19 11:48:22 +02:00
}
// return -1 as the only value in includedIDs if both arrays are empty. This will mean that no events will be shown if there was no hit
if ( empty ( $includeIDs ) && empty ( $excludeIDs )) {
$includeIDs [] = - 1 ;
}
return array ( $includeIDs , $excludeIDs );
}
2020-09-01 17:56:32 +02:00
/**
* @ param string | array $value
* @ return array Event ID that match filter
*/
2018-07-19 11:48:22 +02:00
private function __quickFilter ( $value )
{
if ( ! is_array ( $value )) {
$value = array ( $value );
}
$values = array ();
foreach ( $value as $v ) {
2021-08-02 17:15:40 +02:00
$values [] = '%' . mb_strtolower ( $v ) . '%' ;
2018-07-19 11:48:22 +02:00
}
// get all of the attributes that have a hit on the search term, in either the value or the comment field
// This is not perfect, the search will be case insensitive, but value1 and value2 are searched separately. lower() doesn't seem to work on virtualfields
$subconditions = array ();
foreach ( $values as $v ) {
2021-08-02 17:15:40 +02:00
$subconditions [] = array ( 'Attribute.value1 LIKE' => $v );
$subconditions [] = array ( 'Attribute.value2 LIKE' => $v );
$subconditions [] = array ( 'Attribute.comment LIKE' => $v );
2018-07-19 11:48:22 +02:00
}
$conditions = array (
2020-09-01 17:56:32 +02:00
'OR' => $subconditions ,
2018-07-19 11:48:22 +02:00
);
2020-12-23 12:50:19 +01:00
$result = $this -> Event -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array (
2020-09-01 17:56:32 +02:00
'conditions' => $conditions ,
'flatten' => 1 ,
'event_ids' => true ,
'list' => true ,
2018-07-19 11:48:22 +02:00
));
// we now have a list of event IDs that match on an attribute level, and the user can see it. Let's also find all of the events that match on other criteria!
// What is interesting here is that we no longer have to worry about the event's releasability. With attributes this was a different case,
// because we might run into a situation where a user can see an event but not a specific attribute
// returning a hit on such an attribute would allow users to enumerate hidden attributes
// For anything beyond this point the default pagination restrictions will apply!
// First of all, there are tags that might be interesting for us
$subconditions = array ();
foreach ( $values as $v ) {
$subconditions [] = array ( 'lower(name) LIKE' => $v );
}
$tags = $this -> Event -> EventTag -> Tag -> find ( 'all' , array (
2020-09-01 17:56:32 +02:00
'conditions' => $subconditions ,
'fields' => array ( 'id' ),
'contain' => array ( 'EventTag' => [ 'fields' => 'event_id' ], 'AttributeTag' => [ 'fields' => 'event_id' ]),
2018-07-19 11:48:22 +02:00
));
foreach ( $tags as $tag ) {
foreach ( $tag [ 'EventTag' ] as $eventTag ) {
if ( ! in_array ( $eventTag [ 'event_id' ], $result )) {
$result [] = $eventTag [ 'event_id' ];
}
}
foreach ( $tag [ 'AttributeTag' ] as $attributeTag ) {
if ( ! in_array ( $attributeTag [ 'event_id' ], $result )) {
$result [] = $attributeTag [ 'event_id' ];
}
}
}
// Finally, let's search on the event metadata!
$subconditions = array ();
foreach ( $values as $v ) {
$subconditions [] = array ( 'lower(name) LIKE' => $v );
}
2020-12-23 12:50:19 +01:00
$orgs = $this -> Event -> Org -> find ( 'column' , array (
2020-09-01 17:56:32 +02:00
'conditions' => $subconditions ,
2020-12-23 12:50:19 +01:00
'fields' => array ( 'Org.id' )
2018-07-19 11:48:22 +02:00
));
2020-09-01 17:56:32 +02:00
$conditions = empty ( $result ) ? [] : [ 'NOT' => [ 'id' => $result ]]; // Do not include events that we already found
2018-07-19 11:48:22 +02:00
foreach ( $values as $v ) {
$conditions [ 'OR' ][] = array ( 'lower(info) LIKE' => $v );
$conditions [ 'OR' ][] = array ( 'lower(uuid) LIKE' => $v );
}
if ( ! empty ( $orgs )) {
2020-12-23 12:50:19 +01:00
$conditions [ 'OR' ][ 'orgc_id' ] = $orgs ;
2018-07-19 11:48:22 +02:00
}
2020-12-23 12:50:19 +01:00
$otherEvents = $this -> Event -> find ( 'column' , array (
'fields' => array ( 'Event.id' ),
2020-09-01 17:56:32 +02:00
'conditions' => $conditions ,
2018-07-19 11:48:22 +02:00
));
2020-09-01 17:56:32 +02:00
foreach ( $otherEvents as $eventId ) {
$result [] = $eventId ;
2018-07-19 11:48:22 +02:00
}
return $result ;
}
2021-08-11 22:50:01 +02:00
/**
* @ param array $passedArgs
* @ param string $urlparams
2021-10-15 19:22:53 +02:00
* @ param bool $nothing True when nothing should be fetched from database
2021-08-11 22:50:01 +02:00
* @ return array
*/
2021-10-15 19:22:53 +02:00
private function __setIndexFilterConditions ( array $passedArgs , & $urlparams , & $nothing = false )
2018-07-19 11:48:22 +02:00
{
$passedArgsArray = array ();
foreach ( $passedArgs as $k => $v ) {
2021-08-11 22:50:01 +02:00
if ( substr ( $k , 0 , 6 ) !== 'search' ) {
continue ;
}
if ( ! is_array ( $v )) {
if ( $urlparams != " " ) {
$urlparams .= " / " ;
2018-07-19 11:48:22 +02:00
}
2021-08-11 22:50:01 +02:00
$urlparams .= $k . " : " . $v ;
}
$searchTerm = strtolower ( substr ( $k , 6 ));
switch ( $searchTerm ) {
case 'all' :
2021-10-15 19:09:02 +02:00
if ( ! empty ( $v )) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.id' => $this -> __quickFilter ( $v ));
2021-08-11 22:50:01 +02:00
}
break ;
case 'attribute' :
$event_id_arrays = $this -> __filterOnAttributeValue ( $v );
if ( ! empty ( $event_id_arrays [ 0 ])) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.id' => $event_id_arrays [ 0 ]);
}
if ( ! empty ( $event_id_arrays [ 1 ])) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.id !=' => $event_id_arrays [ 1 ]);
}
break ;
case 'published' :
if ( $v === 2 || $v === '2' ) { // both
continue 2 ;
}
2021-10-15 17:09:48 +02:00
if ( is_array ( $v ) && in_array ( 0 , $v ) && in_array ( 1 , $v )) {
continue 2 ; // both
}
2021-08-11 22:50:01 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.published' => $v );
break ;
case 'hasproposal' :
if ( $v === 2 || $v === '2' ) { // both
continue 2 ;
}
$proposalQuery = " exists (select id, deleted from shadow_attributes where shadow_attributes.event_id = Event.id and shadow_attributes.deleted = 0) " ;
if ( $v == 0 ) {
$proposalQuery = 'not ' . $proposalQuery ;
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = $proposalQuery ;
break ;
case 'eventid' :
if ( $v == " " ) {
continue 2 ;
}
$pieces = is_array ( $v ) ? $v : explode ( '|' , $v );
$eventidConditions = array ();
foreach ( $pieces as $piece ) {
$piece = trim ( $piece );
2021-09-13 23:58:10 +02:00
if ( $piece [ 0 ] === '!' ) {
2021-08-11 23:17:57 +02:00
if ( strlen ( $piece ) === 37 ) {
2021-08-11 22:50:01 +02:00
$eventidConditions [ 'NOT' ][ 'uuid' ][] = substr ( $piece , 1 );
} else {
$eventidConditions [ 'NOT' ][ 'id' ][] = substr ( $piece , 1 );
}
2020-04-14 18:00:43 +02:00
} else {
2021-08-11 23:17:57 +02:00
if ( strlen ( $piece ) === 36 ) {
2021-08-11 22:50:01 +02:00
$eventidConditions [ 'OR' ][ 'uuid' ][] = $piece ;
2018-07-19 11:48:22 +02:00
} else {
2021-08-11 22:50:01 +02:00
$eventidConditions [ 'OR' ][ 'id' ][] = $piece ;
2018-07-19 11:48:22 +02:00
}
}
2021-08-11 22:50:01 +02:00
}
foreach ( $eventidConditions as $operator => $conditionForOperator ) {
foreach ( $conditionForOperator as $conditionKey => $conditionValue ) {
$lookupKey = 'Event.' . $conditionKey ;
if ( $operator === 'NOT' ) {
$lookupKey = $lookupKey . ' !=' ;
2020-04-14 18:00:43 +02:00
}
2021-08-11 22:50:01 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( $lookupKey => $conditionValue );
2020-04-14 18:00:43 +02:00
}
2021-08-11 22:50:01 +02:00
}
break ;
case 'datefrom' :
if ( $v == " " ) {
continue 2 ;
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.date >=' => $v );
break ;
case 'dateuntil' :
if ( $v == " " ) {
continue 2 ;
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.date <=' => $v );
break ;
case 'timestamp' :
if ( $v == " " ) {
continue 2 ;
}
2021-12-06 16:01:12 +01:00
if ( is_array ( $v ) && isset ( $v [ 0 ]) && isset ( $v [ 1 ])) {
2021-12-06 16:20:51 +01:00
if ( ! is_int ( $v [ 0 ])) {
2021-12-06 16:01:12 +01:00
$v [ 0 ] = $this -> Event -> resolveTimeDelta ( $v [ 0 ]);
}
2021-12-06 16:20:51 +01:00
if ( ! is_int ( $v [ 1 ])) {
2021-12-06 16:01:12 +01:00
$v [ 1 ] = $this -> Event -> resolveTimeDelta ( $v [ 1 ]);
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.timestamp >=' => $v [ 0 ]);
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.timestamp <=' => $v [ 1 ]);
} else {
if ( ! is_int ( $v )) {
$v = $this -> Event -> resolveTimeDelta ( $v );
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.timestamp >=' => $v );
2021-08-11 22:50:01 +02:00
}
break ;
case 'publish_timestamp' :
case 'publishtimestamp' :
if ( $v == " " ) {
continue 2 ;
}
if ( is_array ( $v ) && isset ( $v [ 0 ]) && isset ( $v [ 1 ])) {
2021-12-06 16:20:51 +01:00
if ( ! is_int ( $v [ 0 ])) {
2021-08-11 22:50:01 +02:00
$v [ 0 ] = $this -> Event -> resolveTimeDelta ( $v [ 0 ]);
2018-07-19 11:48:22 +02:00
}
2021-12-06 16:20:51 +01:00
if ( ! is_int ( $v [ 1 ])) {
2021-08-11 22:50:01 +02:00
$v [ 1 ] = $this -> Event -> resolveTimeDelta ( $v [ 1 ]);
2018-07-19 11:48:22 +02:00
}
2021-08-11 22:50:01 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.publish_timestamp >=' => $v [ 0 ]);
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.publish_timestamp <=' => $v [ 1 ]);
} else {
2021-12-06 16:01:12 +01:00
if ( ! is_int ( $v )) {
2018-07-19 11:48:22 +02:00
$v = $this -> Event -> resolveTimeDelta ( $v );
}
2021-08-11 22:50:01 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.publish_timestamp >=' => $v );
}
break ;
case 'org' :
2021-08-11 23:17:57 +02:00
if ( $v == " " || ! Configure :: read ( 'MISP.showorg' )) {
2021-08-11 22:50:01 +02:00
continue 2 ;
}
2021-08-11 23:17:57 +02:00
2021-10-14 14:20:26 +02:00
$this -> Event -> Org -> virtualFields = [
'upper_name' => 'UPPER(name)' ,
2021-10-15 10:42:38 +02:00
'lower_uuid' => 'LOWER(uuid)' ,
2021-10-14 14:20:26 +02:00
];
2021-08-11 23:17:57 +02:00
$orgs = array_column ( $this -> Event -> Org -> find ( 'all' , [
2021-10-14 14:20:26 +02:00
'fields' => [ 'Org.id' , 'Org.upper_name' , 'Org.lower_uuid' ],
2021-08-11 23:17:57 +02:00
'recursive' => - 1 ,
]), 'Org' );
2021-10-15 12:15:33 +02:00
$this -> Event -> Org -> virtualFields = [];
2021-10-15 12:21:03 +02:00
$orgByName = array_column ( $orgs , 'id' , 'upper_name' );
$orgByUuid = array_column ( $orgs , 'id' , 'lower_uuid' );
2021-08-11 22:50:01 +02:00
// if the first character is '!', search for NOT LIKE the rest of the string (excluding the '!' itself of course)
2021-08-11 23:17:57 +02:00
$pieces = is_array ( $v ) ? $v : explode ( '|' , $v );
2021-08-11 22:50:01 +02:00
$test = array ();
foreach ( $pieces as $piece ) {
2021-08-11 23:17:57 +02:00
if ( $piece [ 0 ] === '!' ) {
$piece = substr ( $piece , 1 ); // remove `!` char
if ( is_numeric ( $piece )) {
$orgId = $piece ;
} else if ( Validation :: uuid ( $piece )) {
2021-10-15 12:21:03 +02:00
$orgId = isset ( $orgByUuid [ $piece ]) ? $orgByUuid [ $piece ] : null ;
2021-08-11 22:50:01 +02:00
} else {
2021-08-11 23:17:57 +02:00
$orgName = mb_strtoupper ( $piece );
2021-10-15 12:21:03 +02:00
$orgId = isset ( $orgByName [ $orgName ]) ? $orgByName [ $orgName ] : null ;
2021-08-11 23:17:57 +02:00
}
if ( $orgId ) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.orgc_id !=' => $orgId );
2018-07-19 11:48:22 +02:00
}
2020-03-30 08:56:30 +02:00
} else {
2021-08-11 22:50:01 +02:00
if ( is_numeric ( $piece )) {
2021-10-15 12:32:09 +02:00
$test [ 'OR' ][] = array ( 'Event.orgc_id' => $piece );
2021-08-11 22:50:01 +02:00
} else {
if ( Validation :: uuid ( $piece )) {
2021-10-15 12:21:03 +02:00
$orgId = isset ( $orgByUuid [ $piece ]) ? $orgByUuid [ $piece ] : null ;
2018-07-19 11:48:22 +02:00
} else {
2021-08-11 23:17:57 +02:00
$orgName = mb_strtoupper ( $piece );
2021-10-15 12:21:03 +02:00
$orgId = isset ( $orgByName [ $orgName ]) ? $orgByName [ $orgName ] : null ;
2018-07-19 11:48:22 +02:00
}
2021-08-11 23:17:57 +02:00
if ( $orgId ) {
$test [ 'OR' ][] = array ( 'Event.orgc_id' => $orgId );
2018-07-19 11:48:22 +02:00
} else {
2021-10-15 19:22:53 +02:00
$nothing = true ;
2018-07-19 11:48:22 +02:00
}
}
}
2021-08-11 22:50:01 +02:00
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = $test ;
break ;
case 'sharinggroup' :
$pieces = explode ( '|' , $v );
$test = array ();
foreach ( $pieces as $piece ) {
2021-09-13 23:58:10 +02:00
if ( $piece [ 0 ] === '!' ) {
2021-08-11 22:50:01 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.sharing_group_id !=' => substr ( $piece , 1 ));
} else {
$test [ 'OR' ][] = array ( 'Event.sharing_group_id' => $piece );
2018-07-19 11:48:22 +02:00
}
2021-08-11 22:50:01 +02:00
}
if ( ! empty ( $test )) {
2018-07-19 11:48:22 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = $test ;
2021-08-11 22:50:01 +02:00
}
break ;
case 'eventinfo' :
if ( $v == " " ) {
continue 2 ;
}
// if the first character is '!', search for NOT LIKE the rest of the string (excluding the '!' itself of course)
$pieces = explode ( '|' , $v );
$test = array ();
foreach ( $pieces as $piece ) {
2021-10-15 19:09:02 +02:00
if ( $piece [ 0 ] === '!' ) {
2021-09-13 23:58:10 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'lower(Event.info) NOT LIKE' => '%' . mb_strtolower ( substr ( $piece , 1 )) . '%' );
2018-07-19 11:48:22 +02:00
} else {
2021-09-13 23:58:10 +02:00
$test [ 'OR' ][] = array ( 'lower(Event.info) LIKE' => '%' . mb_strtolower ( $piece ) . '%' );
2018-07-19 11:48:22 +02:00
}
2021-08-11 22:50:01 +02:00
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = $test ;
break ;
case 'tag' :
case 'tags' :
if ( ! $v || ! Configure :: read ( 'MISP.tagging' ) || $v === 0 ) {
continue 2 ;
}
$pieces = is_array ( $v ) ? $v : explode ( '|' , $v );
$filterString = " " ;
$expectOR = false ;
$tagRules = [];
foreach ( $pieces as $piece ) {
2021-09-13 23:58:10 +02:00
if ( $piece [ 0 ] === '!' ) {
2021-08-11 22:50:01 +02:00
if ( is_numeric ( substr ( $piece , 1 ))) {
2021-09-13 23:58:10 +02:00
$conditions = array ( 'Tag.id' => substr ( $piece , 1 ));
2021-08-11 22:50:01 +02:00
} else {
2021-09-13 23:58:10 +02:00
$conditions = array ( 'Tag.name' => substr ( $piece , 1 ));
2021-08-11 22:50:01 +02:00
}
$tagName = $this -> Event -> EventTag -> Tag -> find ( 'first' , array (
'conditions' => $conditions ,
'fields' => array ( 'id' , 'name' ),
'recursive' => - 1 ,
));
2018-07-19 11:48:22 +02:00
2021-08-11 22:50:01 +02:00
if ( empty ( $tagName )) {
2018-07-19 11:48:22 +02:00
if ( $filterString != " " ) {
$filterString .= " | " ;
}
2021-08-11 22:50:01 +02:00
$filterString .= '!' . $piece ;
continue ;
}
2021-10-15 19:09:02 +02:00
$tagRules [ 'block' ][] = $tagName [ 'Tag' ][ 'id' ];
2021-08-11 22:50:01 +02:00
if ( $filterString != " " ) {
$filterString .= " | " ;
}
2021-10-15 19:09:02 +02:00
$filterString .= '!' . $tagName [ 'Tag' ][ 'name' ];
2021-08-11 22:50:01 +02:00
} else {
$expectOR = true ;
if ( is_numeric ( $piece )) {
2021-09-13 23:58:10 +02:00
$conditions = array ( 'Tag.id' => $piece );
2018-07-19 11:48:22 +02:00
} else {
2021-09-13 23:58:10 +02:00
$conditions = array ( 'Tag.name' => $piece );
2021-08-11 22:50:01 +02:00
}
$tagName = $this -> Event -> EventTag -> Tag -> find ( 'first' , array (
'conditions' => $conditions ,
'fields' => array ( 'id' , 'name' ),
'recursive' => - 1 ,
));
if ( empty ( $tagName )) {
2018-07-19 11:48:22 +02:00
if ( $filterString != " " ) {
$filterString .= " | " ;
}
2021-08-11 22:50:01 +02:00
$filterString .= $piece ;
continue ;
2018-07-19 11:48:22 +02:00
}
2021-10-15 19:09:02 +02:00
$tagRules [ 'include' ][] = $tagName [ 'Tag' ][ 'id' ];
2018-07-19 11:48:22 +02:00
if ( $filterString != " " ) {
2021-08-11 22:50:01 +02:00
$filterString .= " | " ;
2018-07-19 11:48:22 +02:00
}
2021-10-15 19:09:02 +02:00
$filterString .= $tagName [ 'Tag' ][ 'name' ];
2021-08-11 22:50:01 +02:00
}
}
2021-10-15 19:09:02 +02:00
if ( ! empty ( $tagRules [ 'block' ])) {
$block = $this -> Event -> EventTag -> find ( 'column' , array (
'conditions' => array ( 'EventTag.tag_id' => $tagRules [ 'block' ]),
'fields' => [ 'EventTag.event_id' ],
));
2021-10-15 19:22:53 +02:00
if ( ! empty ( $block )) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = 'Event.id NOT IN (' . implode ( " , " , $block ) . ')' ;
}
2021-10-15 19:09:02 +02:00
}
if ( ! empty ( $tagRules [ 'include' ])) {
$include = $this -> Event -> EventTag -> find ( 'column' , array (
'conditions' => array ( 'EventTag.tag_id' => $tagRules [ 'include' ]),
'fields' => [ 'EventTag.event_id' ],
));
2021-10-15 19:22:53 +02:00
if ( ! empty ( $include )) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = 'Event.id IN (' . implode ( " , " , $include ) . ')' ;
} else {
$nothing = true ;
}
} else if ( $expectOR ) {
// If we have a list of OR-d arguments, we expect to end up with a list of allowed event IDs
// If we don't however, it means that none of the tags was found. To prevent displaying the entire event index in this case:
$nothing = true ;
2021-10-15 19:09:02 +02:00
}
2021-08-11 22:50:01 +02:00
$v = $filterString ;
break ;
case 'email' :
2021-10-15 16:30:50 +02:00
if ( $v == " " ) {
2021-08-11 22:50:01 +02:00
continue 2 ;
}
2021-10-15 16:30:50 +02:00
if ( ! $this -> _isSiteAdmin ()) {
// Special case to filter own events
if ( strtolower ( $this -> Auth -> user ( 'email' )) === strtolower ( trim ( $v ))) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = [ 'Event.user_id' => $this -> Auth -> user ( 'id' )];
break ;
} else {
2021-10-15 19:22:53 +02:00
$nothing = true ;
2021-10-15 16:30:50 +02:00
continue 2 ;
}
}
2021-08-11 22:50:01 +02:00
// if the first character is '!', search for NOT LIKE the rest of the string (excluding the '!' itself of course)
$pieces = explode ( '|' , $v );
2021-10-15 17:02:20 +02:00
$usersToMatch = array ();
$positiveQuery = false ;
2021-08-11 22:50:01 +02:00
foreach ( $pieces as $piece ) {
2021-08-11 23:17:57 +02:00
if ( $piece [ 0 ] === '!' ) {
$users = $this -> Event -> User -> find ( 'column' , array (
'fields' => array ( 'User.id' ),
2021-09-13 23:58:10 +02:00
'conditions' => array ( 'User.email LIKE' => '%' . strtolower ( substr ( $piece , 1 )) . '%' )
2021-08-11 22:50:01 +02:00
));
if ( ! empty ( $users )) {
2021-08-11 23:17:57 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.user_id !=' => $users );
2021-08-11 22:50:01 +02:00
}
} else {
2021-10-15 17:02:20 +02:00
$positiveQuery = true ;
2021-08-11 23:17:57 +02:00
$users = $this -> Event -> User -> find ( 'column' , array (
'fields' => array ( 'User.id' ),
2021-09-13 23:58:10 +02:00
'conditions' => array ( 'User.email LIKE' => '%' . strtolower ( $piece ) . '%' )
2021-08-11 22:50:01 +02:00
));
2021-10-15 17:02:20 +02:00
$usersToMatch = array_merge ( $usersToMatch , $users );
2018-07-19 11:48:22 +02:00
}
2021-08-11 22:50:01 +02:00
}
2021-10-15 17:02:20 +02:00
if ( $positiveQuery ) {
2021-10-15 19:22:53 +02:00
if ( empty ( $usersToMatch )) {
$nothing = true ;
} else {
2022-05-18 10:06:17 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = [ 'Event.user_id' => array_unique ( $usersToMatch , SORT_REGULAR )];
2021-10-15 19:22:53 +02:00
}
2021-08-11 22:50:01 +02:00
}
break ;
case 'distribution' :
case 'analysis' :
case 'threatlevel' :
if ( $v == " " ) {
2018-07-19 11:48:22 +02:00
continue 2 ;
2021-08-11 22:50:01 +02:00
}
$filterString = " " ;
$searchTermInternal = $searchTerm ;
if ( $searchTerm === 'threatlevel' ) {
$searchTermInternal = 'threat_level_id' ;
$terms = $this -> Event -> ThreatLevel -> listThreatLevels ();
} elseif ( $searchTerm === 'analysis' ) {
$terms = $this -> Event -> analysisLevels ;
} else {
$terms = $this -> Event -> distributionLevels ;
}
2021-09-13 23:58:10 +02:00
$pieces = is_array ( $v ) ? $v : explode ( '|' , $v );
2021-08-11 22:50:01 +02:00
$test = array ();
foreach ( $pieces as $piece ) {
if ( $filterString != " " ) {
$filterString .= '|' ;
}
2021-08-11 23:17:57 +02:00
if ( $piece [ 0 ] === '!' ) {
2021-08-11 22:50:01 +02:00
$filterString .= $terms [ substr ( $piece , 1 )];
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.' . $searchTermInternal . ' !=' => substr ( $piece , 1 ));
} else {
$filterString .= $terms [ $piece ];
$test [ 'OR' ][] = array ( 'Event.' . $searchTermInternal => $piece );
}
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = $test ;
$v = $filterString ;
break ;
case 'minimal' :
$tableName = $this -> Event -> EventReport -> table ;
2021-10-15 17:30:20 +02:00
$eventReportQuery = sprintf ( 'EXISTS (SELECT id FROM %s WHERE %s.event_id = Event.id AND %s.deleted = 0)' , $tableName , $tableName , $tableName );
2021-08-11 22:50:01 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = [
'OR' => [
[ 'Event.attribute_count >' => 0 ],
[ $eventReportQuery ]
]
];
2023-05-02 09:49:48 +02:00
break ;
case 'value' :
if ( $v == " " ) {
continue 2 ;
}
$conditions [ 'OR' ] = [
[ 'Attribute.value1' => $v ],
[ 'Attribute.value2' => $v ],
];
$eventIds = $this -> Event -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array (
'conditions' => $conditions ,
'flatten' => true ,
'event_ids' => true ,
'list' => true ,
));
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.id' => $eventIds );
2021-08-11 22:50:01 +02:00
break ;
default :
continue 2 ;
2018-07-19 11:48:22 +02:00
}
2021-08-11 22:50:01 +02:00
$passedArgsArray [ $searchTerm ] = $v ;
2018-07-19 11:48:22 +02:00
}
2019-08-02 14:38:28 +02:00
return $passedArgsArray ;
}
public function index ()
{
// list the events
$urlparams = " " ;
2023-05-02 09:49:48 +02:00
$overrideAbleParams = array ( 'all' , 'attribute' , 'published' , 'eventid' , 'datefrom' , 'dateuntil' , 'org' , 'eventinfo' , 'tag' , 'tags' , 'distribution' , 'sharinggroup' , 'analysis' , 'threatlevel' , 'email' , 'hasproposal' , 'timestamp' , 'publishtimestamp' , 'publish_timestamp' , 'minimal' , 'value' );
2019-08-02 14:38:28 +02:00
$paginationParams = array ( 'limit' , 'page' , 'sort' , 'direction' , 'order' );
$passedArgs = $this -> passedArgs ;
2021-09-30 19:41:15 +02:00
if ( ! empty ( $this -> request -> data )) {
2019-08-02 14:38:28 +02:00
if ( isset ( $this -> request -> data [ 'request' ])) {
$this -> request -> data = $this -> request -> data [ 'request' ];
}
foreach ( $this -> request -> data as $k => $v ) {
2021-09-30 19:41:15 +02:00
if ( substr ( $k , 0 , 6 ) === 'search' && in_array ( strtolower ( substr ( $k , 6 )), $overrideAbleParams , true )) {
2019-08-02 14:38:28 +02:00
unset ( $this -> request -> data [ $k ]);
$this -> request -> data [ strtolower ( substr ( $k , 6 ))] = $v ;
2021-09-30 19:41:15 +02:00
} else if ( in_array ( strtolower ( $k ), $overrideAbleParams , true )) {
2019-08-02 14:38:28 +02:00
unset ( $this -> request -> data [ $k ]);
$this -> request -> data [ strtolower ( $k )] = $v ;
}
}
foreach ( $overrideAbleParams as $oap ) {
if ( isset ( $this -> request -> data [ $oap ])) {
$passedArgs [ 'search' . $oap ] = $this -> request -> data [ $oap ];
}
}
foreach ( $paginationParams as $paginationParam ) {
if ( isset ( $this -> request -> data [ $paginationParam ])) {
$passedArgs [ $paginationParam ] = $this -> request -> data [ $paginationParam ];
}
}
}
2021-01-17 10:50:43 +01:00
2019-08-02 14:38:28 +02:00
// check each of the passed arguments whether they're a filter (could also be a sort for example) and if yes, add it to the pagination conditions
2021-10-15 19:22:53 +02:00
$nothing = false ;
$passedArgsArray = $this -> __setIndexFilterConditions ( $passedArgs , $urlparams , $nothing );
2018-07-19 11:48:22 +02:00
$this -> loadModel ( 'GalaxyCluster' );
2019-07-08 11:39:41 +02:00
2018-07-19 11:48:22 +02:00
// for REST, don't use the pagination. With this, we'll escape the limit of events shown on the index.
if ( $this -> _isRest ()) {
2021-10-15 19:22:53 +02:00
if ( $nothing ) {
return $this -> RestResponse -> viewData ([], $this -> response -> type (), false , false , false , [ 'X-Result-Count' => 0 ]);
}
2021-07-21 10:13:47 +02:00
return $this -> __indexRestResponse ( $passedArgs );
2018-07-19 11:48:22 +02:00
}
2021-01-17 10:50:43 +01:00
$this -> paginate [ 'contain' ][ 'ThreatLevel' ] = [
'fields' => array ( 'ThreatLevel.name' )
];
2021-10-25 09:15:23 +02:00
$this -> paginate [ 'contain' ][ 'EventTag' ] = [
2022-10-03 12:14:46 +02:00
'fields' => [ 'EventTag.event_id' , 'EventTag.tag_id' , 'EventTag.local' , 'EventTag.relationship_type' ],
2021-10-25 09:15:23 +02:00
];
2021-01-17 11:45:22 +01:00
if ( $this -> _isSiteAdmin ()) {
$this -> paginate [ 'contain' ][] = 'User.email' ;
}
2020-08-21 15:43:27 +02:00
2021-10-15 19:22:53 +02:00
if ( $nothing ) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = [ 'Event.id' => - 1 ]; // do not fetch any event
}
2024-01-04 19:56:11 +01:00
$this -> Event -> includeAnalystData = true ;
2024-01-19 17:54:06 +01:00
$this -> paginate [ 'includeAnalystData' ] = true ;
2021-01-17 10:38:20 +01:00
$events = $this -> paginate ();
if ( count ( $events ) === 1 && isset ( $this -> passedArgs [ 'searchall' ])) {
$this -> redirect ( array ( 'controller' => 'events' , 'action' => 'view' , $events [ 0 ][ 'Event' ][ 'id' ]));
2018-07-19 11:48:22 +02:00
}
2021-01-17 10:38:20 +01:00
2021-03-20 11:40:41 +01:00
list ( $possibleColumns , $enabledColumns ) = $this -> __indexColumns ();
$events = $this -> __attachInfoToEvents ( $enabledColumns , $events );
2021-02-08 17:13:25 +01:00
$this -> __noKeyNotification ();
2021-01-17 10:38:20 +01:00
$this -> set ( 'events' , $events );
2021-03-20 11:40:41 +01:00
$this -> set ( 'possibleColumns' , $possibleColumns );
$this -> set ( 'columns' , $enabledColumns );
2018-07-19 11:48:22 +02:00
$this -> set ( 'eventDescriptions' , $this -> Event -> fieldDescriptions );
$this -> set ( 'analysisLevels' , $this -> Event -> analysisLevels );
$this -> set ( 'distributionLevels' , $this -> Event -> distributionLevels );
$this -> set ( 'shortDist' , $this -> Event -> shortDist );
2022-05-15 11:29:12 +02:00
$this -> set ( 'distributionData' , $this -> __genDistributionGraph ( - 1 ));
2021-01-17 10:38:20 +01:00
$this -> set ( 'urlparams' , $urlparams );
$this -> set ( 'passedArgsArray' , $passedArgsArray );
2021-01-17 10:50:43 +01:00
$this -> set ( 'passedArgs' , json_encode ( $passedArgs ));
2021-01-17 10:38:20 +01:00
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'ajax' )) {
$this -> autoRender = false ;
$this -> layout = false ;
$this -> render ( 'ajax/index' );
}
}
2021-07-21 10:13:47 +02:00
/**
* @ param array $passedArgs
* @ return CakeResponse
*/
2021-09-30 19:41:15 +02:00
private function __indexRestResponse ( array $passedArgs )
2021-07-21 10:13:47 +02:00
{
2022-10-29 21:03:29 +02:00
// We do not want to allow instances to pull our data that can't make sense of protected mode events
$skipProtected = (
! empty ( $this -> request -> header ( 'misp-version' )) &&
version_compare ( $this -> request -> header ( 'misp-version' ), '2.4.156' ) < 0
);
2021-10-15 20:23:37 +02:00
$fieldNames = $this -> Event -> schema ();
$minimal = ! empty ( $passedArgs [ 'searchminimal' ]) || ! empty ( $passedArgs [ 'minimal' ]);
if ( $minimal ) {
$rules = [
'recursive' => - 1 ,
2022-03-15 22:59:52 +01:00
'fields' => array ( 'id' , 'timestamp' , 'sighting_timestamp' , 'published' , 'uuid' , 'protected' ),
2022-10-29 21:03:29 +02:00
'contain' => array ( 'Orgc.uuid' ),
2021-10-15 20:23:37 +02:00
];
} else {
// Remove user ID from fetched fields
unset ( $fieldNames [ 'user_id' ]);
$rules = [
2022-10-29 21:03:29 +02:00
'contain' => [ 'EventTag' ],
2021-10-15 20:23:37 +02:00
'fields' => array_keys ( $fieldNames ),
2024-01-19 17:54:06 +01:00
'includeAnalystData' => isset ( $passedArgs [ 'includeAnalystData' ]) ? $passedArgs [ 'includeAnalystData' ] : true ,
2021-10-15 20:23:37 +02:00
];
}
if ( isset ( $passedArgs [ 'sort' ]) && isset ( $fieldNames [ $passedArgs [ 'sort' ]])) {
2021-09-30 19:41:15 +02:00
if ( isset ( $passedArgs [ 'direction' ]) && in_array ( strtoupper ( $passedArgs [ 'direction' ]), [ 'ASC' , 'DESC' ])) {
2021-07-21 10:13:47 +02:00
$rules [ 'order' ] = array ( 'Event.' . $passedArgs [ 'sort' ] => $passedArgs [ 'direction' ]);
} else {
$rules [ 'order' ] = array ( 'Event.' . $passedArgs [ 'sort' ] => 'ASC' );
}
}
if ( isset ( $this -> paginate [ 'conditions' ])) {
$rules [ 'conditions' ] = $this -> paginate [ 'conditions' ];
}
2022-10-29 21:03:29 +02:00
if ( $skipProtected ) {
$rules [ 'conditions' ][ 'Event.protected' ] = 0 ;
}
2021-07-21 10:13:47 +02:00
$paginationRules = array ( 'page' , 'limit' , 'sort' , 'direction' , 'order' );
foreach ( $paginationRules as $paginationRule ) {
if ( isset ( $passedArgs [ $paginationRule ])) {
$rules [ $paginationRule ] = $passedArgs [ $paginationRule ];
}
}
if ( empty ( $rules [ 'limit' ])) {
2024-01-28 15:41:02 +01:00
$events = [];
2021-07-21 10:13:47 +02:00
$i = 1 ;
$rules [ 'limit' ] = 20000 ;
while ( true ) {
2024-01-28 15:41:02 +01:00
$rules [ 'page' ] = $i ++ ;
2021-07-21 10:13:47 +02:00
$temp = $this -> Event -> find ( 'all' , $rules );
$resultCount = count ( $temp );
if ( $resultCount !== 0 ) {
2024-01-28 15:41:02 +01:00
array_push ( $events , ... $temp );
2021-07-21 10:13:47 +02:00
}
if ( $resultCount < $rules [ 'limit' ]) {
break ;
}
}
unset ( $temp );
2024-01-28 15:41:02 +01:00
$absoluteTotal = count ( $events );
2021-07-21 10:13:47 +02:00
} else {
$counting_rules = $rules ;
unset ( $counting_rules [ 'limit' ]);
unset ( $counting_rules [ 'page' ]);
2024-01-28 15:41:02 +01:00
$absoluteTotal = $this -> Event -> find ( 'count' , $counting_rules );
2021-07-21 10:13:47 +02:00
2024-01-28 15:41:02 +01:00
$events = $absoluteTotal === 0 ? [] : $this -> Event -> find ( 'all' , $rules );
2021-07-21 10:13:47 +02:00
}
2022-10-29 21:03:29 +02:00
2021-07-22 11:41:55 +02:00
$isCsvResponse = $this -> response -> type () === 'text/csv' ;
2022-10-29 21:03:29 +02:00
$protectedEventsByInstanceKey = $this -> Event -> CryptographicKey -> protectedEventsByInstanceKey ( $events );
$protectedEventsByInstanceKey = array_flip ( $protectedEventsByInstanceKey );
2021-07-21 10:13:47 +02:00
if ( ! $minimal ) {
// Collect all tag IDs that are events
$tagIds = [];
foreach ( array_column ( $events , 'EventTag' ) as $eventTags ) {
foreach ( array_column ( $eventTags , 'tag_id' ) as $tagId ) {
$tagIds [ $tagId ] = true ;
}
}
if ( ! empty ( $tagIds )) {
$tags = $this -> Event -> EventTag -> Tag -> find ( 'all' , [
'conditions' => [
'Tag.id' => array_keys ( $tagIds ),
'Tag.exportable' => 1 ,
],
'recursive' => - 1 ,
'fields' => [ 'Tag.id' , 'Tag.name' , 'Tag.colour' , 'Tag.is_galaxy' ],
]);
unset ( $tagIds );
$tags = array_column ( array_column ( $tags , 'Tag' ), null , 'id' );
foreach ( $events as $k => $event ) {
if ( empty ( $event [ 'EventTag' ])) {
continue ;
}
foreach ( $event [ 'EventTag' ] as $k2 => $et ) {
if ( ! isset ( $tags [ $et [ 'tag_id' ]])) {
unset ( $events [ $k ][ 'EventTag' ][ $k2 ]); // tag not exists or is not exportable
} else {
$events [ $k ][ 'EventTag' ][ $k2 ][ 'Tag' ] = $tags [ $et [ 'tag_id' ]];
}
}
$events [ $k ][ 'EventTag' ] = array_values ( $events [ $k ][ 'EventTag' ]);
}
2021-07-22 11:41:55 +02:00
if ( ! $isCsvResponse ) {
$events = $this -> GalaxyCluster -> attachClustersToEventIndex ( $this -> Auth -> user (), $events , false );
}
2021-07-21 10:13:47 +02:00
}
2021-07-21 12:07:48 +02:00
// Fetch all org and sharing groups that are in events
$orgIds = [];
$sharingGroupIds = [];
2022-03-15 22:59:52 +01:00
foreach ( $events as $k => $event ) {
2021-07-21 12:07:48 +02:00
$orgIds [ $event [ 'Event' ][ 'org_id' ]] = true ;
$orgIds [ $event [ 'Event' ][ 'orgc_id' ]] = true ;
$sharingGroupIds [ $event [ 'Event' ][ 'sharing_group_id' ]] = true ;
2022-10-29 21:03:29 +02:00
if ( $event [ 'Event' ][ 'protected' ] && ! isset ( $protectedEventsByInstanceKey [ $event [ 'Event' ][ 'id' ]])) {
2022-03-15 22:59:52 +01:00
unset ( $events [ $k ]);
}
2021-07-21 12:07:48 +02:00
}
2022-03-15 22:59:52 +01:00
$events = array_values ( $events );
2021-07-21 12:07:48 +02:00
if ( ! empty ( $orgIds )) {
$orgs = $this -> Event -> Org -> find ( 'all' , [
'conditions' => [ 'Org.id' => array_keys ( $orgIds )],
'recursive' => - 1 ,
'fields' => $this -> paginate [ 'contain' ][ 'Org' ][ 'fields' ],
]);
unset ( $orgIds );
$orgs = array_column ( array_column ( $orgs , 'Org' ), null , 'id' );
} else {
$orgs = [];
}
unset ( $sharingGroupIds [ 0 ]);
if ( ! empty ( $sharingGroupIds )) {
$sharingGroups = $this -> Event -> SharingGroup -> find ( 'all' , [
'conditions' => [ 'SharingGroup.id' => array_keys ( $sharingGroupIds )],
'recursive' => - 1 ,
'fields' => $this -> paginate [ 'contain' ][ 'SharingGroup' ][ 'fields' ],
]);
unset ( $sharingGroupIds );
$sharingGroups = array_column ( array_column ( $sharingGroups , 'SharingGroup' ), null , 'id' );
}
foreach ( $events as $key => $event ) {
2021-07-21 10:13:47 +02:00
$temp = $event [ 'Event' ];
$temp [ 'Org' ] = $orgs [ $temp [ 'org_id' ]];
$temp [ 'Orgc' ] = $orgs [ $temp [ 'orgc_id' ]];
2021-07-21 12:07:48 +02:00
if ( $temp [ 'sharing_group_id' ] != 0 ) {
$temp [ 'SharingGroup' ] = $sharingGroups [ $temp [ 'sharing_group_id' ]];
}
$rearrangeObjects = array ( 'GalaxyCluster' , 'EventTag' );
2021-07-21 10:13:47 +02:00
foreach ( $rearrangeObjects as $ro ) {
if ( isset ( $event [ $ro ])) {
$temp [ $ro ] = $event [ $ro ];
}
}
$events [ $key ] = $temp ;
}
2021-07-21 12:26:19 +02:00
unset ( $sharingGroups );
unset ( $orgs );
2021-07-21 10:13:47 +02:00
if ( $this -> response -> type () === 'application/xml' ) {
$events = array ( 'Event' => $events );
}
2022-10-29 21:03:29 +02:00
} else { // minimal
2021-07-21 10:13:47 +02:00
foreach ( $events as $key => $event ) {
2022-10-29 21:03:29 +02:00
if ( $event [ 'Event' ][ 'protected' ] && ! isset ( $protectedEventsByInstanceKey [ $event [ 'Event' ][ 'id' ]])) {
2022-03-15 22:59:52 +01:00
unset ( $events [ $key ]);
continue ;
}
2021-07-21 10:13:47 +02:00
$event [ 'Event' ][ 'orgc_uuid' ] = $event [ 'Orgc' ][ 'uuid' ];
2022-03-15 22:59:52 +01:00
unset ( $event [ 'Event' ][ 'protected' ]);
2021-07-21 10:13:47 +02:00
$events [ $key ] = $event [ 'Event' ];
}
2022-03-15 22:59:52 +01:00
$events = array_values ( $events );
2021-07-21 10:13:47 +02:00
}
2021-07-22 11:41:55 +02:00
if ( $isCsvResponse ) {
App :: uses ( 'CsvExport' , 'Export' );
$export = new CsvExport ();
$events = $export -> eventIndex ( $events );
}
2024-01-28 15:41:02 +01:00
return $this -> RestResponse -> viewData ( $events , $this -> response -> type (), false , false , false , [ 'X-Result-Count' => $absoluteTotal ]);
2021-07-21 10:13:47 +02:00
}
2021-03-20 11:40:41 +01:00
private function __indexColumns ()
{
$possibleColumns = [];
if ( $this -> _isSiteAdmin () && ! Configure :: read ( 'MISP.showorgalternate' )) {
$possibleColumns [] = 'owner_org' ;
}
if ( Configure :: read ( 'MISP.tagging' )) {
$possibleColumns [] = 'clusters' ;
$possibleColumns [] = 'tags' ;
}
$possibleColumns [] = 'attribute_count' ;
if ( Configure :: read ( 'MISP.showCorrelationsOnIndex' )) {
$possibleColumns [] = 'correlations' ;
}
2022-09-21 10:10:42 +02:00
if ( Configure :: read ( 'MISP.showEventReportCountOnIndex' )) {
$possibleColumns [] = 'report_count' ;
}
2021-03-20 11:40:41 +01:00
if ( Configure :: read ( 'MISP.showSightingsCountOnIndex' )) {
$possibleColumns [] = 'sightings' ;
}
if ( Configure :: read ( 'MISP.showProposalsCountOnIndex' )) {
$possibleColumns [] = 'proposals' ;
}
2022-11-14 14:23:04 +01:00
if ( Configure :: read ( 'MISP.showDiscussionsCountOnIndex' ) && ! Configure :: read ( 'MISP.discussion_disable' )) {
2021-03-20 11:40:41 +01:00
$possibleColumns [] = 'discussion' ;
}
if ( $this -> _isSiteAdmin ()) {
$possibleColumns [] = 'creator_user' ;
}
2022-09-21 10:10:42 +02:00
$possibleColumns [] = 'timestamp' ;
$possibleColumns [] = 'publish_timestamp' ;
2021-12-06 14:27:29 +01:00
$userDisabledColumns = $this -> User -> UserSetting -> getValueForUser ( $this -> Auth -> user ()[ 'id' ], 'event_index_hide_columns' );
if ( $userDisabledColumns === null ) {
$userDisabledColumns = self :: DEFAULT_HIDDEN_INDEX_COLUMNS ;
2021-03-20 11:40:41 +01:00
}
2021-12-06 14:27:29 +01:00
$enabledColumns = array_diff ( $possibleColumns , $userDisabledColumns );
2021-03-20 11:40:41 +01:00
return [ $possibleColumns , $enabledColumns ];
}
private function __attachInfoToEvents ( array $columns , array $events )
{
2022-02-18 12:17:32 +01:00
if ( empty ( $events )) {
return [];
}
2021-03-20 11:40:41 +01:00
$user = $this -> Auth -> user ();
if ( in_array ( 'tags' , $columns , true ) || in_array ( 'clusters' , $columns , true )) {
$events = $this -> Event -> attachTagsToEvents ( $events );
$events = $this -> GalaxyCluster -> attachClustersToEventIndex ( $user , $events , true );
2022-11-30 15:07:41 +01:00
$events = $this -> __attachHighlightedTagsToEvents ( $events );
2021-03-20 11:40:41 +01:00
}
if ( in_array ( 'correlations' , $columns , true )) {
$events = $this -> Event -> attachCorrelationCountToEvents ( $user , $events );
}
if ( in_array ( 'sightings' , $columns , true )) {
$events = $this -> Event -> attachSightingsCountToEvents ( $user , $events );
}
if ( in_array ( 'proposals' , $columns , true )) {
$events = $this -> Event -> attachProposalsCountToEvents ( $user , $events );
}
2022-11-14 14:23:04 +01:00
if ( in_array ( 'discussion' , $columns , true ) && ! Configure :: read ( 'MISP.discussion_disable' )) {
2021-03-20 11:40:41 +01:00
$events = $this -> Event -> attachDiscussionsCountToEvents ( $user , $events );
}
2021-05-07 14:09:34 +02:00
if ( in_array ( 'report_count' , $columns , true )) {
$events = $this -> Event -> EventReport -> attachReportCountsToEvents ( $user , $events );
}
2021-03-20 11:40:41 +01:00
return $events ;
}
2021-02-08 17:13:25 +01:00
private function __noKeyNotification ()
{
$onlyEncrypted = Configure :: read ( 'GnuPG.onlyencrypted' );
$bodyOnlyEncrypted = Configure :: read ( 'GnuPG.bodyonlyencrypted' );
if ( ! $onlyEncrypted && ! $bodyOnlyEncrypted ) {
return ;
}
$user = $this -> Event -> User -> fillKeysToUser ( $this -> Auth -> user ());
if ( ! empty ( $user [ 'gpgkey' ])) {
return ; // use has PGP key
}
if ( $onlyEncrypted ) {
if ( Configure :: read ( 'SMIME.enabled' ) && empty ( $user [ 'certif_public' ])) {
$this -> Flash -> info ( __ ( 'No X.509 certificate or PGP key set in your profile. To receive emails, submit your public certificate or PGP key in your profile.' ));
} elseif ( ! Configure :: read ( 'SMIME.enabled' )) {
$this -> Flash -> info ( __ ( 'No PGP key set in your profile. To receive emails, submit your public key in your profile.' ));
}
} elseif ( $bodyOnlyEncrypted && $user [ 'autoalert' ]) {
if ( Configure :: read ( 'SMIME.enabled' ) && empty ( $user [ 'certif_public' ])) {
$this -> Flash -> info ( __ ( 'No X.509 certificate or PGP key set in your profile. To receive attributes in emails, submit your public certificate or PGP key in your profile.' ));
} elseif ( ! Configure :: read ( 'SMIME.enabled' )) {
$this -> Flash -> info ( __ ( 'No PGP key set in your profile. To receive attributes in emails, submit your public key in your profile.' ));
}
}
}
2018-07-19 11:48:22 +02:00
public function filterEventIndex ()
{
$passedArgsArray = array ();
$filtering = array (
'published' => 2 ,
'org' => array ( 'OR' => array (), 'NOT' => array ()),
'tag' => array ( 'OR' => array (), 'NOT' => array ()),
'eventid' => array ( 'OR' => array (), 'NOT' => array ()),
'date' => array ( 'from' => " " , 'until' => " " ),
'eventinfo' => array ( 'OR' => array (), 'NOT' => array ()),
2022-04-06 10:07:10 +02:00
'all' => array ( 'OR' => array (), 'NOT' => array ()),
2018-07-19 11:48:22 +02:00
'threatlevel' => array ( 'OR' => array (), 'NOT' => array ()),
'distribution' => array ( 'OR' => array (), 'NOT' => array ()),
'sharinggroup' => array ( 'OR' => array (), 'NOT' => array ()),
'analysis' => array ( 'OR' => array (), 'NOT' => array ()),
'attribute' => array ( 'OR' => array (), 'NOT' => array ()),
'hasproposal' => 2 ,
2021-12-06 16:01:12 +01:00
'timestamp' => array ( 'from' => " " , 'until' => " " ),
2023-09-24 19:29:43 +02:00
'publishtimestamp' => array ( 'from' => " " , 'until' => " " )
2018-07-19 11:48:22 +02:00
);
if ( $this -> _isSiteAdmin ()) {
$filtering [ 'email' ] = array ( 'OR' => array (), 'NOT' => array ());
}
foreach ( $this -> passedArgs as $k => $v ) {
if ( substr ( $k , 0 , 6 ) === 'search' ) {
$searchTerm = substr ( $k , 6 );
switch ( $searchTerm ) {
case 'published' :
case 'hasproposal' :
$filtering [ $searchTerm ] = $v ;
break ;
case 'Datefrom' :
$filtering [ 'date' ][ 'from' ] = $v ;
break ;
case 'Dateuntil' :
$filtering [ 'date' ][ 'until' ] = $v ;
break ;
case 'email' :
case 'org' :
case 'eventid' :
case 'tag' :
case 'eventinfo' :
case 'attribute' :
case 'threatlevel' :
case 'distribution' :
case 'sharinggroup' :
case 'analysis' :
if ( $v == " " || ( $searchTerm == 'email' && ! $this -> _isSiteAdmin ())) {
continue 2 ;
}
$pieces = explode ( '|' , $v );
foreach ( $pieces as $piece ) {
if ( $piece [ 0 ] == '!' ) {
$filtering [ $searchTerm ][ 'NOT' ][] = substr ( $piece , 1 );
} else {
$filtering [ $searchTerm ][ 'OR' ][] = $piece ;
}
}
break ;
}
$passedArgsArray [ $searchTerm ] = $v ;
}
}
$this -> set ( 'filtering' , json_encode ( $filtering ));
2021-03-20 20:02:00 +01:00
$tagNames = $this -> Event -> EventTag -> Tag -> find ( 'list' , [
'fields' => [ 'Tag.id' , 'Tag.name' ],
]);
$tagJSON = [];
2021-01-17 12:06:21 +01:00
foreach ( $tagNames as $tagId => $tagName ) {
2021-03-20 20:02:00 +01:00
$tagJSON [] = array ( 'id' => $tagId , 'value' => $tagName );
2018-07-19 11:48:22 +02:00
}
2021-03-20 20:02:00 +01:00
2021-03-20 20:43:56 +01:00
$rules = [
'published' => __ ( 'Published' ),
'eventid' => __ ( 'Event ID' ),
'tag' => __ ( 'Tag' ),
'date' => __ ( 'Date' ),
'eventinfo' => __ ( 'Event info' ),
'threatlevel' => __ ( 'Threat level' ),
'distribution' => __ ( 'Distribution' ),
'sharinggroup' => __ ( 'Sharing group' ),
'analysis' => __ ( 'Analysis' ),
'attribute' => __ ( 'Attribute' ),
'hasproposal' => __ ( 'Has proposal' ),
2021-12-06 14:27:29 +01:00
'timestamp' => __ ( 'Last change at' ),
'publishtimestamp' => __ ( 'Published at' ),
2022-04-06 10:07:10 +02:00
'all' => __ ( 'Search in all fields' ),
2021-03-20 20:43:56 +01:00
];
2018-07-19 11:48:22 +02:00
if ( $this -> _isSiteAdmin ()) {
2021-03-20 20:43:56 +01:00
$rules [ 'email' ] = __ ( 'Email' );
2018-07-19 11:48:22 +02:00
}
if ( Configure :: read ( 'MISP.showorg' )) {
$orgs = $this -> Event -> Orgc -> find ( 'list' , array (
'fields' => array ( 'Orgc.id' , 'Orgc.name' ),
'sort' => array ( 'lower(Orgc.name) asc' )
));
$this -> set ( 'showorg' , true );
$this -> set ( 'orgs' , $orgs );
2021-03-20 20:43:56 +01:00
$rules [ 'org' ] = __ ( 'Organisation' );
2018-07-19 11:48:22 +02:00
} else {
$this -> set ( 'showorg' , false );
}
$sharingGroups = $this -> Event -> SharingGroup -> fetchAllAuthorised ( $this -> Auth -> user (), 'name' , true );
$this -> set ( 'sharingGroups' , $sharingGroups );
$this -> set ( 'tags' , $tagNames );
$this -> set ( 'tagJSON' , json_encode ( $tagJSON ));
$this -> set ( 'rules' , $rules );
2022-04-28 14:51:21 +02:00
$this -> layout = false ;
2018-07-19 11:48:22 +02:00
}
public function viewEventAttributes ( $id , $all = false )
{
2019-01-31 14:39:24 +01:00
$filterData = array (
2021-10-19 18:40:20 +02:00
'paramArray' => self :: ACCEPTED_FILTERING_NAMED_PARAMS ,
2021-09-30 20:08:45 +02:00
'named_params' => $this -> request -> params [ 'named' ]
2019-01-31 14:39:24 +01:00
);
2022-04-29 19:55:12 +02:00
$filters = $this -> _harvestParameters ( $filterData , $exception );
if ( $exception ) {
return $exception ;
}
2021-10-29 16:30:24 +02:00
// Remove default filters
foreach ( $filters as $filterName => $filterValue ) {
if ( isset ( self :: DEFAULT_FILTERING_RULE [ $filterName ]) && self :: DEFAULT_FILTERING_RULE [ $filterName ] == $filterValue ) {
unset ( $filters [ $filterName ]);
}
}
2019-01-31 14:39:24 +01:00
2024-01-24 21:48:53 +01:00
$this -> Event -> Attribute -> includeAnalystData = true ;
2024-02-06 10:04:20 +01:00
$this -> Event -> Attribute -> includeAnalystDataRecursive = true ;
2024-01-24 21:48:53 +01:00
2019-01-31 14:39:24 +01:00
if ( isset ( $filters [ 'focus' ])) {
$this -> set ( 'focus' , $filters [ 'focus' ]);
2018-07-19 11:48:22 +02:00
}
2021-02-21 16:26:02 +01:00
$conditions = [
'eventid' => $id ,
'includeFeedCorrelations' => true ,
'includeWarninglistHits' => true ,
'fetchFullClusters' => false ,
'includeAllTags' => true ,
'includeGranularCorrelations' => true ,
2022-04-29 14:36:06 +02:00
'includeEventCorrelations' => true , // event correlations are need for filtering
2021-02-21 16:26:02 +01:00
'noEventReports' => true , // event reports for view are loaded dynamically
'noSightings' => true ,
2022-04-30 17:34:12 +02:00
'includeServerCorrelations' => $filters [ 'includeServerCorrelations' ] ? ? 1 ,
2021-02-21 16:26:02 +01:00
];
2019-01-31 14:39:24 +01:00
if ( isset ( $filters [ 'extended' ])) {
2018-07-19 11:48:22 +02:00
$conditions [ 'extended' ] = 1 ;
$this -> set ( 'extended' , 1 );
} else {
$this -> set ( 'extended' , 0 );
}
2019-01-31 14:39:24 +01:00
if ( ! empty ( $filters [ 'overrideLimit' ])) {
2018-07-19 11:48:22 +02:00
$conditions [ 'overrideLimit' ] = 1 ;
}
2019-01-31 16:22:11 +01:00
if ( isset ( $filters [ 'deleted' ])) {
2020-11-10 14:30:28 +01:00
if ( $filters [ 'deleted' ] == 1 ) { // both
2019-09-06 11:22:14 +02:00
$conditions [ 'deleted' ] = [ 0 , 1 ];
2022-04-30 17:34:12 +02:00
} elseif ( $filters [ 'deleted' ] == 0 ) { // not-deleted only (default)
2020-11-10 14:30:28 +01:00
$conditions [ 'deleted' ] = 0 ;
2021-10-23 16:38:27 +02:00
} else { // only deleted
$conditions [ 'deleted' ] = 1 ;
2019-09-06 11:22:14 +02:00
}
2018-07-19 11:48:22 +02:00
}
2019-02-15 16:28:04 +01:00
if ( isset ( $filters [ 'toIDS' ]) && $filters [ 'toIDS' ] != 0 ) {
$conditions [ 'to_ids' ] = $filters [ 'toIDS' ] == 2 ? 0 : 1 ;
}
2019-01-31 14:39:24 +01:00
if ( ! empty ( $filters [ 'includeRelatedTags' ])) {
2018-11-23 14:11:33 +01:00
$this -> set ( 'includeRelatedTags' , 1 );
$conditions [ 'includeRelatedTags' ] = 1 ;
} else {
$this -> set ( 'includeRelatedTags' , 0 );
}
2019-08-12 16:34:26 +02:00
if ( ! empty ( $filters [ 'includeDecayScore' ])) {
$this -> set ( 'includeDecayScore' , 1 );
$conditions [ 'includeDecayScore' ] = 1 ;
} else {
$this -> set ( 'includeDecayScore' , 0 );
}
2019-01-31 16:22:11 +01:00
2021-03-10 18:27:19 +01:00
// Site admin can view event as different user
2021-09-30 20:08:45 +02:00
if ( $this -> _isSiteAdmin () && isset ( $this -> request -> params [ 'named' ][ 'viewAs' ])) {
$user = $this -> User -> getAuthUser ( $this -> request -> params [ 'named' ][ 'viewAs' ]);
2021-03-10 18:27:19 +01:00
if ( empty ( $user )) {
throw new NotFoundException ( __ ( " User not found " ));
}
} else {
$user = $this -> Auth -> user ();
}
$results = $this -> Event -> fetchEvent ( $user , $conditions );
2018-07-19 11:48:22 +02:00
if ( empty ( $results )) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$event = $results [ 0 ];
2021-10-29 14:44:19 +02:00
$emptyEvent = empty ( $event [ 'Object' ]) && empty ( $event [ 'Attribute' ]);
$this -> set ( 'emptyEvent' , $emptyEvent );
2021-10-18 16:36:03 +02:00
$attributeTagsName = $this -> Event -> Attribute -> AttributeTag -> extractAttributeTagsNameFromEvent ( $event );
2019-04-16 14:14:51 +02:00
$this -> set ( 'attributeTags' , array_values ( $attributeTagsName [ 'tags' ]));
$this -> set ( 'attributeClusters' , array_values ( $attributeTagsName [ 'clusters' ]));
2019-01-31 16:22:11 +01:00
if ( isset ( $filters [ 'distribution' ])) {
if ( ! is_array ( $filters [ 'distribution' ])) {
$filters [ 'distribution' ] = array ( $filters [ 'distribution' ]);
}
$temp = implode ( '|' , $filters [ 'distribution' ]);
2019-02-01 11:35:01 +01:00
$this -> __applyQueryString ( $event , $temp , 'distribution' );
2019-01-31 16:22:11 +01:00
}
2019-01-31 14:39:24 +01:00
if ( isset ( $filters [ 'searchFor' ]) && $filters [ 'searchFor' ] !== '' ) {
2019-02-04 16:19:11 +01:00
if ( isset ( $filters [ 'filterColumnsOverwrite' ])) {
$this -> __applyQueryString ( $event , $filters [ 'searchFor' ], $filters [ 'filterColumnsOverwrite' ]);
} else {
$this -> __applyQueryString ( $event , $filters [ 'searchFor' ]);
}
2019-01-31 14:39:24 +01:00
$this -> set ( 'passedArgsArray' , array ( 'all' => $filters [ 'searchFor' ]));
2018-07-19 11:48:22 +02:00
}
2019-02-13 14:59:49 +01:00
if ( isset ( $filters [ 'taggedAttributes' ]) && $filters [ 'taggedAttributes' ] !== '' ) {
$this -> __applyQueryString ( $event , $filters [ 'taggedAttributes' ], 'Tag.name' );
}
if ( isset ( $filters [ 'galaxyAttachedAttributes' ]) && $filters [ 'galaxyAttachedAttributes' ] !== '' ) {
$this -> __applyQueryString ( $event , $filters [ 'galaxyAttachedAttributes' ], 'Tag.name' );
}
2018-07-19 11:48:22 +02:00
// remove galaxies tags
2022-09-26 18:15:05 +02:00
$containsProposals = ! empty ( $event [ 'ShadowAttribute' ]);;
2019-11-04 11:54:22 +01:00
$this -> loadModel ( 'Taxonomy' );
2018-07-19 11:48:22 +02:00
foreach ( $event [ 'Object' ] as $k => $object ) {
2018-09-27 16:34:16 +02:00
if ( isset ( $object [ 'Attribute' ])) {
foreach ( $object [ 'Attribute' ] as $k2 => $attribute ) {
2021-10-29 14:49:06 +02:00
if ( ! empty ( $attribute [ 'AttributeTag' ])) {
2021-10-29 17:24:35 +02:00
$this -> Event -> Attribute -> removeGalaxyClusterTags ( $event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ]);
2020-05-23 17:30:00 +02:00
2021-10-29 14:49:06 +02:00
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
$event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ][ 'tagConflicts' ] = $tagConflicts ;
2019-11-04 14:55:43 +01:00
}
2022-09-26 18:15:05 +02:00
if ( ! $containsProposals && ! empty ( $attribute [ 'ShadowAttribute' ])) {
$containsProposals = true ;
}
2018-07-19 11:48:22 +02:00
}
}
}
2020-05-23 17:30:00 +02:00
2021-10-29 14:49:06 +02:00
foreach ( $event [ 'Attribute' ] as & $attribute ) {
if ( ! empty ( $attribute [ 'AttributeTag' ])) {
2021-10-29 17:24:35 +02:00
$this -> Event -> Attribute -> removeGalaxyClusterTags ( $attribute );
2021-10-29 14:49:06 +02:00
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
$attribute [ 'tagConflicts' ] = $tagConflicts ;
2019-11-04 14:55:43 +01:00
}
2022-09-26 18:15:05 +02:00
if ( ! $containsProposals && ! empty ( $attribute [ 'ShadowAttribute' ])) {
$containsProposals = true ;
}
2018-07-19 11:48:22 +02:00
}
2019-01-28 16:13:15 +01:00
if ( empty ( $this -> passedArgs [ 'sort' ])) {
2019-01-31 14:39:24 +01:00
$filters [ 'sort' ] = 'timestamp' ;
$filters [ 'direction' ] = 'desc' ;
2019-01-28 16:13:15 +01:00
}
2021-10-29 17:28:31 +02:00
$sightingsData = $this -> Event -> Sighting -> eventsStatistic ([ $event ], $user );
2019-03-01 11:54:29 +01:00
$this -> set ( 'sightingsData' , $sightingsData );
$params = $this -> Event -> rearrangeEventForView ( $event , $filters , $all , $sightingsData );
2019-11-06 21:20:04 +01:00
if ( ! empty ( $filters [ 'includeSightingdb' ]) && Configure :: read ( 'Plugin.Sightings_sighting_db_enable' )) {
$this -> loadModel ( 'Sightingdb' );
$event = $this -> Sightingdb -> attachToEvent ( $event , $this -> Auth -> user ());
}
2018-07-19 11:48:22 +02:00
$this -> params -> params [ 'paging' ] = array ( $this -> modelClass => $params );
$this -> set ( 'event' , $event );
2022-09-26 18:15:05 +02:00
$this -> set ( 'includeOrgColumn' , ( isset ( $conditions [ 'extended' ]) || $containsProposals ));
2019-11-26 12:34:22 +01:00
$this -> set ( 'includeSightingdb' , ( ! empty ( $filters [ 'includeSightingdb' ]) && Configure :: read ( 'Plugin.Sightings_sighting_db_enable' )));
2021-10-23 16:38:27 +02:00
$this -> set ( 'deleted' , isset ( $filters [ 'deleted' ]) && $filters [ 'deleted' ] != 0 );
2019-01-31 14:39:24 +01:00
$this -> set ( 'attributeFilter' , isset ( $filters [ 'attributeFilter' ]) ? $filters [ 'attributeFilter' ] : 'all' );
$this -> set ( 'filters' , $filters );
2019-02-01 16:18:34 +01:00
$advancedFiltering = $this -> __checkIfAdvancedFiltering ( $filters );
$this -> set ( 'advancedFilteringActive' , $advancedFiltering [ 'active' ] ? 1 : 0 );
$this -> set ( 'advancedFilteringActiveRules' , $advancedFiltering [ 'activeRules' ]);
2022-05-22 15:40:13 +02:00
$this -> set ( 'mayModify' , $this -> __canModifyEvent ( $event , $user ));
2022-10-22 15:47:08 +02:00
$this -> set ( 'mayPublish' , $this -> __canPublishEvent ( $event , $user ));
2021-09-02 10:19:06 +02:00
$this -> response -> disableCache ();
2021-10-19 18:40:40 +02:00
// Remove `focus` attribute from URI
$uriArray = explode ( '/' , $this -> request -> here );
2018-07-19 11:48:22 +02:00
foreach ( $uriArray as $k => $v ) {
2021-10-19 18:40:40 +02:00
if ( strpos ( $v , 'focus:' ) === 0 ) {
unset ( $uriArray [ $k ]);
2018-07-19 11:48:22 +02:00
}
2021-10-19 18:40:40 +02:00
$this -> request -> here = implode ( '/' , $uriArray );
2018-07-19 11:48:22 +02:00
}
2021-10-19 18:40:40 +02:00
2019-11-06 21:20:04 +01:00
if ( ! empty ( $filters [ 'includeSightingdb' ]) && Configure :: read ( 'Plugin.Sightings_sighting_db_enable' )) {
2022-05-22 15:40:13 +02:00
$this -> set ( 'sightingdbs' , $this -> Sightingdb -> getSightingdbList ( $user ));
2019-11-06 21:20:04 +01:00
}
2021-10-19 18:40:40 +02:00
$this -> set ( 'currentUri' , $this -> request -> here );
2018-11-23 14:11:33 +01:00
$this -> layout = false ;
2021-10-29 17:28:31 +02:00
$this -> __eventViewCommon ( $user );
2018-07-19 11:48:22 +02:00
$this -> render ( '/Elements/eventattribute' );
}
2021-03-03 10:01:36 +01:00
/**
2021-03-10 18:27:19 +01:00
* @ param array $user
2021-03-03 10:01:36 +01:00
* @ param array $event
* @ param bool $continue
* @ param int $fromEvent
*/
2021-03-10 18:27:19 +01:00
private function __viewUI ( array $user , $event , $continue , $fromEvent )
2018-07-19 11:48:22 +02:00
{
2019-11-04 11:54:22 +01:00
$this -> loadModel ( 'Taxonomy' );
2019-01-31 14:39:24 +01:00
$filterData = array (
'request' => $this -> request ,
2021-10-19 18:40:20 +02:00
'paramArray' => self :: ACCEPTED_FILTERING_NAMED_PARAMS ,
2021-09-30 20:08:45 +02:00
'named_params' => $this -> request -> params [ 'named' ]
2019-01-31 14:39:24 +01:00
);
$exception = false ;
2019-11-04 15:46:53 +01:00
$warningTagConflicts = array ();
2019-01-31 14:39:24 +01:00
$filters = $this -> _harvestParameters ( $filterData , $exception );
2018-07-19 11:48:22 +02:00
$emptyEvent = ( empty ( $event [ 'Object' ]) && empty ( $event [ 'Attribute' ]));
$this -> set ( 'emptyEvent' , $emptyEvent );
2022-09-26 18:15:05 +02:00
2018-07-19 11:48:22 +02:00
// set the data for the contributors / history field
2019-02-28 08:30:17 +01:00
$contributors = $this -> Event -> ShadowAttribute -> getEventContributors ( $event [ 'Event' ][ 'id' ]);
2020-10-11 20:29:50 +02:00
$this -> set ( 'contributors' , $contributors );
2022-10-22 15:47:08 +02:00
2018-07-19 11:48:22 +02:00
// set the pivot data
$this -> helpers [] = 'Pivot' ;
if ( $continue ) {
2021-03-03 10:01:36 +01:00
$this -> __continuePivoting ( $event [ 'Event' ][ 'id' ], $event [ 'Event' ][ 'info' ], $event [ 'Event' ][ 'date' ], $fromEvent );
2018-07-19 11:48:22 +02:00
} else {
2021-03-03 10:01:36 +01:00
$this -> __startPivoting ( $event [ 'Event' ][ 'id' ], $event [ 'Event' ][ 'info' ], $event [ 'Event' ][ 'date' ]);
2018-07-19 11:48:22 +02:00
}
$pivot = $this -> Session -> read ( 'pivot_thread' );
$this -> __arrangePivotVertical ( $pivot );
$this -> __setDeletable ( $pivot , $event [ 'Event' ][ 'id' ], true );
$this -> set ( 'allPivots' , $this -> Session -> read ( 'pivot_thread' ));
$this -> set ( 'pivot' , $pivot );
2020-05-29 09:31:59 +02:00
// workaround to get number of correlation per related event
2019-06-21 11:21:43 +02:00
$relatedEventCorrelationCount = array ();
2020-05-29 09:31:59 +02:00
if ( ! empty ( $event [ 'RelatedAttribute' ])) {
foreach ( $event [ 'RelatedAttribute' ] as $relatedAttribute ) {
foreach ( $relatedAttribute as $relation ) {
$relatedEventCorrelationCount [ $relation [ 'id' ]][ $relation [ 'value' ]] = true ;
2018-07-19 11:48:22 +02:00
}
}
}
2019-06-21 11:21:43 +02:00
foreach ( $relatedEventCorrelationCount as $key => $relation ) {
2022-09-26 18:15:05 +02:00
$relatedEventCorrelationCount [ $key ] = count ( $relation );
2019-06-21 11:21:43 +02:00
}
2018-07-19 11:48:22 +02:00
2020-01-27 21:22:18 +01:00
$this -> Event -> removeGalaxyClusterTags ( $event );
2019-11-04 11:54:22 +01:00
2019-11-04 14:55:43 +01:00
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $event [ 'EventTag' ]);
foreach ( $tagConflicts [ 'global' ] as $tagConflict ) {
2019-11-04 15:46:53 +01:00
$warningTagConflicts [ $tagConflict [ 'taxonomy' ][ 'Taxonomy' ][ 'namespace' ]] = $tagConflict [ 'taxonomy' ];
2019-11-04 14:55:43 +01:00
}
foreach ( $tagConflicts [ 'local' ] as $tagConflict ) {
2019-11-04 15:46:53 +01:00
$warningTagConflicts [ $tagConflict [ 'taxonomy' ][ 'Taxonomy' ][ 'namespace' ]] = $tagConflict [ 'taxonomy' ];
2019-11-04 13:41:53 +01:00
}
2019-11-04 11:54:22 +01:00
$this -> set ( 'tagConflicts' , $tagConflicts );
2022-09-26 18:15:05 +02:00
$attributeCount = isset ( $event [ 'Attribute' ]) ? count ( $event [ 'Attribute' ]) : 0 ;
$objectCount = isset ( $event [ 'Object' ]) ? count ( $event [ 'Object' ]) : 0 ;
$oldestTimestamp = PHP_INT_MAX ;
$containsProposals = ! empty ( $event [ 'ShadowAttribute' ]);
2020-07-05 16:22:01 +02:00
$modDate = date ( " Y-m-d " , $event [ 'Event' ][ 'timestamp' ]);
$modificationMap = array ( $modDate => 1 );
2018-07-19 11:48:22 +02:00
foreach ( $event [ 'Attribute' ] as $k => $attribute ) {
2022-09-26 18:15:05 +02:00
if ( $oldestTimestamp > $attribute [ 'timestamp' ]) {
$oldestTimestamp = $attribute [ 'timestamp' ];
2019-04-04 15:00:05 +02:00
}
2019-02-06 17:47:22 +01:00
$modDate = date ( " Y-m-d " , $attribute [ 'timestamp' ]);
2020-07-05 16:22:01 +02:00
$modificationMap [ $modDate ] = ! isset ( $modificationMap [ $modDate ]) ? 1 : $modificationMap [ $modDate ] + 1 ;
2020-01-27 21:22:18 +01:00
$this -> Event -> Attribute -> removeGalaxyClusterTags ( $event [ 'Attribute' ][ $k ]);
2021-10-29 14:49:06 +02:00
if ( ! empty ( $attribute [ 'AttributeTag' ])) {
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
foreach ( $tagConflicts [ 'global' ] as $tagConflict ) {
$warningTagConflicts [ $tagConflict [ 'taxonomy' ][ 'Taxonomy' ][ 'namespace' ]] = $tagConflict [ 'taxonomy' ];
}
foreach ( $tagConflicts [ 'local' ] as $tagConflict ) {
$warningTagConflicts [ $tagConflict [ 'taxonomy' ][ 'Taxonomy' ][ 'namespace' ]] = $tagConflict [ 'taxonomy' ];
}
$event [ 'Attribute' ][ $k ][ 'tagConflicts' ] = $tagConflicts ;
2019-11-04 13:41:53 +01:00
}
2022-09-26 18:15:05 +02:00
if ( ! $containsProposals && ! empty ( $attribute [ 'ShadowAttribute' ])) {
$containsProposals = true ;
}
2018-07-19 11:48:22 +02:00
}
2020-07-05 16:22:01 +02:00
2018-07-19 11:48:22 +02:00
foreach ( $event [ 'Object' ] as $k => $object ) {
2019-02-06 17:47:22 +01:00
$modDate = date ( " Y-m-d " , $object [ 'timestamp' ]);
2020-07-05 16:22:01 +02:00
$modificationMap [ $modDate ] = ! isset ( $modificationMap [ $modDate ]) ? 1 : $modificationMap [ $modDate ] + 1 ;
2018-07-19 11:48:22 +02:00
if ( ! empty ( $object [ 'Attribute' ])) {
2021-09-02 10:19:06 +02:00
$attributeCount += count ( $object [ 'Attribute' ]);
2018-07-19 11:48:22 +02:00
foreach ( $object [ 'Attribute' ] as $k2 => $attribute ) {
2022-09-26 18:15:05 +02:00
if ( $oldestTimestamp > $attribute [ 'timestamp' ]) {
$oldestTimestamp = $attribute [ 'timestamp' ];
2021-09-02 10:19:06 +02:00
}
2019-02-06 17:47:22 +01:00
$modDate = date ( " Y-m-d " , $attribute [ 'timestamp' ]);
2020-07-05 16:22:01 +02:00
$modificationMap [ $modDate ] = ! isset ( $modificationMap [ $modDate ]) ? 1 : $modificationMap [ $modDate ] + 1 ;
2020-01-27 21:22:18 +01:00
$this -> Event -> Attribute -> removeGalaxyClusterTags ( $event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ]);
2021-10-29 14:49:06 +02:00
if ( ! empty ( $attribute [ 'AttributeTag' ])) {
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
foreach ( $tagConflicts [ 'global' ] as $tagConflict ) {
$warningTagConflicts [ $tagConflict [ 'taxonomy' ][ 'Taxonomy' ][ 'namespace' ]] = $tagConflict [ 'taxonomy' ];
}
foreach ( $tagConflicts [ 'local' ] as $tagConflict ) {
$warningTagConflicts [ $tagConflict [ 'taxonomy' ][ 'Taxonomy' ][ 'namespace' ]] = $tagConflict [ 'taxonomy' ];
}
$event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ][ 'tagConflicts' ] = $tagConflicts ;
2019-11-04 13:41:53 +01:00
}
2022-09-26 18:15:05 +02:00
if ( ! $containsProposals && ! empty ( $attribute [ 'ShadowAttribute' ])) {
$containsProposals = true ;
}
2018-07-19 11:48:22 +02:00
}
}
}
2022-09-26 18:15:05 +02:00
if ( $containsProposals && $this -> __canPublishEvent ( $event , $user )) {
$mess = $this -> Session -> read ( 'Message' );
if ( empty ( $mess )) {
$this -> Flash -> info ( __ ( 'This event has active proposals for you to accept or discard.' ));
}
}
$attributeTagsName = $this -> Event -> Attribute -> AttributeTag -> extractAttributeTagsNameFromEvent ( $event );
$this -> set ( 'attributeTags' , array_values ( $attributeTagsName [ 'tags' ]));
$this -> set ( 'attributeClusters' , array_values ( $attributeTagsName [ 'clusters' ]));
2019-11-04 15:46:53 +01:00
$this -> set ( 'warningTagConflicts' , $warningTagConflicts );
2019-01-31 14:39:24 +01:00
$filters [ 'sort' ] = 'timestamp' ;
$filters [ 'direction' ] = 'desc' ;
2019-01-31 16:22:11 +01:00
if ( isset ( $filters [ 'distribution' ])) {
if ( ! is_array ( $filters [ 'distribution' ])) {
$filters [ 'distribution' ] = array ( $filters [ 'distribution' ]);
}
$temp = implode ( '|' , $filters [ 'distribution' ]);
2019-02-01 11:35:01 +01:00
$this -> __applyQueryString ( $event , $temp , 'distribution' );
2019-01-31 16:22:11 +01:00
}
2019-02-06 17:47:22 +01:00
$modificationMapCSV = 'Date,Close\n' ;
$startDate = array_keys ( $modificationMap );
sort ( $startDate );
$startDate = $startDate [ 0 ];
$this -> set ( 'startDate' , $startDate );
2021-09-02 10:19:06 +02:00
$today = strtotime ( date ( 'Y-m-d' ));
2020-07-05 16:22:01 +02:00
if (( $today - 172800 ) > $startDate ) {
$startDate = date ( 'Y-m-d' , $today - 172800 );
2019-02-06 17:47:22 +01:00
}
2020-07-05 16:22:01 +02:00
for ( $date = $startDate ; strtotime ( $date ) <= $today ; $date = date ( 'Y-m-d' , strtotime ( " +1 day " , strtotime ( $date )))) {
2019-02-06 17:47:22 +01:00
if ( isset ( $modificationMap [ $date ])) {
$modificationMapCSV .= $date . ',' . $modificationMap [ $date ] . '\n' ;
} else {
$modificationMapCSV .= $date . ',0\n' ;
}
}
unset ( $modificationMap );
2020-11-11 09:00:50 +01:00
$this -> loadModel ( 'Sighting' );
2021-03-10 18:27:19 +01:00
$sightingsData = $this -> Sighting -> eventsStatistic ([ $event ], $user );
2019-03-01 11:54:29 +01:00
$this -> set ( 'sightingsData' , $sightingsData );
$params = $this -> Event -> rearrangeEventForView ( $event , $filters , false , $sightingsData );
2019-11-06 21:20:04 +01:00
if ( ! empty ( $filters [ 'includeSightingdb' ]) && Configure :: read ( 'Plugin.Sightings_sighting_db_enable' )) {
$this -> loadModel ( 'Sightingdb' );
2021-03-10 18:27:19 +01:00
$event = $this -> Sightingdb -> attachToEvent ( $event , $user );
2019-11-06 21:20:04 +01:00
}
2018-07-19 11:48:22 +02:00
$this -> params -> params [ 'paging' ] = array ( $this -> modelClass => $params );
$this -> set ( 'event' , $event );
$extensionParams = array (
'conditions' => array (
'Event.extends_uuid' => $event [ 'Event' ][ 'uuid' ]
)
);
2021-03-10 18:27:19 +01:00
$extensions = $this -> Event -> fetchSimpleEvents ( $user , $extensionParams );
2018-07-19 11:48:22 +02:00
$this -> set ( 'extensions' , $extensions );
if ( ! empty ( $event [ 'Event' ][ 'extends_uuid' ])) {
2021-03-10 18:27:19 +01:00
$extendedEvent = $this -> Event -> fetchSimpleEvents ( $user , array ( 'conditions' => array ( 'Event.uuid' => $event [ 'Event' ][ 'extends_uuid' ])));
2018-07-19 11:48:22 +02:00
if ( empty ( $extendedEvent )) {
$extendedEvent = $event [ 'Event' ][ 'extends_uuid' ];
}
$this -> set ( 'extendedEvent' , $extendedEvent );
}
if ( Configure :: read ( 'MISP.delegation' )) {
$this -> loadModel ( 'EventDelegation' );
$delegationConditions = array ( 'EventDelegation.event_id' => $event [ 'Event' ][ 'id' ]);
if ( ! $this -> _isSiteAdmin () && $this -> userRole [ 'perm_publish' ]) {
2021-03-10 18:27:19 +01:00
$delegationConditions [ 'OR' ] = array ( 'EventDelegation.org_id' => $user [ 'org_id' ],
'EventDelegation.requester_org_id' => $user [ 'org_id' ]);
2018-07-19 11:48:22 +02:00
}
2019-11-12 14:52:10 +01:00
$this -> set ( 'delegationRequest' , $this -> EventDelegation -> find ( 'first' , array (
'conditions' => $delegationConditions ,
'recursive' => - 1 ,
'contain' => array ( 'Org' , 'RequesterOrg' )
)));
2018-07-19 11:48:22 +02:00
}
2021-09-02 10:19:06 +02:00
2020-08-17 15:52:32 +02:00
$attributeUri = $this -> baseurl . '/events/viewEventAttributes/' . $event [ 'Event' ][ 'id' ];
2018-07-19 11:48:22 +02:00
foreach ( $this -> params -> named as $k => $v ) {
if ( ! is_numeric ( $k )) {
2019-05-31 09:19:51 +02:00
if ( is_array ( $v )) {
foreach ( $v as $value ) {
$attributeUri .= sprintf ( '/%s[]:%s' , $k , $value );
}
} else {
$attributeUri .= sprintf ( '/%s:%s' , $k , $v );
}
2018-07-19 11:48:22 +02:00
}
}
2021-09-02 10:19:06 +02:00
2019-11-06 21:20:04 +01:00
if ( ! empty ( $filters [ 'includeSightingdb' ]) && Configure :: read ( 'Plugin.Sightings_sighting_db_enable' )) {
2021-03-10 18:27:19 +01:00
$this -> set ( 'sightingdbs' , $this -> Sightingdb -> getSightingdbList ( $user ));
2019-11-06 21:20:04 +01:00
}
2022-09-26 18:15:05 +02:00
$this -> set ( 'includeOrgColumn' , $this -> viewVars [ 'extended' ] || $containsProposals );
2021-09-02 16:38:16 +02:00
$this -> set ( 'includeSightingdb' , ! empty ( $filters [ 'includeSightingdb' ]) && Configure :: read ( 'Plugin.Sightings_sighting_db_enable' ));
2019-06-21 11:21:43 +02:00
$this -> set ( 'relatedEventCorrelationCount' , $relatedEventCorrelationCount );
2022-09-26 18:15:05 +02:00
$this -> set ( 'oldest_timestamp' , $oldestTimestamp === PHP_INT_MAX ? false : $oldestTimestamp );
2021-02-24 08:13:45 +01:00
$this -> set ( 'missingTaxonomies' , $this -> Event -> missingTaxonomies ( $event ));
2018-07-19 11:48:22 +02:00
$this -> set ( 'currentUri' , $attributeUri );
2019-01-31 14:39:24 +01:00
$this -> set ( 'filters' , $filters );
2019-02-01 16:18:34 +01:00
$advancedFiltering = $this -> __checkIfAdvancedFiltering ( $filters );
$this -> set ( 'advancedFilteringActive' , $advancedFiltering [ 'active' ] ? 1 : 0 );
$this -> set ( 'advancedFilteringActiveRules' , $advancedFiltering [ 'activeRules' ]);
2019-02-06 17:47:22 +01:00
$this -> set ( 'modificationMapCSV' , $modificationMapCSV );
2020-05-19 21:20:31 +02:00
$this -> set ( 'title_for_layout' , __ ( 'Event #%s' , $event [ 'Event' ][ 'id' ]));
2021-09-02 10:19:06 +02:00
$this -> set ( 'attribute_count' , $attributeCount );
$this -> set ( 'object_count' , $objectCount );
2022-02-17 09:24:12 +01:00
$this -> set ( 'warnings' , $this -> Event -> generateWarnings ( $event ));
2022-03-06 23:51:25 +01:00
$this -> set ( 'menuData' , array ( 'menuList' => 'event' , 'menuItem' => 'viewEvent' ));
2022-05-22 15:40:13 +02:00
$this -> set ( 'mayModify' , $this -> __canModifyEvent ( $event , $user ));
2022-10-22 15:47:08 +02:00
$this -> set ( 'mayPublish' , $this -> __canPublishEvent ( $event , $user ));
2022-03-18 13:54:31 +01:00
try {
2022-05-20 23:00:31 +02:00
$instanceKey = $event [ 'Event' ][ 'protected' ] ? $this -> Event -> CryptographicKey -> ingestInstanceKey () : null ;
2022-03-18 13:54:31 +01:00
} catch ( Exception $e ) {
$instanceKey = null ;
}
$this -> set ( 'instanceFingerprint' , $instanceKey );
2021-09-02 10:19:06 +02:00
$this -> __eventViewCommon ( $user );
}
private function __eventViewCommon ( array $user )
{
2021-10-23 16:38:27 +02:00
$this -> set ( 'defaultFilteringRules' , self :: DEFAULT_FILTERING_RULE );
2022-04-29 14:36:06 +02:00
$this -> set ( 'typeGroups' , array_keys ( Attribute :: TYPE_GROUPINGS ));
2021-09-02 10:19:06 +02:00
$orgTable = $this -> Event -> Orgc -> find ( 'list' , array (
'fields' => array ( 'Orgc.id' , 'Orgc.name' )
));
$this -> set ( 'orgTable' , $orgTable );
$dataForView = array (
'Attribute' => array ( 'attrDescriptions' => 'fieldDescriptions' , 'distributionDescriptions' => 'distributionDescriptions' , 'distributionLevels' => 'distributionLevels' , 'shortDist' => 'shortDist' ),
'Event' => array ( 'eventDescriptions' => 'fieldDescriptions' , 'analysisDescriptions' => 'analysisDescriptions' , 'analysisLevels' => 'analysisLevels' )
);
foreach ( $dataForView as $m => $variables ) {
if ( $m === 'Event' ) {
$currentModel = $this -> Event ;
} elseif ( $m === 'Attribute' ) {
$currentModel = $this -> Event -> Attribute ;
}
foreach ( $variables as $alias => $variable ) {
$this -> set ( $alias , $currentModel -> { $variable });
}
}
if ( Configure :: read ( 'Plugin.Enrichment_services_enable' )) {
$this -> loadModel ( 'Module' );
$modules = $this -> Module -> getEnabledModules ( $user );
$this -> set ( 'modules' , $modules );
}
if ( Configure :: read ( 'Plugin.Cortex_services_enable' )) {
$this -> loadModel ( 'Module' );
$cortex_modules = $this -> Module -> getEnabledModules ( $user , false , 'Cortex' );
$this -> set ( 'cortex_modules' , $cortex_modules );
}
2022-09-29 15:06:45 +02:00
$this -> set ( 'sightingsDbEnabled' , ( bool ) Configure :: read ( 'Plugin.Sightings_sighting_db_enable' ));
2018-07-19 11:48:22 +02:00
}
2020-07-22 19:06:00 +02:00
public function view ( $id = null , $continue = false , $fromEvent = null )
2018-07-19 11:48:22 +02:00
{
2020-10-30 08:51:42 +01:00
if ( $this -> request -> is ( 'head' )) { // Just check if event exists
$exists = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id , [ 'fields' => [ 'id' ]]);
return new CakeResponse ([ 'status' => $exists ? 200 : 404 ]);
}
2020-07-22 19:06:00 +02:00
if ( is_numeric ( $id )) {
$conditions = array ( 'eventid' => $id );
} else if ( Validation :: uuid ( $id )) {
$conditions = array ( 'event_uuid' => $id );
} else {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
2021-09-30 20:08:45 +02:00
$namedParams = $this -> request -> params [ 'named' ];
2024-01-19 17:54:06 +01:00
$conditions [ 'includeAnalystData' ] = true ;
2020-08-18 21:59:25 +02:00
if ( $this -> _isRest ()) {
2021-09-30 20:08:45 +02:00
$conditions [ 'includeAttachments' ] = isset ( $namedParams [ 'includeAttachments' ]) ? $namedParams [ 'includeAttachments' ] : true ;
2020-08-18 21:59:25 +02:00
} else {
$conditions [ 'includeAllTags' ] = true ;
2020-10-10 14:19:39 +02:00
$conditions [ 'noEventReports' ] = true ; // event reports for view are loaded dynamically
2020-11-11 09:00:50 +01:00
$conditions [ 'noSightings' ] = true ;
2021-02-21 16:26:02 +01:00
$conditions [ 'fetchFullClusters' ] = false ;
2018-07-19 11:48:22 +02:00
}
2020-11-10 14:30:28 +01:00
$deleted = 0 ;
2021-09-30 20:08:45 +02:00
if ( isset ( $namedParams [ 'deleted' ])) {
$deleted = $namedParams [ 'deleted' ];
2019-09-13 15:34:12 +02:00
}
if ( isset ( $this -> request -> data [ 'deleted' ])) {
$deleted = $this -> request -> data [ 'deleted' ];
}
2021-10-19 18:27:16 +02:00
// workaround for old instances trying to pull events with both deleted / non deleted data
if (( $this -> userRole [ 'perm_sync' ] && $this -> _isRest () && ! $this -> userRole [ 'perm_site_admin' ]) && $deleted == 1 ) {
$conditions [ 'deleted' ] = array ( 0 , 1 );
} else {
if ( is_array ( $deleted )) {
$conditions [ 'deleted' ] = $deleted ;
} else if ( $deleted == 1 ) { // both
$conditions [ 'deleted' ] = [ 0 , 1 ];
} elseif ( $deleted == 0 ) { // not-deleted only
$conditions [ 'deleted' ] = 0 ;
} else { // only deleted
$conditions [ 'deleted' ] = 1 ;
2019-06-04 13:54:47 +02:00
}
new: [related tags] View the related tags of attributes on the event view (via a toggle)
,,.,,+zznzzzzzzzzzzzzzzzzzzzzzzzzzzxMMMMMMMMMMMMMMMMMMMMMxMxMMWMMMWMMz*ii****iiiiiiiii**iiii,....
,,.,,#zzzzzzzzzzzzzzzzzzzzzzzznxMMMMMWMMMMMMMMMMMMMMMMMMxMxMMMWWWWWWWWx+*iii*iiiiiiiii*iiiii,,,..
,,,,,#zzzzzzzzzzzzzzzzzzzzzzznMWWMMMMMMMMMMMMMMMMMMMMMMMWWMxnnzxxMWWWWMn*iiiiiiiiiiiiiiiiiii..,..
,,,,,#znzzzzzzzzzzzzzzzzzzzznMMMMMMWWWWMMMMMMMMMMMMMMMMWWWMMMxnxxxxMMMMW#*iiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzzzznMMMMMMMMMWMMMMMMMMMMMMMMMMMMMMWxMMMMMMxxxxnxxz*iiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzzzzxMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWMWWWWMWMMMxxxni*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzzznMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWMMWWMWMMWWWMMMni*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzzzxWMMMMMMMMMMMMMMMMMMMMMMMMMMMWMMMWMMMMMMWMWWMMMMMz*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznzzznMMMMMMMMMMMWMMMMMMMMMMMMMMMMMMMMMMMMWWWWMMMMMMMMMWn*iiiiiiiiiiii*i,.,.,
,,.,,#zzzzzzzzzzzzzzznzzzxMMMMMMMMMMMWMMMMMMMMMMMMMMMMMMMMMWWWWWWWWWWWMMMMMWWM+*iiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznzzznzznMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWMWWWWWWWWWWWWWMMWWn*iiiiiiiiii*i,.,.,
,,.,,#zzzzzzzzzzznzzzznzxMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWMMMMWWWWMMWWWWWMMMM**iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzznMMMMMMMMMMMMMWMMMMMWMMMMMMMMMMMMMMWWWWWMMMMMMMMWWWWWMWM#iiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzxMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWWWWWWWMMMMMMMWWWWMzi*iiiiiiii*i,.,.,
,,.,,#zzzzzzzzzzzzzzzzzMMMMMMMMMMMMMMMWMnzxMMMMMMMMMMMMMWWWWWWWWWWWWMMMMMMMWWWWni*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzWMMMMMMMMMMMMMMMnnzznxMWMMMMMMMMMMWWWWWWWWWWWWWWWWWMMWWMn**iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzMMMMMMMMMMMWMMMMzz#+#znxMWMMMMMMMMMMMMMWWWWWWWWWWWWWMWWMn**iiiiiiii*i,.,,,
,,.,,#zzzzzzzzzzzzzzzzzxMMMMMMMMMMMMMMxz#*i**+zznMMMMMMMMMMMMMMMWWWWWWWMWWWWWWWx**iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzxMMMMMMMMMMWWMMn#*iii*i*+znxMWMMMMMMMMMMMMWWWWWMMMMMMMMMM+*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzznMWMMMMMMMMMMMMn#*iiii*i*i+#znMMWWMMMMMWMWMMWWWMMMMMMMMWWx+iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzMMMMMMMMMMMMMx#i*iii**iiii*#znxMWMMMMMMMMMMMWWMMMMWWWWWWniiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznzMMMMMMMMMMMMxn+ii**i**iiii*i*zznMMMMMMMMMMMMMMMMMxMWWWMMx*iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznnMMMMMMMMMMMMxz*ii*iiiiiiiii:;*+znMWMMMMMMMMMMMMMMMMMWWWMx**iiiiiiii*i,.,,.
,,.,,#zzzzzzzzzzzzzzzznMMMMMMMMMMMMMn+ii*iiiii**;;:.:i*zznxMMMMMMMMMMMMMMWWWWWWni*ii**iiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzxMMMMMMMMMMMMMn*ii*iii*i;:,.,..,.,;+znxxMMMMMMMMMMMMMMWWWziiii**iiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznxMMMMMMMMMMMMxzi*ii*ii*;,,,,,,,,,,,,:i*i#znnnxMWWMMMMMMMWn*iii*iiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznxMMMMMMMMMMMMz*i*i*i*;:,.,,,,,,,,,,,,.,,,;i*#zznxMMMMMMWWM+iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMWMMMMMMMMx#iii*i*i:.,.,,,.,.,,,,,,,,,,,,,,;i#znxMMMMMWM+iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMWMMMMMMMMx#iiiiii:.,,.,,.......,,,,..,,,,,,,,iznxMMMMWM*iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMMMMMMMMMMx#ii*ii:.,,,,,,..........,.....,,,,,,:*#MMMMWxi*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzMMMMMMMMMMMMn+i*i;:,.,,,......,.............,....,,;xMMMWniiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznzzMMMMMMMMMWMn+iiii;,,,,,,.,..........,....,.,...,,,,.zMMMMxiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznznMMMMMMMMMMnz*iiii:,,,,,,,,,,,,................,,,...zMMMMzi*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznznMMMMMMMMMxzz**ii;..,,,.,,,,,,.................,,,...nMMMM#**iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznzzMMMMMMMWxzzz+iii:.,,,,.,,,,,....,............,,,,..,nMMWx*iiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznznMMMMMMMWnzzzn+i*,...,,..,,,.,..,.,...,........,,,.,;MWMM+iiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMMMMMWnzzzzzzii*++++z+;,,,.,,,,,,,,,...,.....,...;MWMxii**iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMMMMMWnzzznzzzzznnnzzzn#i,,,.,...................,MWM#iii*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzxMMMMMMMMzz+#znzznznMWWMMWMx#i:,,,,,,,,,,,,,,.,,..,,:MMx*iiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzxMMMMMMMxzz**#znMMnnxxxxxMWWWMnz;,,,,,.,.,,,,,,,,,,,,MMziiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzMMMMxMMMnzz*ii#nWWWWMWWnMMMWWWWWn*,,;i;i;**+#zzz+i,,,Mx*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzMMMMMMMxzzzi*;,+xWWMnxMnx+xMWWMWWn,.,znMMMxxMMMMxni:*Mziiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzznxnxMMMMxznziii.,:+nxiinn*.iMMMWMM+,,.*WWWWWWM#:,:#z##M*iiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznzznxzMWMMMxznziii,..,+#n:,:,,,izzMM#;,,,+WWWWWzxn+i,:zzzMi**iiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznzznnzxMMMMxzz#ii;,,,,:**++i::,:::zx;,,,,#MM#zxxMznWx#+izxiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzxnzMWMMMnzzz*i:.,,,,,,,i;i;,,.,*n,,,,,+#+::#n*,#xni,,zniiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzxnzMMMMWnzzz**;..,,,.,..,;,,,,,;n,.,,:*;,:::,,,:*,.,,n#i*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzznxzMWMMMnzzz**i,..,,.,,,,,,,,,,+#,...,i,.,;**++*:.,,:x***iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznzznnxWWMxnzzzz+*i,,,,,.,,,,,,,,,:z;,,..,:..,,,,::.,..,;xi*iiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzznxxxzzzzzz+ii,...,.,,,,,,.,,+zi.,,.,,.,,.,,..,,,,,++iiiiiiiiiiiiiiii*i,.,,.
,,.,,#zzzzzzzzzzzzzzzzzznMzzzznz#ii:.,.,..,,,,,,,izn:,..,.,,..,...,,.,,,#*iiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzznxzzzzzz#ii;.,.,..,,,,.,:zzz,,..,,,,.,...,,,,,,:+*iiiiiiiiiiiiiiii*i,.,,.
,,.,,#zzzzzzzzzzzzzzzznzxxzzzznzz*i;..,,,.,,,,..;zz*..,.,,,,........,.,**iiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzznzxMnzzznzz*ii,.,,,,,,,,,,ii:,,,,,,,,,,,,,,.,,.,;+*iiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzxMzzzzzzz**i,,.,..,,,,,;*:*,,,.,,...,,,,,,.,,,**iiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzMMnnzzzzz*ii:.,,,,,,..,#nnn#+,,,,,..,,....,.,i+i*iiiiiiiiiiiiiiiii*i,.,,.
,,.,,#zzzzzzzzzzzznzznnzMMnxzzzzz**i;.,,,,.,,.,zxWWWxi,,,:*,,,..,.,,,#**iiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznM+WMxxzzzzz***;..,,,,,,..;xWWWWn+**#;,,,,.,,,.i#*iiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzznW#zWMxnnzzzz*iii,.,,,,,,,,,+nWMWWWMx+,,,,,.,,,,++i*iiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznMM,zWMMnnzzz#*ii*;.,,,,,,::iznxMMWWWWn#;,,.,,,,*#**iiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzMWz,zMMMxxznn#*ii*i::;i++#zznxWxxxWWWxxxzi,.,,,,#+iiiiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznMWW#,#MMMMMnznz*ii**izzzzzzxMMWWnxM@WMMMMzzi,.,,+*+iiiiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzznMWWW#,*xMMMMnznz*iiii+MnnnnnxMWWWxxMxMxMxxxnz*,,,*+*iiii**iiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzMWWWW#;;zMMMMMnnz#*i*#MWxxxxxMWMxMMxMxMWWWWxMzn;.i:#*iiii**iiiiiiiiiiiiiii*i,.,..
,,,,,#zzzzzznnzxWWWWW#:;+MMMMMxzzz#*zzxWMWMWxMWWMMWWMMWWWWMxxMn:,*:#iiiiiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzxWWWWWWz::inMMMMMxznzzzzznxMMMxxxMMxxxzxMWWWMMWWx:ii+*iiiiiiiiiiiiiiiiiiiiii*i,.,..
....,#zzzzzzznWWWWWWWz;,;+MMMMMMxzzzzzzzzznz#**i;::,,:;#nxxWMM+;*;+*iiiiiiiiiiiiiiiiiiiiii*i,.,..
...,,#zzzzzznMWWWWWWWni,,*nWMMMMMxnzzzzzzzz#i*i,,,,:,,,,:+#z##i#+#*iiiiiiiiiiiiiiiiiiiiiii*i,.,..
...,,#zzznnnxWWWWWWWWx*,.i+MMMMMMMMxxnzz#+****i,i**#z+;,:*iiii*zz+*iiiiiiiiiiiiiiiiiiiiiii*i,.,..
,,,,,#nzzzxMMWWWWWWWWW*;.:*#WMMMMMMMMxz+**iiiii;*++####:;i****zz#*iiiiiiiiiiiiiiiiiiiiiiii*i,.,,.
,,,,,#zznMWxWWWWWWWWWWz;,.;*nWMMMMMMMMnz#ii:.....,,,,,,,,ii*+zzz*ii**iiiiiiiiiiiiiiiiiiiii*i,.,..
,,,,,#nxWWMxWWWWWWWWWWW;:,,*+xMMMMMMMMMxnz*:.,,,,,..,,,,,,i#nnx+i*i*iiiiiiiiiiiiiiiiiiiiii*i,.,..
,,,,,zWWWWMxWWWWWWWWWWW*;,.,*+MMMMMMWMMWMx#*:,,,,....,,,,:#nMM#+*ii*iiiiiiiiiiiiiiiiiiiiii*i,.,..
,,,,,xWWWWxWWWWWWWWWWWWx::,,:;+MMMMMMWMWMMnz+:....,,.,,,,+MWMM*#z+*iiiiiiii**iiiiiiiiiiiii*i,.,..
,,,,,xWWWMxWWWWWWWWWWWWW+:,,,;:+MMMMMMMMMMMxnz*;,,:,,,i+#xM++W#+nz#iii*iiiiiiiiiiiiiiiiiii*i,.,..
,,,,,xWWWMMWWWWWWWWWWWWWx,,..,;,*xWMMMMMMMWMWxnn####+##nxx#,+Wx*nznz:i**iiiiiiiiiiiiiiiiii*i,.,..
,,.,,xWWWxMWWWWWWWWWWWWWWi.,,,,:,*#MMMMMMMMMMWMMxxxxxxxMnn,.zWM#;zzMn;*i*iiiiiiiiiiiiiiiii*i,.,..
,..,,xWWWxWWWWWWWWWWWWWWWx,,,,,,:,;+MMWMMMMWWWWWWWMMMMMxn:..nWWni+nzMn#niii**iiiiiiiiiiiii*i,.,..
,..,,xWWMxWWWWWWWWWWWWWWWWi,,,,.,:,,;xWMMMMMMMMMMMMMMxnni...xMWxz;znnMxxM#;i*i**iiiiiiiiii*i,.,..
,..,,xWWMMWWWWWWWWWWWWWWWWz.,,...::,,;zWMMMMMMMMMMMMnzzi,,,,MMMMx*innxMxxWx+iiii**iiiiiiii*i,.,..
,..,,xWWMMWWWWWWWWWWWWWWWWM:,,...,:,,,,+xWMMMMMMMMxnnzi,.,,,MMMMMzinxMxMxxMMM#;i**iiiiiiii*i,.,..
,..,,xWWxWWWWWWWWWWWWWWWWWW*.,.,.,,:,,.,i+xWWMMMMxnnni,,,,,.WMMMMMz#nMMxMMMMMWxi;i*iiii*ii*i,,,..
,..,,xWWxWWWWWWWWWWWWWWWWWWz.,,,,.,,:,,,,::#@WMMxnnn;..,,.,:WMWMMMMznxWxxWMMMMMM#;iiiiiiii*i,,,..
,..,.nWMMWWWWWWWWWWWWWWWWWWM,.,,,...,,..,.,.iMWMxnz:.,.,,.,;WMWMMMMnzxMMxMMMMMMWMxi;i*iii*ii..,..
,..,,nWWMMWWWWWWWWWWWWWWWWWWi,,,....,.,,.,,,,:nxxz:,.,,,...iWMWMMMWMznMMMxMMMMMMMMMzi;i**iii..,.,
,..,,xWWWMMWWWWWWWWWWWWWWWWW#:.....,....,.,,..:#+,..,,,....:WWMMMMMMxnnMMMxWMMMMMMMWM#;;*i*i,.,..
,..,,xWWWWWMMWWWWWWWWWWWWWWWxi:..,.......,,,,..;;,...,,...,,@WMMMMMMMxzxMMxxMMWMMMMMMWx+;iii,,,..
,..,,xWWWWWWMMMWWWWWWWWWWWWWM*i,,,,......,,,,,;MWx+,..,,,..,@WMMMMMMMMnzxxnMMMMMMMMMMMWWx+ii,,,,.
,..,,xWWWWWWWMxWWWWWWWWWWWWWW+*;,,,,.....,,.,,xWWW@n:.,,,,.,WWMMMMMMMMMnnnMMMMMMMMMMMMWMWMxz,,,..
,..,,xWWWWWWWWMxWWWWWWWWWWWWWzi*;,,,,.....,,,nWMMMWWM:.,,,..MWMMMWMMMMMMnMMMMMMMMMMMMMMMMMMx,.,.,
,..,,xWWWWWWWWMxWWWWWWWWWWWWWMiii;,,.,,...,.zWWWWWWWWn,.....zWMMMMMMMMMMMxMMMMMMMMMMMMMMMMMx,,,..
,..,,xWWWWWWWWMWWWWWWWWWWWWWWWiii*;,,,,,,.,z@WWWWWWWWW*,..,,zWMMMMMMMMMMMMnMMMMMMMMMMMMMMMMx,,,..
,..,,xWWWWWWWMWWWWWWWWWWWWWWW@+,;ii:,,.,,,zWWWWWWWWWWWM:.,,,#WMMMMMMMMMMMMxnMMWMMMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWz,.;i*:...,ixWWWWWWWWWMMW+,,,.+WMMMMMMMMMMMMMxxMWWMMMMMMMMMMMx,,,..
,..,.xWWWWWWWWWWWWWWWWWWWWWWWWM,,,iii,,,;i+WWWWWWWWW#+xx;,,.+WWMMMMMMMMMMMWMxxMMMMMMMMMMMMMx,,,,,
,..,.xWWWMWWWWWWWWWWWWWWWWWWWWW;.,:iii,:ii*xWWWWWWWW+i*Mz,.,*WWMMMMMMMMMMMMWMxnMMMMMMMMMMMMx,,,..
,..,.xWWWMWWWWWWWWWWWWWWWWWWWWWz.,.;i*iiiiinWWWWWWWW*i*+z*.,iWWMMMMMMMMMMMMMMMxxMMMMMMMMMMMx,,,..
,..,.xWWWMMWWWWWWWWWWWWWWWWWWWWx,,,.i***;:i#WWWWWWWMi*ii*zi,;WWMMMMMMMMMMMMMMMMxMMMMMMMMMMMx,,,,.
,..,,xWWWWMMWWWWWWWWWWWWWWWWWWWW;,,.:*ii,,i+WWWWWWWM::iiiizi:WWMMMMMMMMMMMMMMMMMMMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWW+,,,.,i,,,;*WWWWWWWx:.:iii*z*MWMMMMMMMMMMMMMMMMMWMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWWn,,,,...,,:*MWWWWWWn:..;ii**xWWMMMMMMMMMMMMMMMMWWMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWWW:.,.,,,.,,iMWWWWWWz,.,,i*i*nWWMMMMMMMMMMMMMMMWWMMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWW@*..,,,..,,ixWWWWWWz..,.,i*inWWMMMMMMMMMMMMMMMWWMMMMMMMMMMMx,,,,.
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWWWn,.,,,,,,,;n@WWWWWn..,,,:*izWWMMMMMMMMMMMMMMWWWWMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWWWM:.,,,....:xWWWWWWM,,,,,.:izMWMMMMMMMMMMMMMMMWWMMMMMMMMMMMx,,,..
,..,,nMWWWWWWWWWWWWWWWWWWWWWMWWWWM#*********MWWWWWWW+*******nMWMMMMMMMMMMMMMMMMMMMMMMMMMMMMx,,,..
,..,,nMWWMMMMMMMMMMMMMMMMWWMMMMMWMMMWWMMMWWMMMMMMMMMMMMWWMWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMx,,,..
2018-10-11 17:37:58 +02:00
}
2021-09-30 20:08:45 +02:00
if ( isset ( $namedParams [ 'toIDS' ]) && $namedParams [ 'toIDS' ] != 0 ) {
$conditions [ 'to_ids' ] = $namedParams [ 'toIDS' ] == 2 ? 0 : 1 ;
2019-02-15 16:28:04 +01:00
}
2021-09-30 20:08:45 +02:00
if ( isset ( $namedParams [ 'includeRelatedTags' ]) && $namedParams [ 'includeRelatedTags' ]) {
new: [related tags] View the related tags of attributes on the event view (via a toggle)
,,.,,+zznzzzzzzzzzzzzzzzzzzzzzzzzzzxMMMMMMMMMMMMMMMMMMMMMxMxMMWMMMWMMz*ii****iiiiiiiii**iiii,....
,,.,,#zzzzzzzzzzzzzzzzzzzzzzzznxMMMMMWMMMMMMMMMMMMMMMMMMxMxMMMWWWWWWWWx+*iii*iiiiiiiii*iiiii,,,..
,,,,,#zzzzzzzzzzzzzzzzzzzzzzznMWWMMMMMMMMMMMMMMMMMMMMMMMWWMxnnzxxMWWWWMn*iiiiiiiiiiiiiiiiiii..,..
,,,,,#znzzzzzzzzzzzzzzzzzzzznMMMMMMWWWWMMMMMMMMMMMMMMMMWWWMMMxnxxxxMMMMW#*iiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzzzznMMMMMMMMMWMMMMMMMMMMMMMMMMMMMMWxMMMMMMxxxxnxxz*iiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzzzzxMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWMWWWWMWMMMxxxni*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzzznMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWMMWWMWMMWWWMMMni*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzzzxWMMMMMMMMMMMMMMMMMMMMMMMMMMMWMMMWMMMMMMWMWWMMMMMz*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznzzznMMMMMMMMMMMWMMMMMMMMMMMMMMMMMMMMMMMMWWWWMMMMMMMMMWn*iiiiiiiiiiii*i,.,.,
,,.,,#zzzzzzzzzzzzzzznzzzxMMMMMMMMMMMWMMMMMMMMMMMMMMMMMMMMMWWWWWWWWWWWMMMMMWWM+*iiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznzzznzznMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWMWWWWWWWWWWWWWMMWWn*iiiiiiiiii*i,.,.,
,,.,,#zzzzzzzzzzznzzzznzxMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWMMMMWWWWMMWWWWWMMMM**iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzznMMMMMMMMMMMMMWMMMMMWMMMMMMMMMMMMMMWWWWWMMMMMMMMWWWWWMWM#iiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzxMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWWWWWWWWWMMMMMMMWWWWMzi*iiiiiiii*i,.,.,
,,.,,#zzzzzzzzzzzzzzzzzMMMMMMMMMMMMMMMWMnzxMMMMMMMMMMMMMWWWWWWWWWWWWMMMMMMMWWWWni*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzWMMMMMMMMMMMMMMMnnzznxMWMMMMMMMMMMWWWWWWWWWWWWWWWWWMMWWMn**iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzMMMMMMMMMMMWMMMMzz#+#znxMWMMMMMMMMMMMMMWWWWWWWWWWWWWMWWMn**iiiiiiii*i,.,,,
,,.,,#zzzzzzzzzzzzzzzzzxMMMMMMMMMMMMMMxz#*i**+zznMMMMMMMMMMMMMMMWWWWWWWMWWWWWWWx**iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzxMMMMMMMMMMWWMMn#*iii*i*+znxMWMMMMMMMMMMMMWWWWWMMMMMMMMMM+*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzznMWMMMMMMMMMMMMn#*iiii*i*i+#znMMWWMMMMMWMWMMWWWMMMMMMMMWWx+iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzMMMMMMMMMMMMMx#i*iii**iiii*#znxMWMMMMMMMMMMMWWMMMMWWWWWWniiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznzMMMMMMMMMMMMxn+ii**i**iiii*i*zznMMMMMMMMMMMMMMMMMxMWWWMMx*iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznnMMMMMMMMMMMMxz*ii*iiiiiiiii:;*+znMWMMMMMMMMMMMMMMMMMWWWMx**iiiiiiii*i,.,,.
,,.,,#zzzzzzzzzzzzzzzznMMMMMMMMMMMMMn+ii*iiiii**;;:.:i*zznxMMMMMMMMMMMMMMWWWWWWni*ii**iiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzxMMMMMMMMMMMMMn*ii*iii*i;:,.,..,.,;+znxxMMMMMMMMMMMMMMWWWziiii**iiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznxMMMMMMMMMMMMxzi*ii*ii*;,,,,,,,,,,,,:i*i#znnnxMWWMMMMMMMWn*iii*iiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznxMMMMMMMMMMMMz*i*i*i*;:,.,,,,,,,,,,,,.,,,;i*#zznxMMMMMMWWM+iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMWMMMMMMMMx#iii*i*i:.,.,,,.,.,,,,,,,,,,,,,,;i#znxMMMMMWM+iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMWMMMMMMMMx#iiiiii:.,,.,,.......,,,,..,,,,,,,,iznxMMMMWM*iiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMMMMMMMMMMx#ii*ii:.,,,,,,..........,.....,,,,,,:*#MMMMWxi*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzMMMMMMMMMMMMn+i*i;:,.,,,......,.............,....,,;xMMMWniiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznzzMMMMMMMMMWMn+iiii;,,,,,,.,..........,....,.,...,,,,.zMMMMxiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznznMMMMMMMMMMnz*iiii:,,,,,,,,,,,,................,,,...zMMMMzi*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznznMMMMMMMMMxzz**ii;..,,,.,,,,,,.................,,,...nMMMM#**iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznzzMMMMMMMWxzzz+iii:.,,,,.,,,,,....,............,,,,..,nMMWx*iiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznznMMMMMMMWnzzzn+i*,...,,..,,,.,..,.,...,........,,,.,;MWMM+iiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMMMMMWnzzzzzzii*++++z+;,,,.,,,,,,,,,...,.....,...;MWMxii**iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznMMMMMMMWnzzznzzzzznnnzzzn#i,,,.,...................,MWM#iii*iiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzxMMMMMMMMzz+#znzznznMWWMMWMx#i:,,,,,,,,,,,,,,.,,..,,:MMx*iiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzxMMMMMMMxzz**#znMMnnxxxxxMWWWMnz;,,,,,.,.,,,,,,,,,,,,MMziiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzMMMMxMMMnzz*ii#nWWWWMWWnMMMWWWWWn*,,;i;i;**+#zzz+i,,,Mx*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzMMMMMMMxzzzi*;,+xWWMnxMnx+xMWWMWWn,.,znMMMxxMMMMxni:*Mziiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzznxnxMMMMxznziii.,:+nxiinn*.iMMMWMM+,,.*WWWWWWM#:,:#z##M*iiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznzznxzMWMMMxznziii,..,+#n:,:,,,izzMM#;,,,+WWWWWzxn+i,:zzzMi**iiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznzznnzxMMMMxzz#ii;,,,,:**++i::,:::zx;,,,,#MM#zxxMznWx#+izxiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzxnzMWMMMnzzz*i:.,,,,,,,i;i;,,.,*n,,,,,+#+::#n*,#xni,,zniiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzxnzMMMMWnzzz**;..,,,.,..,;,,,,,;n,.,,:*;,:::,,,:*,.,,n#i*iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzznxzMWMMMnzzz**i,..,,.,,,,,,,,,,+#,...,i,.,;**++*:.,,:x***iiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznzznnxWWMxnzzzz+*i,,,,,.,,,,,,,,,:z;,,..,:..,,,,::.,..,;xi*iiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzznxxxzzzzzz+ii,...,.,,,,,,.,,+zi.,,.,,.,,.,,..,,,,,++iiiiiiiiiiiiiiii*i,.,,.
,,.,,#zzzzzzzzzzzzzzzzzznMzzzznz#ii:.,.,..,,,,,,,izn:,..,.,,..,...,,.,,,#*iiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzznxzzzzzz#ii;.,.,..,,,,.,:zzz,,..,,,,.,...,,,,,,:+*iiiiiiiiiiiiiiii*i,.,,.
,,.,,#zzzzzzzzzzzzzzzznzxxzzzznzz*i;..,,,.,,,,..;zz*..,.,,,,........,.,**iiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzznzxMnzzznzz*ii,.,,,,,,,,,,ii:,,,,,,,,,,,,,,.,,.,;+*iiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzxMzzzzzzz**i,,.,..,,,,,;*:*,,,.,,...,,,,,,.,,,**iiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzzzzzMMnnzzzzz*ii:.,,,,,,..,#nnn#+,,,,,..,,....,.,i+i*iiiiiiiiiiiiiiiii*i,.,,.
,,.,,#zzzzzzzzzzzznzznnzMMnxzzzzz**i;.,,,,.,,.,zxWWWxi,,,:*,,,..,.,,,#**iiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzzznM+WMxxzzzzz***;..,,,,,,..;xWWWWn+**#;,,,,.,,,.i#*iiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzznW#zWMxnnzzzz*iii,.,,,,,,,,,+nWMWWWMx+,,,,,.,,,,++i*iiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzznMM,zWMMnnzzz#*ii*;.,,,,,,::iznxMMWWWWn#;,,.,,,,*#**iiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzzzzMWz,zMMMxxznn#*ii*i::;i++#zznxWxxxWWWxxxzi,.,,,,#+iiiiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzznMWW#,#MMMMMnznz*ii**izzzzzzxMMWWnxM@WMMMMzzi,.,,+*+iiiiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzznMWWW#,*xMMMMnznz*iiii+MnnnnnxMWWWxxMxMxMxxxnz*,,,*+*iiii**iiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzzzMWWWW#;;zMMMMMnnz#*i*#MWxxxxxMWMxMMxMxMWWWWxMzn;.i:#*iiii**iiiiiiiiiiiiiii*i,.,..
,,,,,#zzzzzznnzxWWWWW#:;+MMMMMxzzz#*zzxWMWMWxMWWMMWWMMWWWWMxxMn:,*:#iiiiiiiiiiiiiiiiiiiiii*i,.,..
,,.,,#zzzzzzzzxWWWWWWz::inMMMMMxznzzzzznxMMMxxxMMxxxzxMWWWMMWWx:ii+*iiiiiiiiiiiiiiiiiiiiii*i,.,..
....,#zzzzzzznWWWWWWWz;,;+MMMMMMxzzzzzzzzznz#**i;::,,:;#nxxWMM+;*;+*iiiiiiiiiiiiiiiiiiiiii*i,.,..
...,,#zzzzzznMWWWWWWWni,,*nWMMMMMxnzzzzzzzz#i*i,,,,:,,,,:+#z##i#+#*iiiiiiiiiiiiiiiiiiiiiii*i,.,..
...,,#zzznnnxWWWWWWWWx*,.i+MMMMMMMMxxnzz#+****i,i**#z+;,:*iiii*zz+*iiiiiiiiiiiiiiiiiiiiiii*i,.,..
,,,,,#nzzzxMMWWWWWWWWW*;.:*#WMMMMMMMMxz+**iiiii;*++####:;i****zz#*iiiiiiiiiiiiiiiiiiiiiiii*i,.,,.
,,,,,#zznMWxWWWWWWWWWWz;,.;*nWMMMMMMMMnz#ii:.....,,,,,,,,ii*+zzz*ii**iiiiiiiiiiiiiiiiiiiii*i,.,..
,,,,,#nxWWMxWWWWWWWWWWW;:,,*+xMMMMMMMMMxnz*:.,,,,,..,,,,,,i#nnx+i*i*iiiiiiiiiiiiiiiiiiiiii*i,.,..
,,,,,zWWWWMxWWWWWWWWWWW*;,.,*+MMMMMMWMMWMx#*:,,,,....,,,,:#nMM#+*ii*iiiiiiiiiiiiiiiiiiiiii*i,.,..
,,,,,xWWWWxWWWWWWWWWWWWx::,,:;+MMMMMMWMWMMnz+:....,,.,,,,+MWMM*#z+*iiiiiiii**iiiiiiiiiiiii*i,.,..
,,,,,xWWWMxWWWWWWWWWWWWW+:,,,;:+MMMMMMMMMMMxnz*;,,:,,,i+#xM++W#+nz#iii*iiiiiiiiiiiiiiiiiii*i,.,..
,,,,,xWWWMMWWWWWWWWWWWWWx,,..,;,*xWMMMMMMMWMWxnn####+##nxx#,+Wx*nznz:i**iiiiiiiiiiiiiiiiii*i,.,..
,,.,,xWWWxMWWWWWWWWWWWWWWi.,,,,:,*#MMMMMMMMMMWMMxxxxxxxMnn,.zWM#;zzMn;*i*iiiiiiiiiiiiiiiii*i,.,..
,..,,xWWWxWWWWWWWWWWWWWWWx,,,,,,:,;+MMWMMMMWWWWWWWMMMMMxn:..nWWni+nzMn#niii**iiiiiiiiiiiii*i,.,..
,..,,xWWMxWWWWWWWWWWWWWWWWi,,,,.,:,,;xWMMMMMMMMMMMMMMxnni...xMWxz;znnMxxM#;i*i**iiiiiiiiii*i,.,..
,..,,xWWMMWWWWWWWWWWWWWWWWz.,,...::,,;zWMMMMMMMMMMMMnzzi,,,,MMMMx*innxMxxWx+iiii**iiiiiiii*i,.,..
,..,,xWWMMWWWWWWWWWWWWWWWWM:,,...,:,,,,+xWMMMMMMMMxnnzi,.,,,MMMMMzinxMxMxxMMM#;i**iiiiiiii*i,.,..
,..,,xWWxWWWWWWWWWWWWWWWWWW*.,.,.,,:,,.,i+xWWMMMMxnnni,,,,,.WMMMMMz#nMMxMMMMMWxi;i*iiii*ii*i,,,..
,..,,xWWxWWWWWWWWWWWWWWWWWWz.,,,,.,,:,,,,::#@WMMxnnn;..,,.,:WMWMMMMznxWxxWMMMMMM#;iiiiiiii*i,,,..
,..,.nWMMWWWWWWWWWWWWWWWWWWM,.,,,...,,..,.,.iMWMxnz:.,.,,.,;WMWMMMMnzxMMxMMMMMMWMxi;i*iii*ii..,..
,..,,nWWMMWWWWWWWWWWWWWWWWWWi,,,....,.,,.,,,,:nxxz:,.,,,...iWMWMMMWMznMMMxMMMMMMMMMzi;i**iii..,.,
,..,,xWWWMMWWWWWWWWWWWWWWWWW#:.....,....,.,,..:#+,..,,,....:WWMMMMMMxnnMMMxWMMMMMMMWM#;;*i*i,.,..
,..,,xWWWWWMMWWWWWWWWWWWWWWWxi:..,.......,,,,..;;,...,,...,,@WMMMMMMMxzxMMxxMMWMMMMMMWx+;iii,,,..
,..,,xWWWWWWMMMWWWWWWWWWWWWWM*i,,,,......,,,,,;MWx+,..,,,..,@WMMMMMMMMnzxxnMMMMMMMMMMMWWx+ii,,,,.
,..,,xWWWWWWWMxWWWWWWWWWWWWWW+*;,,,,.....,,.,,xWWW@n:.,,,,.,WWMMMMMMMMMnnnMMMMMMMMMMMMWMWMxz,,,..
,..,,xWWWWWWWWMxWWWWWWWWWWWWWzi*;,,,,.....,,,nWMMMWWM:.,,,..MWMMMWMMMMMMnMMMMMMMMMMMMMMMMMMx,.,.,
,..,,xWWWWWWWWMxWWWWWWWWWWWWWMiii;,,.,,...,.zWWWWWWWWn,.....zWMMMMMMMMMMMxMMMMMMMMMMMMMMMMMx,,,..
,..,,xWWWWWWWWMWWWWWWWWWWWWWWWiii*;,,,,,,.,z@WWWWWWWWW*,..,,zWMMMMMMMMMMMMnMMMMMMMMMMMMMMMMx,,,..
,..,,xWWWWWWWMWWWWWWWWWWWWWWW@+,;ii:,,.,,,zWWWWWWWWWWWM:.,,,#WMMMMMMMMMMMMxnMMWMMMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWz,.;i*:...,ixWWWWWWWWWMMW+,,,.+WMMMMMMMMMMMMMxxMWWMMMMMMMMMMMx,,,..
,..,.xWWWWWWWWWWWWWWWWWWWWWWWWM,,,iii,,,;i+WWWWWWWWW#+xx;,,.+WWMMMMMMMMMMMWMxxMMMMMMMMMMMMMx,,,,,
,..,.xWWWMWWWWWWWWWWWWWWWWWWWWW;.,:iii,:ii*xWWWWWWWW+i*Mz,.,*WWMMMMMMMMMMMMWMxnMMMMMMMMMMMMx,,,..
,..,.xWWWMWWWWWWWWWWWWWWWWWWWWWz.,.;i*iiiiinWWWWWWWW*i*+z*.,iWWMMMMMMMMMMMMMMMxxMMMMMMMMMMMx,,,..
,..,.xWWWMMWWWWWWWWWWWWWWWWWWWWx,,,.i***;:i#WWWWWWWMi*ii*zi,;WWMMMMMMMMMMMMMMMMxMMMMMMMMMMMx,,,,.
,..,,xWWWWMMWWWWWWWWWWWWWWWWWWWW;,,.:*ii,,i+WWWWWWWM::iiiizi:WWMMMMMMMMMMMMMMMMMMMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWW+,,,.,i,,,;*WWWWWWWx:.:iii*z*MWMMMMMMMMMMMMMMMMMWMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWWn,,,,...,,:*MWWWWWWn:..;ii**xWWMMMMMMMMMMMMMMMMWWMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWWW:.,.,,,.,,iMWWWWWWz,.,,i*i*nWWMMMMMMMMMMMMMMMWWMMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWW@*..,,,..,,ixWWWWWWz..,.,i*inWWMMMMMMMMMMMMMMMWWMMMMMMMMMMMx,,,,.
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWWWn,.,,,,,,,;n@WWWWWn..,,,:*izWWMMMMMMMMMMMMMMWWWWMMMMMMMMMMx,,,..
,..,,xWWWWWWWWWWWWWWWWWWWWWWWWWWWM:.,,,....:xWWWWWWM,,,,,.:izMWMMMMMMMMMMMMMMMWWMMMMMMMMMMMx,,,..
,..,,nMWWWWWWWWWWWWWWWWWWWWWMWWWWM#*********MWWWWWWW+*******nMWMMMMMMMMMMMMMMMMMMMMMMMMMMMMx,,,..
,..,,nMWWMMMMMMMMMMMMMMMMWWMMMMMWMMMWWMMMWWMMMMMMMMMMMMWWMWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMx,,,..
2018-10-11 17:37:58 +02:00
$conditions [ 'includeRelatedTags' ] = 1 ;
2018-07-19 11:48:22 +02:00
}
2021-09-30 20:08:45 +02:00
if ( ! empty ( $namedParams [ 'includeDecayScore' ])) {
2019-08-12 16:34:26 +02:00
$conditions [ 'includeDecayScore' ] = 1 ;
}
2021-09-30 20:08:45 +02:00
if ( isset ( $namedParams [ 'public' ]) && $namedParams [ 'public' ]) {
2018-07-19 11:48:22 +02:00
$conditions [ 'distribution' ] = array ( 3 , 5 );
}
2021-09-30 20:08:45 +02:00
if ( ! empty ( $namedParams [ 'overrideLimit' ]) && ! $this -> _isRest ()) {
2018-07-19 11:48:22 +02:00
$conditions [ 'overrideLimit' ] = 1 ;
}
2021-09-30 20:08:45 +02:00
if ( ! empty ( $namedParams [ 'excludeGalaxy' ])) {
2018-07-19 11:48:22 +02:00
$conditions [ 'excludeGalaxy' ] = 1 ;
2021-09-30 20:08:45 +02:00
if ( ! empty ( $namedParams [ 'includeCustomGalaxyCluster' ])) {
2020-03-12 10:26:09 +01:00
$conditions [ 'includeCustomGalaxyCluster' ] = 1 ;
}
2018-07-19 11:48:22 +02:00
}
2021-09-30 20:08:45 +02:00
if ( ! empty ( $namedParams [ 'extended' ]) || ! empty ( $this -> request -> data [ 'extended' ])) {
2018-07-19 11:48:22 +02:00
$conditions [ 'extended' ] = 1 ;
$this -> set ( 'extended' , 1 );
} else {
$this -> set ( 'extended' , 0 );
}
2020-07-22 19:06:00 +02:00
$conditions [ 'excludeLocalTags' ] = false ;
2020-09-03 15:24:03 +02:00
$conditions [ 'includeWarninglistHits' ] = true ;
2021-09-30 20:08:45 +02:00
if ( isset ( $namedParams [ 'excludeLocalTags' ])) {
$conditions [ 'excludeLocalTags' ] = $namedParams [ 'excludeLocalTags' ];
2020-07-16 10:56:32 +02:00
}
2019-01-18 16:15:22 +01:00
$conditions [ 'includeFeedCorrelations' ] = 1 ;
2018-11-23 14:11:33 +01:00
if ( ! $this -> _isRest ()) {
$conditions [ 'includeGranularCorrelations' ] = 1 ;
2021-09-30 20:08:45 +02:00
} else if ( ! empty ( $namedParams [ 'includeGranularCorrelations' ])) {
2019-06-18 10:51:16 +02:00
$conditions [ 'includeGranularCorrelations' ] = 1 ;
2018-11-23 14:11:33 +01:00
}
2021-09-30 20:08:45 +02:00
if ( ! isset ( $namedParams [ 'includeServerCorrelations' ])) {
2019-01-18 16:15:22 +01:00
$conditions [ 'includeServerCorrelations' ] = 1 ;
if ( $this -> _isRest ()) {
$conditions [ 'includeServerCorrelations' ] = 0 ;
}
} else {
2021-09-30 20:08:45 +02:00
$conditions [ 'includeServerCorrelations' ] = $namedParams [ 'includeServerCorrelations' ];
2019-01-18 16:15:22 +01:00
}
2021-03-10 18:27:19 +01:00
2021-08-10 21:26:06 +02:00
if ( $this -> _isRest ()) {
foreach ([ 'includeEventCorrelations' , 'includeFeedCorrelations' , 'includeWarninglistHits' , 'noEventReports' , 'noShadowAttributes' ] as $param ) {
2021-09-30 20:08:45 +02:00
if ( isset ( $namedParams [ $param ])) {
$conditions [ $param ] = $namedParams [ $param ];
2021-08-10 21:26:06 +02:00
}
}
}
2021-03-10 18:27:19 +01:00
// Site admin can view event as different user
2021-09-30 20:08:45 +02:00
if ( $this -> _isSiteAdmin () && isset ( $namedParams [ 'viewAs' ])) {
$user = $this -> User -> getAuthUser ( $namedParams [ 'viewAs' ]);
2021-03-10 18:27:19 +01:00
if ( empty ( $user )) {
throw new NotFoundException ( __ ( " User not found " ));
}
$this -> Flash -> info ( __ ( 'Viewing event as %s from %s' , h ( $user [ 'email' ]), h ( $user [ 'Organisation' ][ 'name' ])));
} else {
$user = $this -> Auth -> user ();
}
$results = $this -> Event -> fetchEvent ( $user , $conditions );
2020-10-04 13:16:33 +02:00
if ( empty ( $results )) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$event = $results [ 0 ];
// Attach related attributes to proper attribute
2021-09-30 20:08:45 +02:00
if ( ! empty ( $namedParams [ 'includeGranularCorrelations' ]) && ! empty ( $event [ 'RelatedAttribute' ])) {
2020-10-04 13:16:33 +02:00
foreach ( $event [ 'RelatedAttribute' ] as $attribute_id => $relation ) {
foreach ( $event [ 'Attribute' ] as $k2 => $attribute ) {
if (( int ) $attribute [ 'id' ] == $attribute_id ) {
$event [ 'Attribute' ][ $k2 ][ 'RelatedAttribute' ][] = $relation ;
break 2 ;
}
}
foreach ( $event [ 'Object' ] as $k2 => $object ) {
foreach ( $object [ 'Attribute' ] as $k3 => $attribute ) {
if (( int ) $attribute [ 'id' ] == $attribute_id ) {
$event [ 'Object' ][ $k2 ][ 'Attribute' ][ $k3 ][ 'RelatedAttribute' ][] = $relation ;
break 3 ;
2019-06-18 10:51:16 +02:00
}
}
}
}
}
2020-10-04 13:16:33 +02:00
2020-07-22 19:06:00 +02:00
$this -> Event -> id = $event [ 'Event' ][ 'id' ];
2021-09-30 20:08:45 +02:00
if ( isset ( $namedParams [ 'searchFor' ]) && $namedParams [ 'searchFor' ] !== '' ) {
$this -> __applyQueryString ( $event , $namedParams [ 'searchFor' ]);
2019-01-31 14:39:24 +01:00
}
2021-09-30 20:08:45 +02:00
if ( isset ( $namedParams [ 'taggedAttributes' ]) && $namedParams [ 'taggedAttributes' ] !== '' ) {
$this -> __applyQueryString ( $event , $namedParams [ 'taggedAttributes' ], 'Tag.name' );
2019-02-13 14:59:49 +01:00
}
2021-09-30 20:08:45 +02:00
if ( isset ( $namedParams [ 'galaxyAttachedAttributes' ]) && $namedParams [ 'galaxyAttachedAttributes' ] !== '' ) {
$this -> __applyQueryString ( $event , $namedParams [ 'galaxyAttachedAttributes' ], 'Tag.name' );
2019-02-13 14:59:49 +01:00
}
2018-07-19 11:48:22 +02:00
if ( $this -> _isRest ()) {
2022-03-16 01:28:59 +01:00
if ( $this -> RestResponse -> isAutomaticTool () && $event [ 'Event' ][ 'protected' ]) {
2022-03-15 22:59:52 +01:00
$this -> RestResponse -> signContents = true ;
}
2021-01-17 20:54:14 +01:00
return $this -> __restResponse ( $event );
}
2020-10-04 13:16:33 +02:00
2021-10-19 18:27:16 +02:00
$this -> set ( 'deleted' , $deleted > 0 );
2021-09-30 20:08:45 +02:00
$this -> set ( 'includeRelatedTags' , ( ! empty ( $namedParams [ 'includeRelatedTags' ])) ? 1 : 0 );
$this -> set ( 'includeDecayScore' , ( ! empty ( $namedParams [ 'includeDecayScore' ])) ? 1 : 0 );
2021-01-17 20:54:14 +01:00
2022-11-30 16:00:17 +01:00
$this -> __setHighlightedTags ( $event );
2021-01-17 20:54:14 +01:00
if ( $this -> _isSiteAdmin () && $event [ 'Event' ][ 'orgc_id' ] !== $this -> Auth -> user ( 'org_id' )) {
$this -> Flash -> info ( __ ( 'You are currently logged in as a site administrator and about to edit an event not belonging to your organisation. This goes against the sharing model of MISP. Use a normal user account for day to day work.' ));
2018-07-19 11:48:22 +02:00
}
2021-03-10 18:27:19 +01:00
$this -> __viewUI ( $user , $event , $continue , $fromEvent );
2018-07-19 11:48:22 +02:00
}
2021-03-03 10:01:36 +01:00
/**
* @ param int $id
* @ param string $info
* @ param string $date
*/
2018-07-19 11:48:22 +02:00
private function __startPivoting ( $id , $info , $date )
{
2021-03-03 10:01:36 +01:00
$initialPivot = [
'id' => $id ,
'info' => $info ,
'date' => $date ,
'depth' => 0 ,
'height' => 0 ,
'children' => [],
'deletable' => true ,
];
$this -> Session -> write ( 'pivot_thread' , $initialPivot );
2018-07-19 11:48:22 +02:00
}
2021-03-03 10:01:36 +01:00
/**
* @ param int $id
* @ param string $info
* @ param string $date
* @ param int $fromEvent
*/
2018-07-19 11:48:22 +02:00
private function __continuePivoting ( $id , $info , $date , $fromEvent )
{
$pivot = $this -> Session -> read ( 'pivot_thread' );
2021-03-03 10:01:36 +01:00
if ( ! is_array ( $pivot )) {
$this -> __startPivoting ( $id , $info , $date );
return ;
}
$newPivot = [
'id' => $id ,
'info' => $info ,
'date' => $date ,
'depth' => null ,
'children' => [],
'deletable' => true ,
];
2018-07-19 11:48:22 +02:00
if ( ! $this -> __checkForPivot ( $pivot , $id )) {
$pivot = $this -> __insertPivot ( $pivot , $fromEvent , $newPivot , 0 );
}
$this -> Session -> write ( 'pivot_thread' , $pivot );
}
2021-03-03 10:01:36 +01:00
/**
* @ param array $pivot
* @ param int $oldId
* @ param array $newPivot
* @ param int $depth
* @ return array
*/
private function __insertPivot ( array $pivot , $oldId , array $newPivot , $depth )
2018-07-19 11:48:22 +02:00
{
$depth ++ ;
if ( $pivot [ 'id' ] == $oldId ) {
$newPivot [ 'depth' ] = $depth ;
$pivot [ 'children' ][] = $newPivot ;
return $pivot ;
}
if ( ! empty ( $pivot [ 'children' ])) {
foreach ( $pivot [ 'children' ] as $k => $v ) {
$pivot [ 'children' ][ $k ] = $this -> __insertPivot ( $v , $oldId , $newPivot , $depth );
}
}
return $pivot ;
}
2021-03-03 10:01:36 +01:00
/**
* @ param array $pivot
* @ param int $id
* @ return bool
*/
private function __checkForPivot ( array $pivot , $id )
2018-07-19 11:48:22 +02:00
{
if ( $id == $pivot [ 'id' ]) {
return true ;
}
foreach ( $pivot [ 'children' ] as $k => $v ) {
if ( $this -> __checkForPivot ( $v , $id )) {
return true ;
}
}
return false ;
}
private function __arrangePivotVertical ( & $pivot )
{
if ( empty ( $pivot )) {
return null ;
}
$max = count ( $pivot [ 'children' ]) - 1 ;
if ( $max < 0 ) {
$max = 0 ;
}
$temp = 0 ;
$pivot [ 'children' ] = array_values ( $pivot [ 'children' ]);
foreach ( $pivot [ 'children' ] as $k => $v ) {
$pivot [ 'children' ][ $k ][ 'height' ] = ( $temp + $k ) * 50 ;
$temp += $this -> __arrangePivotVertical ( $pivot [ 'children' ][ $k ]);
if ( $k == $max ) {
$temp = $pivot [ 'children' ][ $k ][ 'height' ] / 50 ;
}
}
return $temp ;
}
public function removePivot ( $id , $eventId , $self = false )
{
$pivot = $this -> Session -> read ( 'pivot_thread' );
if ( $pivot [ 'id' ] == $id ) {
$pivot = null ;
$this -> Session -> write ( 'pivot_thread' , null );
$this -> redirect ( array ( 'controller' => 'events' , 'action' => 'view' , $eventId ));
} else {
$pivot = $this -> __doRemove ( $pivot , $id );
}
$this -> Session -> write ( 'pivot_thread' , $pivot );
$pivot = $this -> __arrangePivotVertical ( $pivot );
$this -> redirect ( array ( 'controller' => 'events' , 'action' => 'view' , $eventId , true , $eventId ));
}
2021-10-29 16:30:24 +02:00
/**
* @ param array $event
* @ param string $searchFor
* @ param string | false $filterColumnsOverwrite
*/
2022-05-29 09:26:27 +02:00
private function __applyQueryString ( & $event , $searchFor , $filterColumnsOverwrite = false )
2020-10-06 09:56:43 +02:00
{
2019-01-31 14:39:24 +01:00
// filtering on specific columns is specified
if ( $filterColumnsOverwrite !== false ) {
$filterValue = array_map ( 'trim' , explode ( " , " , $filterColumnsOverwrite ));
} else {
2020-10-06 09:56:43 +02:00
$filterColumnsOverwrite = Configure :: read ( 'MISP.event_view_filter_fields' ) ? : 'id,uuid,value,comment,type,category,Tag.name' ;
2019-01-31 14:39:24 +01:00
$filterValue = array_map ( 'trim' , explode ( " , " , $filterColumnsOverwrite ));
2022-05-29 09:26:27 +02:00
$validFilters = [ 'id' , 'uuid' , 'value' , 'comment' , 'type' , 'category' , 'Tag.name' ];
2019-01-31 14:39:24 +01:00
foreach ( $filterValue as $k => $v ) {
2021-10-29 16:30:24 +02:00
if ( ! in_array ( $v , $validFilters , true )) {
2019-01-31 14:39:24 +01:00
unset ( $filterValue [ $k ]);
}
}
}
2021-10-29 14:39:23 +02:00
$searchParts = explode ( '|' , mb_strtolower ( $searchFor ));
2019-01-31 14:39:24 +01:00
// search in all attributes
2022-05-29 09:26:27 +02:00
$foundAttributes = [];
foreach ( $event [ 'Attribute' ] as $attribute ) {
if ( $this -> __valueInFieldAttribute ( $attribute , $filterValue , $searchParts )) {
$foundAttributes [] = $attribute ;
2019-01-31 14:39:24 +01:00
}
}
2022-05-29 09:26:27 +02:00
$event [ 'Attribute' ] = $foundAttributes ;
2019-01-31 14:39:24 +01:00
2022-05-29 09:26:27 +02:00
// search in all proposals
$foundProposals = [];
foreach ( $event [ 'ShadowAttribute' ] as $proposals ) {
if ( $this -> __valueInFieldAttribute ( $proposals , $filterValue , $searchParts )) {
$foundProposals [] = $proposals ;
2019-01-31 14:39:24 +01:00
}
}
2022-05-29 09:26:27 +02:00
$event [ 'ShadowAttribute' ] = $foundProposals ;
2019-01-31 14:39:24 +01:00
// search for all attributes in object
foreach ( $event [ 'Object' ] as $k => $object ) {
2021-10-29 14:39:23 +02:00
if ( $this -> __valueInFieldAttribute ( $object , [ 'id' , 'uuid' , 'name' , 'comment' ], $searchParts )) {
2021-02-15 15:17:00 +01:00
continue ;
}
2022-05-29 09:26:27 +02:00
$foundAttributes = [];
foreach ( $object [ 'Attribute' ] as $attribute ) {
if ( $this -> __valueInFieldAttribute ( $attribute , $filterValue , $searchParts )) {
$foundAttributes [] = $attribute ;
2019-01-31 14:39:24 +01:00
}
}
2022-05-29 09:26:27 +02:00
if ( empty ( $foundAttributes )) {
unset ( $event [ 'Object' ][ $k ]); // remove object if contains no attributes
2019-01-31 14:39:24 +01:00
} else {
2022-05-29 09:26:27 +02:00
$event [ 'Object' ][ $k ][ 'Attribute' ] = $foundAttributes ;
2019-01-31 14:39:24 +01:00
}
}
$event [ 'Object' ] = array_values ( $event [ 'Object' ]);
}
2022-05-29 09:26:27 +02:00
/**
* Search for a value on an attribute level for a specific field .
*
* @ param array $attribute An attribute
* @ param array $fields List of keys in attribute to search in
* @ param array $searchParts Values to search ( OR )
* @ return bool Returns true on match
*/
private function __valueInFieldAttribute ( $attribute , $fields , $searchParts )
{
foreach ( $fields as $field ) {
if ( $field === 'Tag.name' ) {
if ( empty ( $attribute [ 'AttributeTag' ])) {
continue ;
}
foreach ( $attribute [ 'AttributeTag' ] as $fieldValue ) {
$fieldValue = mb_strtolower ( $fieldValue [ 'Tag' ][ 'name' ]);
foreach ( $searchParts as $s ) {
if ( strpos ( $fieldValue , $s ) !== false ) {
return true ;
}
}
}
} else {
if ( ! isset ( $attribute [ $field ])) {
continue ;
}
$fieldValue = mb_strtolower ( $attribute [ $field ]);
foreach ( $searchParts as $s ) {
if ( strpos ( $fieldValue , $s ) !== false ) {
return true ;
}
}
}
}
return false ;
}
2019-02-01 11:35:01 +01:00
// look in the parameters if we are doing advanced filtering or not
2021-10-29 14:39:23 +02:00
private function __checkIfAdvancedFiltering ( $filters )
{
2020-10-06 09:56:43 +02:00
$advancedFilteringActive = array_diff_key ( $filters , array ( 'sort' => 0 , 'direction' => 0 , 'focus' => 0 , 'overrideLimit' => 0 , 'filterColumnsOverwrite' => 0 , 'attributeFilter' => 0 , 'extended' => 0 , 'page' => 0 ));
2019-02-13 11:30:05 +01:00
2019-02-01 11:35:01 +01:00
if ( count ( $advancedFilteringActive ) > 0 ) {
2019-09-06 11:22:14 +02:00
if ( count ( array_diff_key ( $advancedFilteringActive , array ( 'deleted' , 'includeRelatedTags' , 'includeDecayScore' ))) > 0 ) {
2019-02-01 15:36:59 +01:00
$res = true ;
} else if (
2019-09-13 15:34:12 +02:00
( isset ( $advancedFilteringActive [ 'deleted' ]) && $advancedFilteringActive [ 'deleted' ] == 2 ) ||
( isset ( $advancedFilteringActive [ 'includeRelatedTags' ]) && $advancedFilteringActive [ 'includeRelatedTags' ] == 1 ) ||
2019-09-12 10:18:52 +02:00
( isset ( $advancedFilteringActive [ 'includeDecayScore' ]) && $advancedFilteringActive [ 'includeDecayScore' ] == 1 )
2019-02-01 11:35:01 +01:00
) {
2019-02-01 15:36:59 +01:00
$res = true ;
2019-02-01 11:35:01 +01:00
} else {
2019-02-01 15:36:59 +01:00
$res = false ;
2019-02-01 11:35:01 +01:00
}
} else {
$res = false ;
}
2019-02-01 16:18:34 +01:00
unset ( $filters [ 'sort' ]);
unset ( $filters [ 'direction' ]);
2019-02-13 14:59:49 +01:00
$activeRules = array ();
2019-02-01 16:18:34 +01:00
foreach ( $filters as $k => $v ) {
2021-10-23 16:38:27 +02:00
if ( isset ( self :: DEFAULT_FILTERING_RULE [ $k ]) && self :: DEFAULT_FILTERING_RULE [ $k ] != $v ) {
2021-10-18 18:10:09 +02:00
$activeRules [ $k ] = $v ;
2019-02-01 16:18:34 +01:00
}
}
2019-02-13 11:30:05 +01:00
return array ( 'active' => $activeRules > 0 ? $res : false , 'activeRules' => $activeRules );
2019-02-01 11:35:01 +01:00
}
2018-07-19 11:48:22 +02:00
private function __doRemove ( & $pivot , $id )
{
foreach ( $pivot [ 'children' ] as $k => $v ) {
if ( $v [ 'id' ] == $id ) {
unset ( $pivot [ 'children' ][ $k ]);
return $pivot ;
} else {
$pivot [ 'children' ][ $k ] = $this -> __doRemove ( $pivot [ 'children' ][ $k ], $id );
}
}
return $pivot ;
}
private function __setDeletable ( & $pivot , $id , $root = false )
{
if ( $pivot [ 'id' ] == $id && ! $root ) {
$pivot [ 'deletable' ] = false ;
return true ;
}
if ( ! empty ( $pivot [ 'children' ])) {
foreach ( $pivot [ 'children' ] as $k => $v ) {
$containsCurrent = $this -> __setDeletable ( $pivot [ 'children' ][ $k ], $id );
if ( $containsCurrent && ! $root ) {
$pivot [ 'deletable' ] = false ;
}
}
}
return ! $pivot [ 'deletable' ];
}
public function add ()
{
$sgs = $this -> Event -> SharingGroup -> fetchAllAuthorised ( $this -> Auth -> user (), 'name' , 1 );
if ( $this -> request -> is ( 'post' )) {
if ( $this -> _isRest ()) {
if ( empty ( $this -> data )) {
throw new MethodNotAllowedException ( __ ( 'No valid event data received.' ));
}
// rearrange the response if the event came from an export
if ( isset ( $this -> request -> data [ 'response' ])) {
$this -> request -> data = $this -> request -> data [ 'response' ];
}
2018-08-08 11:27:49 +02:00
if ( isset ( $this -> request -> data [ 'request' ])) {
$this -> request -> data = $this -> request -> data [ 'request' ];
}
2018-07-19 11:48:22 +02:00
if ( ! isset ( $this -> request -> data [ 'Event' ])) {
2018-08-08 11:27:49 +02:00
$this -> request -> data = array ( 'Event' => $this -> request -> data );
2018-07-19 11:48:22 +02:00
}
// Distribution, reporter for the events pushed will be the owner of the authentication key
$this -> request -> data [ 'Event' ][ 'user_id' ] = $this -> Auth -> user ( 'id' );
}
2022-03-13 12:35:58 +01:00
if (
! empty ( $this -> request -> data [ 'Event' ][ 'protected' ]) &&
$this -> Auth -> user ( 'Role' )[ 'perm_sync' ] &&
! $this -> Auth -> user ( 'Role' )[ 'perm_site_admin' ]
) {
$pgp_signature = $this -> request -> header ( 'x-pgp-signature' );
2022-03-14 00:30:44 +01:00
if ( empty ( $pgp_signature )) {
throw new MethodNotAllowedException ( __ ( 'Protected event failed signature validation as no key was provided.' ));
}
2022-03-13 12:35:58 +01:00
$raw_data = $this -> request -> input ();
if (
2022-03-14 00:30:44 +01:00
! $this -> Event -> CryptographicKey -> validateProtectedEvent (
2022-03-14 15:54:24 +01:00
$raw_data ,
2022-03-13 12:35:58 +01:00
$this -> Auth -> user (),
$pgp_signature ,
$this -> request -> data
)
) {
throw new MethodNotAllowedException ( __ ( 'Protected event failed signature validation.' ));
}
}
2018-07-19 11:48:22 +02:00
if ( ! empty ( $this -> data )) {
if ( ! isset ( $this -> request -> data [ 'Event' ][ 'distribution' ])) {
2021-10-10 11:37:54 +02:00
$this -> request -> data [ 'Event' ][ 'distribution' ] = Configure :: read ( 'MISP.default_event_distribution' ) ? : 0 ;
2018-07-19 11:48:22 +02:00
}
if ( ! isset ( $this -> request -> data [ 'Event' ][ 'analysis' ])) {
$this -> request -> data [ 'Event' ][ 'analysis' ] = 0 ;
}
if ( ! isset ( $this -> request -> data [ 'Event' ][ 'threat_level_id' ])) {
2021-10-10 11:37:54 +02:00
$this -> request -> data [ 'Event' ][ 'threat_level_id' ] = Configure :: read ( 'MISP.default_event_threat_level' ) ? : 4 ;
2018-07-19 11:48:22 +02:00
}
if ( ! isset ( $this -> request -> data [ 'Event' ][ 'date' ])) {
$this -> request -> data [ 'Event' ][ 'date' ] = date ( 'Y-m-d' );
}
// If the distribution is set to sharing group, check if the id provided is really visible to the user, if not throw an error.
if ( $this -> request -> data [ 'Event' ][ 'distribution' ] == 4 ) {
if ( $this -> userRole [ 'perm_sync' ] && $this -> _isRest ()) {
if ( isset ( $this -> request -> data [ 'Event' ][ 'SharingGroup' ])) {
if ( ! isset ( $this -> request -> data [ 'Event' ][ 'SharingGroup' ][ 'uuid' ])) {
if ( $this -> Event -> SharingGroup -> checkIfExists ( $this -> request -> data [ 'Event' ][ 'SharingGroup' ][ 'uuid' ]) &&
$this -> Event -> SharingGroup -> checkIfAuthorised ( $this -> Auth -> user (), $this -> request -> data [ 'Event' ][ 'SharingGroup' ][ 'uuid' ])) {
throw new MethodNotAllowedException ( __ ( 'Invalid Sharing Group or not authorised (Sync user is not contained in the Sharing group).' ));
}
}
} elseif ( ! isset ( $sgs [ $this -> request -> data [ 'Event' ][ 'sharing_group_id' ]])) {
throw new MethodNotAllowedException ( __ ( 'Invalid Sharing Group or not authorised.' ));
}
} else {
if ( ! isset ( $sgs [ $this -> request -> data [ 'Event' ][ 'sharing_group_id' ]])) {
throw new MethodNotAllowedException ( __ ( 'Invalid Sharing Group or not authorised.' ));
}
}
} else {
// If the distribution is set to something "traditional", set the SG id to 0.
$this -> request -> data [ 'Event' ][ 'sharing_group_id' ] = 0 ;
}
// If we are not sync users / site admins, we only allow events to be created for our own org
// Set the orgc ID as our own orgc ID and unset both the 2.4 and 2.3 style creator orgs
if ( $this -> _isRest () && ! $this -> userRole [ 'perm_sync' ]) {
$this -> request -> data [ 'Event' ][ 'orgc_id' ] = $this -> Auth -> user ( 'org_id' );
if ( isset ( $this -> request -> data [ 'Event' ][ 'Orgc' ])) {
unset ( $this -> request -> data [ 'Event' ][ 'Orgc' ]);
}
if ( isset ( $this -> request -> data [ 'Event' ][ 'orgc' ])) {
unset ( $this -> request -> data [ 'Event' ][ 'orgc' ]);
}
}
$validationErrors = array ();
$created_id = 0 ;
$add = $this -> Event -> _add ( $this -> request -> data , $this -> _isRest (), $this -> Auth -> user (), '' , null , false , null , $created_id , $validationErrors );
2021-08-11 09:38:57 +02:00
if ( $add === true ) {
2018-07-19 11:48:22 +02:00
if ( $this -> _isRest ()) {
// REST users want to see the newly created event
2020-10-28 10:04:55 +01:00
$metadata = $this -> request -> param ( 'named.metadata' );
$results = $this -> Event -> fetchEvent ( $this -> Auth -> user (), [ 'eventid' => $created_id , 'metadata' => $metadata ]);
2018-07-19 11:48:22 +02:00
$event = $results [ 0 ];
if ( ! empty ( $validationErrors )) {
$event [ 'errors' ] = $validationErrors ;
}
2021-01-17 20:54:14 +01:00
return $this -> __restResponse ( $event );
2018-07-19 11:48:22 +02:00
} else {
// redirect to the view of the newly created event
$this -> Flash -> success ( __ ( 'The event has been saved' ));
$this -> redirect ( array ( 'action' => 'view' , $this -> Event -> getID ()));
}
} else {
if ( $this -> _isRest ()) { // TODO return error if REST
if ( is_numeric ( $add )) {
2020-08-17 15:52:32 +02:00
$this -> response -> header ( 'Location' , $this -> baseurl . '/events/' . $add );
2018-07-19 11:48:22 +02:00
$this -> response -> send ();
throw new NotFoundException ( __ ( 'Event already exists, if you would like to edit it, use the url in the location header.' ));
}
2021-08-11 09:38:57 +02:00
if ( $add === 'blocked' ) {
throw new ForbiddenException ( __ ( 'Event blocked by organisation blocklist.' ));
} else if ( $add === 'Blocked by blocklist' ) {
throw new ForbiddenException ( __ ( 'Event blocked by event blocklist.' ));
} else if ( $add === 'Blocked by event block rules' ) {
throw new ForbiddenException ( __ ( 'Blocked by event block rules.' ));
}
2018-07-19 11:48:22 +02:00
// # TODO i18n?
2019-02-06 18:04:05 +01:00
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'add' , false , $validationErrors , $this -> response -> type ());
2018-07-19 11:48:22 +02:00
} else {
if ( $add === 'blocked' ) {
2020-09-01 12:56:35 +02:00
$this -> Flash -> error ( __ ( 'A blocklist entry is blocking you from creating any events. Please contact the administration team of this instance' ) . ( Configure :: read ( 'MISP.contact' ) ? ' at ' . Configure :: read ( 'MISP.contact' ) : '' ) . '.' );
2018-07-19 11:48:22 +02:00
} else {
$this -> Flash -> error ( __ ( 'The event could not be saved. Please, try again.' ), 'default' , array (), 'error' );
}
}
}
}
} elseif ( $this -> _isRest ()) {
return $this -> RestResponse -> describe ( 'Events' , 'add' , false , $this -> response -> type ());
}
$this -> request -> data [ 'Event' ][ 'date' ] = date ( 'Y-m-d' );
2019-11-11 23:35:53 +01:00
if ( isset ( $this -> request -> data [ 'Event' ][ 'distribution' ])) {
$initialDistribution = $this -> request -> data [ 'Event' ][ 'distribution' ];
} else {
$initialDistribution = 3 ;
if ( Configure :: read ( 'MISP.default_event_distribution' ) != null ) {
$initialDistribution = Configure :: read ( 'MISP.default_event_distribution' );
}
}
$this -> set ( 'initialDistribution' , $initialDistribution );
2018-07-19 11:48:22 +02:00
// combobox for distribution
$distributions = array_keys ( $this -> Event -> distributionDescriptions );
$distributions = $this -> _arrayToValuesIndexArray ( $distributions );
$this -> set ( 'distributions' , $distributions );
// tooltip for distribution
2019-11-11 23:35:53 +01:00
$fieldDesc = array ();
2018-07-19 11:48:22 +02:00
$distributionLevels = $this -> Event -> distributionLevels ;
if ( empty ( $sgs )) {
unset ( $distributionLevels [ 4 ]);
}
$this -> set ( 'distributionLevels' , $distributionLevels );
foreach ( $distributionLevels as $key => $value ) {
2019-11-11 23:35:53 +01:00
$fieldDesc [ 'distribution' ][ $key ] = $this -> Event -> distributionDescriptions [ $key ][ 'formdesc' ];
2018-07-19 11:48:22 +02:00
}
// combobox for risks
2021-08-11 09:38:57 +02:00
$threat_levels = array_column ( $this -> Event -> ThreatLevel -> find ( 'all' ), 'ThreatLevel' );
$this -> set ( 'threatLevels' , array_column ( $threat_levels , 'name' , 'id' ));
$fieldDesc [ 'threat_level_id' ] = array_column ( $threat_levels , 'description' , 'id' );
2019-11-12 14:57:57 +01:00
2018-07-19 11:48:22 +02:00
// combobox for analysis
$this -> set ( 'sharingGroups' , $sgs );
// tooltip for analysis
2019-11-11 23:35:53 +01:00
$analysisLevels = $this -> Event -> analysisLevels ;
$this -> set ( 'analysisLevels' , $analysisLevels );
foreach ( $analysisLevels as $key => $value ) {
$fieldDesc [ 'analysis' ][ $key ] = $this -> Event -> analysisDescriptions [ $key ][ 'formdesc' ];
2018-07-19 11:48:22 +02:00
}
2022-10-05 18:06:31 +02:00
if ( Configure :: read ( 'MISP.unpublishedprivate' )) {
$this -> Flash -> info ( __ ( 'The event created will be visible only to your organisation until it is published.' ));
} else {
$this -> Flash -> info ( __ ( 'The event created will be visible to the organisations having an account on this platform, but not synchronised to other MISP instances until it is published.' ));
}
2019-11-11 23:35:53 +01:00
$this -> set ( 'fieldDesc' , $fieldDesc );
2019-05-06 15:38:08 +02:00
if ( isset ( $this -> params [ 'named' ][ 'extends' ])) {
$this -> set ( 'extends_uuid' , $this -> params [ 'named' ][ 'extends' ]);
}
2018-07-19 11:48:22 +02:00
}
public function addIOC ( $id )
{
$this -> Event -> recursive = - 1 ;
$this -> Event -> read ( null , $id );
2020-07-20 10:10:47 +02:00
if ( ! $this -> __canModifyEvent ( $this -> Event -> data )) {
2018-07-19 11:48:22 +02:00
throw new UnauthorizedException ( __ ( 'You do not have permission to do that.' ));
}
if ( $this -> request -> is ( 'post' )) {
if ( ! empty ( $this -> data )) {
if ( isset ( $this -> data [ 'Event' ][ 'submittedioc' ])) {
$this -> _addIOCFile ( $id );
}
// redirect to the view of the newly created event
$this -> Flash -> success ( __ ( 'The event has been saved' ));
}
}
// set the id
$this -> set ( 'id' , $id );
// set whether it is published or not
2023-04-12 14:54:15 +02:00
$this -> set ( 'published' , $this -> Event -> data [ 'Event' ][ 'published' ] ? ? false );
2018-07-19 11:48:22 +02:00
}
public function add_misp_export ()
{
if ( $this -> request -> is ( 'post' )) {
$results = array ();
2022-05-29 10:11:09 +02:00
if ( ! empty ( $this -> request -> data )) {
2023-02-17 15:59:34 +01:00
if ( empty ( $this -> request -> data [ 'Event' ])) {
$this -> request -> data [ 'Event' ] = $this -> request -> data ;
}
2022-05-29 10:11:09 +02:00
if ( ! empty ( $this -> request -> data [ 'Event' ][ 'filecontent' ])) {
$data = $this -> request -> data [ 'Event' ][ 'filecontent' ];
$isXml = $data [ 0 ] === '<' ;
} elseif ( isset ( $this -> request -> data [ 'Event' ][ 'submittedfile' ])) {
$file = $this -> request -> data [ 'Event' ][ 'submittedfile' ];
if ( $file [ 'error' ] === UPLOAD_ERR_NO_FILE ) {
$this -> Flash -> error ( __ ( 'No file was uploaded.' ));
$this -> redirect ([ 'controller' => 'events' , 'action' => 'add_misp_export' ]);
}
2021-09-20 15:53:11 +02:00
2022-05-29 10:11:09 +02:00
$ext = strtolower ( pathinfo ( $file [ 'name' ], PATHINFO_EXTENSION ));
if (( $ext !== 'xml' && $ext !== 'json' ) && $file [ 'size' ] > 0 && is_uploaded_file ( $file [ 'tmp_name' ])) {
$log = ClassRegistry :: init ( 'Log' );
$log -> createLogEntry ( $this -> Auth -> user (), 'file_upload' , 'Event' , 0 , 'MISP export file upload failed' , 'File details: ' . json_encode ( $file ));
$this -> Flash -> error ( __ ( 'You may only upload MISP XML or MISP JSON files.' ));
throw new MethodNotAllowedException ( __ ( 'File upload failed or file does not have the expected extension (.xml / .json).' ));
}
2021-09-20 15:53:11 +02:00
2022-05-29 10:11:09 +02:00
$isXml = $ext === 'xml' ;
$data = FileAccessTool :: readFromFile ( $file [ 'tmp_name' ], $file [ 'size' ]);
} else {
throw new MethodNotAllowedException ( __ ( 'No file uploaded.' ));
2018-07-19 11:48:22 +02:00
}
2021-09-20 15:53:11 +02:00
$takeOwnership = Configure :: read ( 'MISP.take_ownership_xml_import' )
2022-05-29 10:11:09 +02:00
&& ( isset ( $this -> request -> data [ 'Event' ][ 'takeownership' ]) && $this -> request -> data [ 'Event' ][ 'takeownership' ] == 1 );
2021-09-20 15:53:11 +02:00
2022-10-07 15:30:20 +02:00
$publish = $this -> request -> data [ 'Event' ][ 'publish' ] ? ? false ;
2021-09-20 15:53:11 +02:00
try {
2022-10-07 15:30:20 +02:00
$results = $this -> Event -> addMISPExportFile ( $this -> Auth -> user (), $data , $isXml , $takeOwnership , $publish );
2021-09-20 15:53:11 +02:00
} catch ( Exception $e ) {
2022-05-29 10:11:09 +02:00
$this -> log ( " Exception during processing MISP file import: { $e -> getMessage () } " );
2022-12-22 16:15:53 +01:00
$this -> Flash -> error ( __ ( 'Could not process MISP export file. %s' , $e -> getMessage ()));
2021-09-20 15:53:11 +02:00
$this -> redirect ([ 'controller' => 'events' , 'action' => 'add_misp_export' ]);
2018-07-19 11:48:22 +02:00
}
}
$this -> set ( 'results' , $results );
$this -> render ( 'add_misp_export_result' );
}
2022-10-06 17:19:23 +02:00
$this -> set ( 'title_for_layout' , __ ( 'Import from MISP Export File' ));
2018-07-19 11:48:22 +02:00
}
2023-04-13 15:30:17 +02:00
public function upload_stix ( $stix_version = '1' , $publish = false , $galaxies_as_tags = true , $debug = false )
2018-07-19 11:48:22 +02:00
{
2023-04-20 20:37:02 +02:00
$sgs = $this -> Event -> SharingGroup -> fetchAllAuthorised ( $this -> Auth -> user (), 'name' , 1 );
$initialDistribution = 0 ;
if ( Configure :: read ( 'MISP.default_event_distribution' ) != null ) {
$initialDistribution = Configure :: read ( 'MISP.default_event_distribution' );
}
$distributionLevels = $this -> Event -> distributionLevels ;
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'post' )) {
if ( $this -> _isRest ()) {
2021-10-26 08:54:04 +02:00
if ( isset ( $this -> params [ 'named' ][ 'publish' ])) {
$publish = $this -> params [ 'named' ][ 'publish' ];
}
2023-04-20 20:37:02 +02:00
if ( isset ( $this -> params [ 'named' ][ 'distribution' ])) {
2023-04-21 16:26:09 +02:00
$distribution = intval ( $this -> params [ 'named' ][ 'distribution' ]);
2023-12-12 10:57:57 +01:00
if ( ! array_key_exists ( $distribution , $distributionLevels )) {
2023-04-20 20:37:02 +02:00
throw new MethodNotAllowedException ( __ ( 'Wrong distribution level' ));
}
2023-12-12 10:57:57 +01:00
} else {
$distribution = $initialDistribution ;
2023-04-20 20:37:02 +02:00
}
2023-04-21 15:21:29 +02:00
$sharingGroupId = null ;
2023-12-12 10:57:57 +01:00
if ( $distribution == 4 ) {
2023-04-21 15:21:29 +02:00
if ( ! isset ( $this -> params [ 'named' ][ 'sharing_group_id' ])) {
throw new MethodNotAllowedException ( __ ( 'The sharing group id is needed when the distribution is set to 4 ("Sharing group").' ));
}
2023-04-21 16:26:09 +02:00
$sharingGroupId = intval ( $this -> params [ 'named' ][ 'sharing_group_id' ]);
2023-04-21 16:36:54 +02:00
if ( ! array_key_exists ( $sharingGroupId , $sgs )) {
2023-04-21 15:21:29 +02:00
throw new MethodNotAllowedException ( __ ( 'Please select a valid sharing group id.' ));
}
}
2023-12-12 10:57:57 +01:00
$clusterDistribution = $initialDistribution ;
$clusterSharingGroupId = null ;
2023-04-13 15:30:17 +02:00
if ( isset ( $this -> params [ 'named' ][ 'galaxies_as_tags' ])) {
$galaxies_as_tags = $this -> params [ 'named' ][ 'galaxies_as_tags' ];
2023-12-12 10:57:57 +01:00
if ( isset ( $this -> params [ 'name' ][ 'cluster_distribution' ])) {
$clusterDistribution = intval ( $this -> params [ 'named' ][ 'cluster_distribution' ]);
if ( ! array_key_exists ( $clusterDistribution , $distributionLevels )) {
throw new MethodNotAllowedException ( __ ( 'Wrong cluster distribution level' ));
}
if ( $clusterDistribution == 4 ) {
if ( ! isset ( $this -> params [ 'named' ][ 'cluster_sharing_group_id' ])) {
throw new MethodNotAllowedException ( __ ( 'The cluster sharing group id is needed when the cluster distribution is set to 4 ("Sharing group").' ));
}
$clusterSharingGroupId = intval ( $this -> params [ 'named' ][ 'cluster_sharing_group_id' ]);
if ( ! array_key_exists ( $clusterSharingGroupId , $sgs )) {
throw new MethodNotAllowedException ( __ ( 'Please select a valid cluster sharing group id.' ));
}
}
}
2023-04-13 15:30:17 +02:00
}
if ( isset ( $this -> params [ 'named' ][ 'debugging' ])) {
$debug = $this -> params [ 'named' ][ 'debugging' ];
}
2021-10-13 13:18:49 +02:00
$filePath = FileAccessTool :: writeToTempFile ( $this -> request -> input ());
2019-09-28 02:35:22 +02:00
$result = $this -> Event -> upload_stix (
$this -> Auth -> user (),
2021-10-13 13:18:49 +02:00
$filePath ,
2019-09-28 02:35:22 +02:00
$stix_version ,
2019-12-19 16:17:05 +01:00
'uploaded_stix_file.' . ( $stix_version == '1' ? 'xml' : 'json' ),
2023-04-13 15:30:17 +02:00
$publish ,
2023-12-12 10:57:57 +01:00
$distribution ,
2023-04-21 15:21:29 +02:00
$sharingGroupId ,
2023-04-13 15:30:17 +02:00
$galaxies_as_tags ,
2023-12-12 10:57:57 +01:00
$clusterDistribution ,
$clusterSharingGroupId ,
2023-04-13 15:30:17 +02:00
$debug
2019-09-28 02:35:22 +02:00
);
2021-09-29 14:54:08 +02:00
if ( is_numeric ( $result )) {
2018-07-19 11:48:22 +02:00
$event = $this -> Event -> fetchEvent ( $this -> Auth -> user (), array ( 'eventid' => $result ));
if ( ! empty ( $event )) {
2019-05-21 15:05:35 +02:00
return $this -> RestResponse -> viewData ( $event [ 0 ], 'json' );
2018-07-19 11:48:22 +02:00
} else {
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'upload_stix' , false , 'Could not read saved event.' , $this -> response -> type ());
}
} else {
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'upload_stix' , false , $result , $this -> response -> type ());
}
} else {
2019-12-19 16:17:05 +01:00
$original_file = ! empty ( $this -> data [ 'Event' ][ 'original_file' ]) ? $this -> data [ 'Event' ][ 'stix' ][ 'name' ] : '' ;
2018-07-19 11:48:22 +02:00
if ( isset ( $this -> data [ 'Event' ][ 'stix' ]) && $this -> data [ 'Event' ][ 'stix' ][ 'size' ] > 0 && is_uploaded_file ( $this -> data [ 'Event' ][ 'stix' ][ 'tmp_name' ])) {
2021-10-13 13:18:49 +02:00
$filePath = FileAccessTool :: createTempFile ();
if ( ! move_uploaded_file ( $this -> data [ 'Event' ][ 'stix' ][ 'tmp_name' ], $filePath )) {
2021-09-29 14:54:08 +02:00
throw new Exception ( " Could not move uploaded STIX file. " );
}
2023-04-13 15:30:17 +02:00
if ( isset ( $this -> data [ 'Event' ][ 'debug' ])) {
$debug = $this -> data [ 'Event' ][ 'debug' ];
}
2019-09-28 02:35:22 +02:00
$result = $this -> Event -> upload_stix (
$this -> Auth -> user (),
2021-10-13 13:18:49 +02:00
$filePath ,
2019-09-28 02:35:22 +02:00
$stix_version ,
$original_file ,
2023-04-13 15:30:17 +02:00
$this -> data [ 'Event' ][ 'publish' ],
2023-04-20 20:37:02 +02:00
$this -> data [ 'Event' ][ 'distribution' ],
2024-01-02 17:54:17 +01:00
$this -> data [ 'Event' ][ 'sharing_group_id' ] ? ? null ,
2023-09-28 13:12:56 +02:00
$this -> data [ 'Event' ][ 'galaxies_handling' ],
2023-12-12 10:57:57 +01:00
$this -> data [ 'Event' ][ 'cluster_distribution' ],
$this -> data [ 'Event' ][ 'cluster_sharing_group_id' ],
2023-04-13 15:30:17 +02:00
$debug
2019-09-28 02:35:22 +02:00
);
2021-09-29 14:54:08 +02:00
if ( is_numeric ( $result )) {
2018-07-19 11:48:22 +02:00
$this -> Flash -> success ( __ ( 'STIX document imported.' ));
$this -> redirect ( array ( 'action' => 'view' , $result ));
} else {
2021-09-29 14:54:08 +02:00
$this -> Flash -> error ( __ ( 'Could not import STIX document: %s' , $result ));
2018-07-19 11:48:22 +02:00
}
} else {
2020-12-05 13:55:23 +01:00
$maxUploadSize = intval ( ini_get ( 'post_max_size' ));
if ( intval ( ini_get ( 'upload_max_filesize' )) < $maxUploadSize ) {
$maxUploadSize = intval ( ini_get ( 'upload_max_filesize' ));
2018-07-19 11:48:22 +02:00
}
2020-12-05 13:55:23 +01:00
$this -> Flash -> error ( __ ( 'File upload failed. Make sure that you select a STIX file to be uploaded and that the file doesn\'t exceed the maximum file size of %s MB.' , $maxUploadSize ));
2018-07-19 11:48:22 +02:00
}
}
}
2021-09-29 14:54:08 +02:00
$this -> set ( 'stix_version' , $stix_version == 2 ? '2.x JSON' : '1.x XML' );
2023-04-20 20:37:02 +02:00
$this -> set ( 'initialDistribution' , $initialDistribution );
$distributions = array_keys ( $this -> Event -> distributionDescriptions );
$distributions = $this -> _arrayToValuesIndexArray ( $distributions );
$this -> set ( 'distributions' , $distributions );
$fieldDesc = array ();
if ( empty ( $sgs )) {
unset ( $distributionLevels [ 4 ]);
}
$this -> set ( 'distributionLevels' , $distributionLevels );
foreach ( $distributionLevels as $key => $value ) {
$fieldDesc [ 'distribution' ][ $key ] = $this -> Event -> distributionDescriptions [ $key ][ 'formdesc' ];
}
2024-01-03 08:55:29 +01:00
$debugOptions = [
0 => __ ( 'Standard debugging' ),
1 => __ ( 'Advanced debugging' ),
];
$debugDescriptions = [
0 => __ ( 'The critical errors are logged in the usual log file.' ),
1 => __ ( 'All the errors and warnings are logged in the usual log file.' ),
];
$galaxiesOptions = [
0 => __ ( 'As MISP standard format' ),
1 => __ ( 'As tag names' ),
];
$galaxiesOptionsDescriptions = [
0 => __ ( 'Galaxies and Clusters are passed as MISP standard format. New generic Galaxies and Clusters are created when there is no match with existing ones.' ),
1 => __ ( 'Galaxies are passed as tags and there is only a simple search with existing galaxy tag names.' ),
];
2023-09-28 12:46:43 +02:00
$this -> set ( 'debugOptions' , $debugOptions );
foreach ( $debugOptions as $key => $value ) {
2024-01-03 08:55:29 +01:00
$fieldDesc [ 'debug' ][ $key ] = $debugDescriptions [ $key ];
2023-09-28 12:46:43 +02:00
}
$this -> set ( 'galaxiesOptions' , $galaxiesOptions );
foreach ( $galaxiesOptions as $key => $value ) {
2024-01-03 08:55:29 +01:00
$fieldDesc [ 'galaxies_handling' ][ $key ] = $galaxiesOptionsDescriptions [ $key ];
2023-09-28 12:46:43 +02:00
}
2023-04-20 20:37:02 +02:00
$this -> set ( 'sharingGroups' , $sgs );
$this -> set ( 'fieldDesc' , $fieldDesc );
2018-07-19 11:48:22 +02:00
}
2020-07-06 16:43:18 +02:00
public function merge ( $target_id = null , $source_id = null )
2018-07-19 11:48:22 +02:00
{
2020-07-06 16:43:18 +02:00
if ( $this -> request -> is ( 'post' )) {
if ( empty ( $this -> request -> data [ 'Event' ])) {
$this -> request -> data = [ 'Event' => $this -> request -> data ];
}
2018-07-19 11:48:22 +02:00
}
2020-07-06 16:43:18 +02:00
$extractedParams = array ( 'target_id' , 'source_id' );
foreach ( $extractedParams as $param ) {
if ( empty ( ${$param} )) {
if ( ! empty ( $this -> request -> data [ 'Event' ][ $param ])) {
${$param} = $this -> request -> data [ 'Event' ][ $param ];
} else {
if ( $param === 'target_id' || $this -> request -> is ( 'post' )) {
throw new InvalidArgumentException ( __ ( 'This action requires a target_id for GET requests and both a target_id and a source_id for POST requests.' ));
}
}
}
2018-07-19 11:48:22 +02:00
}
2020-12-05 20:44:55 +01:00
$target_event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $target_id , [ 'contain' => [ 'Orgc' ]]);
2020-07-19 16:22:16 +02:00
if ( empty ( $target_event )) {
throw new NotFoundException ( __ ( 'Invalid target event.' ));
}
2020-07-20 10:10:47 +02:00
if ( ! $this -> __canModifyEvent ( $target_event )) {
throw new ForbiddenException ( __ ( 'You do not have permission to do that.' ));
}
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'post' )) {
2020-07-06 16:43:18 +02:00
$source_id = $this -> Toolbox -> findIdByUuid ( $this -> Event , $source_id );
$source_event = $this -> Event -> fetchEvent (
$this -> Auth -> user (),
[
'eventid' => $source_id ,
'includeAllTags' => 1 ,
'includeAttachments' => 1
]
);
if ( empty ( $source_event )) {
throw new NotFoundException ( __ ( 'Invalid source event.' ));
}
2021-02-15 16:36:17 +01:00
$recovered_uuids = [];
2020-07-06 16:43:18 +02:00
foreach ( $source_event [ 0 ][ 'Attribute' ] as & $attribute ) {
unset ( $attribute [ 'id' ]);
2021-02-15 16:36:17 +01:00
$originalUUID = $attribute [ 'uuid' ];
2020-07-06 16:43:18 +02:00
$attribute [ 'uuid' ] = CakeText :: uuid ();
2021-02-15 16:36:17 +01:00
$recovered_uuids [ $originalUUID ] = $attribute [ 'uuid' ];
2020-07-06 16:43:18 +02:00
unset ( $attribute [ 'ShadowAttribute' ]);
$attribute [ 'Tag' ] = [];
foreach ( $attribute [ 'AttributeTag' ] as $aT ) {
$attribute [ 'Tag' ][] = $aT [ 'Tag' ];
$aT [ 'Tag' ][ 'local' ] = $aT [ 'local' ];
2018-07-19 11:48:22 +02:00
}
2020-07-06 16:43:18 +02:00
unset ( $attribute [ 'AttributeTag' ]);
}
foreach ( $source_event [ 0 ][ 'Object' ] as & $object ) {
unset ( $object [ 'id' ]);
2021-02-15 16:36:17 +01:00
$originalUUID = $object [ 'uuid' ];
2020-07-06 16:43:18 +02:00
$object [ 'uuid' ] = CakeText :: uuid ();
2021-02-15 16:36:17 +01:00
$recovered_uuids [ $originalUUID ] = $object [ 'uuid' ];
2020-07-06 16:43:18 +02:00
foreach ( $object [ 'Attribute' ] as & $attribute ) {
unset ( $attribute [ 'id' ]);
2021-02-15 16:36:17 +01:00
$originalUUID = $attribute [ 'uuid' ];
2020-07-06 16:43:18 +02:00
$attribute [ 'uuid' ] = CakeText :: uuid ();
2021-02-15 16:36:17 +01:00
$recovered_uuids [ $originalUUID ] = $attribute [ 'uuid' ];
2020-07-06 16:43:18 +02:00
unset ( $attribute [ 'ShadowAttribute' ]);
$attribute [ 'Tag' ] = [];
foreach ( $attribute [ 'AttributeTag' ] as $aT ) {
$attribute [ 'Tag' ][] = $aT [ 'Tag' ];
$aT [ 'Tag' ][ 'local' ] = $aT [ 'local' ];
}
unset ( $attribute [ 'AttributeTag' ]);
2018-07-19 11:48:22 +02:00
}
}
2021-02-15 16:36:17 +01:00
foreach ( $source_event [ 0 ][ 'Object' ] as & $object ) {
foreach ( $object [ 'ObjectReference' ] as & $reference ) {
if ( isset ( $recovered_uuids [ $object [ 'uuid' ]])) {
$reference [ 'object_uuid' ] = $recovered_uuids [ $object [ 'uuid' ]];
}
if ( isset ( $recovered_uuids [ $reference [ 'referenced_uuid' ]])) {
$reference [ 'referenced_uuid' ] = $recovered_uuids [ $reference [ 'referenced_uuid' ]];
}
}
}
foreach ( $source_event [ 0 ][ 'EventReport' ] as & $report ) {
unset ( $report [ 'id' ], $report [ 'event_id' ]);
$report [ 'uuid' ] = CakeText :: uuid ();
}
2020-07-06 16:43:18 +02:00
$results = [
'results' => [
'Object' => $source_event [ 0 ][ 'Object' ],
2021-02-15 16:35:20 +01:00
'Attribute' => $source_event [ 0 ][ 'Attribute' ],
'EventReport' => $source_event [ 0 ][ 'EventReport' ]
2020-07-06 16:43:18 +02:00
]
];
if ( $this -> _isRest ()) {
$this -> loadModel ( 'Log' );
2021-02-15 16:35:20 +01:00
$save_results = [ 'attributes' => 0 , 'objects' => 0 , 'eventReports' => 0 ];
2020-07-06 16:43:18 +02:00
foreach ( $results [ 'results' ][ 'Attribute' ] as $attribute ) {
2021-08-30 15:49:46 +02:00
$this -> Event -> Attribute -> captureAttribute ( $attribute , $target_id , $this -> Auth -> user ());
2018-07-19 11:48:22 +02:00
}
2020-07-06 16:43:18 +02:00
foreach ( $results [ 'results' ][ 'Object' ] as $object ) {
2021-08-30 17:08:49 +02:00
$this -> Event -> Object -> captureObject ( $object , $target_id , $this -> Auth -> user ());
2020-04-28 10:00:09 +02:00
}
2021-02-15 16:35:20 +01:00
foreach ( $results [ 'results' ][ 'EventReport' ] as $report ) {
$this -> Event -> EventReport -> captureReport ( $this -> Auth -> user (), $report , $target_id );
}
2020-07-06 16:43:18 +02:00
$event = $this -> Event -> fetchEvent (
$this -> Auth -> user (),
[
'eventid' => $target_id
]
2018-07-19 11:48:22 +02:00
);
2020-07-06 16:43:18 +02:00
return $this -> RestResponse -> viewData ( $event , $this -> response -> type ());
2018-07-19 11:48:22 +02:00
}
2020-07-06 16:43:18 +02:00
$event = $this -> Event -> handleMispFormatFromModuleResult ( $results );
2020-07-19 16:22:16 +02:00
$event [ 'Event' ] = $target_event [ 'Event' ];
2020-04-28 10:00:09 +02:00
$distributions = $this -> Event -> Attribute -> distributionLevels ;
$sgs = $this -> Event -> SharingGroup -> fetchAllAuthorised ( $this -> Auth -> user (), 'name' , 1 );
if ( empty ( $sgs )) {
unset ( $distributions [ 4 ]);
}
$this -> set ( 'distributions' , $distributions );
$this -> set ( 'sgs' , $sgs );
2020-07-06 16:43:18 +02:00
$this -> set ( 'event' , $event );
2021-06-29 13:38:33 +02:00
$this -> set ( 'title_for_layout' , __ ( 'Event merge results' ));
2020-07-06 16:43:18 +02:00
$this -> set ( 'title' , __ ( 'Event merge results' ));
2018-07-19 11:48:22 +02:00
$this -> set ( 'importComment' , 'Merged from event ' . $source_id );
2020-07-06 16:43:18 +02:00
$this -> render ( 'resolved_misp_format' );
2020-07-19 16:22:16 +02:00
} else {
$this -> set ( 'target_event' , $target_event );
2021-06-29 13:38:33 +02:00
$this -> set ( 'title_for_layout' , __ ( 'Merge data from event' ));
2018-07-19 11:48:22 +02:00
}
}
2023-02-14 08:59:06 +01:00
public function populate ( $id , $regenerateUUIDs = false )
2022-02-10 12:31:11 +01:00
{
if ( $this -> request -> is ( 'get' ) && $this -> _isRest ()) {
return $this -> RestResponse -> describe ( 'Events' , 'populate' , false , $this -> response -> type ());
}
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id , [ 'contain' => [ 'Orgc' ]]);
if ( ! $event ) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$id = $event [ 'Event' ][ 'id' ]; // change possible event UUID with real ID
// check if private and user not authorised to edit
if ( ! $this -> __canModifyEvent ( $event ) && ! ( $this -> userRole [ 'perm_sync' ] && $this -> _isRest ())) {
$message = __ ( 'You are not authorised to do that.' );
if ( $this -> _isRest ()) {
throw new ForbiddenException ( $message );
} else {
$this -> Flash -> error ( $message );
$this -> redirect ( array ( 'controller' => 'events' , 'action' => 'index' ));
}
}
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
if ( isset ( $this -> request -> data [ 'Event' ])) {
2023-02-14 08:59:06 +01:00
$regenerateUUIDs = $this -> request -> data [ 'Event' ][ 'regenerate_uuids' ] ? ? false ;
2022-02-10 12:31:11 +01:00
$this -> request -> data = $this -> request -> data [ 'Event' ];
}
if ( isset ( $this -> request -> data [ 'json' ])) {
2022-10-19 14:36:18 +02:00
$this -> request -> data = $this -> _jsonDecode ( $this -> request -> data [ 'json' ]);
2022-02-10 12:31:11 +01:00
}
2023-02-14 08:34:47 +01:00
if ( isset ( $this -> request -> data [ 'Event' ])) {
$this -> request -> data = $this -> request -> data [ 'Event' ];
}
2022-02-10 12:31:11 +01:00
$eventToSave = $event ;
2024-02-14 11:22:43 +01:00
$capturedObjects = [ 'Attribute' , 'Object' , 'Tag' , 'Galaxy' , 'EventReport' , 'Note' , 'Opinion' , 'Relationship' ,];
2022-02-10 12:31:11 +01:00
foreach ( $capturedObjects as $objectType ) {
if ( ! empty ( $this -> request -> data [ $objectType ])) {
2023-02-14 08:59:06 +01:00
if ( ! empty ( $regenerateUUIDs )) {
foreach ( $this -> request -> data [ $objectType ] as $i => $obj ) {
unset ( $this -> request -> data [ $objectType ][ $i ][ 'id' ]);
unset ( $this -> request -> data [ $objectType ][ $i ][ 'uuid' ]);
2023-04-13 09:28:10 +02:00
if ( $objectType === 'Object' && ! empty ( $this -> request -> data [ $objectType ][ $i ][ 'Attribute' ])) {
foreach ( $this -> request -> data [ $objectType ][ $i ][ 'Attribute' ] as $j => $attr ) {
unset ( $this -> request -> data [ $objectType ][ $i ][ 'Attribute' ][ $j ][ 'id' ]);
unset ( $this -> request -> data [ $objectType ][ $i ][ 'Attribute' ][ $j ][ 'uuid' ]);
}
}
2023-02-14 08:59:06 +01:00
}
}
2022-02-10 12:31:11 +01:00
$eventToSave [ 'Event' ][ $objectType ] = $this -> request -> data [ $objectType ];
}
}
$eventToSave [ 'Event' ][ 'published' ] = 0 ;
2022-10-19 14:36:18 +02:00
$eventToSave [ 'Event' ][ 'timestamp' ] = time ();
2022-02-10 12:31:11 +01:00
$result = $this -> Event -> _edit ( $eventToSave , $this -> Auth -> user (), $id );
if ( $this -> _isRest ()) {
if ( $result === true ) {
// REST users want to see the newly created event
$metadata = $this -> request -> param ( 'named.metadata' );
$results = $this -> Event -> fetchEvent ( $this -> Auth -> user (), [ 'eventid' => $id , 'metadata' => $metadata ]);
$event = $results [ 0 ];
return $this -> __restResponse ( $event );
} else {
$message = 'Error' ;
if ( $this -> _isRest ()) {
if ( isset ( $result [ 'error' ])) {
$errors = $result [ 'error' ];
} else {
$errors = $result ;
}
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'populate' , $id , $errors , $this -> response -> type ());
} else {
$this -> set ( array ( 'message' => $message , '_serialize' => array ( 'message' ))); // $this->Event->validationErrors
$this -> render ( 'populate' );
}
return false ;
}
}
if ( $result ) {
$this -> Flash -> success ( __ ( 'The event has been saved' ));
$this -> redirect ( array ( 'action' => 'view' , $id ));
} else {
$this -> Flash -> error ( __ ( 'The event could not be saved. Please, try again.' ));
}
}
$this -> set ( 'event' , $event );
}
2018-07-19 11:48:22 +02:00
public function edit ( $id = null )
{
if ( $this -> request -> is ( 'get' ) && $this -> _isRest ()) {
return $this -> RestResponse -> describe ( 'Events' , 'edit' , false , $this -> response -> type ());
}
2022-03-17 00:47:06 +01:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id , [ 'contain' => [ 'Orgc' , 'CryptographicKey' ]]);
2020-11-02 13:02:22 +01:00
if ( ! $event ) {
2018-07-19 11:48:22 +02:00
throw new NotFoundException ( __ ( 'Invalid event' ));
}
2020-11-02 13:02:22 +01:00
$id = $event [ 'Event' ][ 'id' ]; // change possible event UUID with real ID
2018-07-19 11:48:22 +02:00
// check if private and user not authorised to edit
2020-11-02 13:02:22 +01:00
if ( ! $this -> __canModifyEvent ( $event ) && ! ( $this -> userRole [ 'perm_sync' ] && $this -> _isRest ())) {
2020-07-20 10:10:47 +02:00
$message = __ ( 'You are not authorised to do that.' );
if ( $this -> _isRest ()) {
throw new ForbiddenException ( $message );
} else {
$this -> Flash -> error ( $message );
$this -> redirect ( array ( 'controller' => 'events' , 'action' => 'index' ));
2018-07-19 11:48:22 +02:00
}
}
2022-03-13 16:42:07 +01:00
if (
! empty ( $event [ 'Event' ][ 'protected' ]) &&
$this -> Auth -> user ( 'Role' )[ 'perm_sync' ] &&
! $this -> Auth -> user ( 'Role' )[ 'perm_site_admin' ]
) {
$pgp_signature = $this -> request -> header ( 'x-pgp-signature' );
2022-03-14 00:30:44 +01:00
if ( empty ( $pgp_signature )) {
throw new MethodNotAllowedException ( __ ( 'Protected event failed signature validation as no key was provided.' ));
}
2022-03-13 16:42:07 +01:00
$raw_data = $this -> request -> input ();
if (
2022-03-14 00:30:44 +01:00
! $this -> Event -> CryptographicKey -> validateProtectedEvent (
2022-03-13 16:42:07 +01:00
$raw_data ,
$this -> Auth -> user (),
$pgp_signature ,
2022-03-17 00:47:06 +01:00
$event
2022-03-13 16:42:07 +01:00
)
) {
throw new MethodNotAllowedException ( __ ( 'Protected event failed signature validation.' ));
}
}
2018-07-19 11:48:22 +02:00
if ( ! $this -> _isRest ()) {
$this -> Event -> insertLock ( $this -> Auth -> user (), $id );
}
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
2020-11-02 13:02:22 +01:00
$this -> Event -> set ( $event );
2018-07-19 11:48:22 +02:00
if ( $this -> _isRest ()) {
if ( isset ( $this -> request -> data [ 'response' ])) {
$this -> request -> data = $this -> Event -> updateXMLArray ( $this -> request -> data , true );
} else {
$this -> request -> data = $this -> Event -> updateXMLArray ( $this -> request -> data , false );
}
// Workaround for different structure in XML/array than what CakePHP expects
if ( isset ( $this -> request -> data [ 'response' ])) {
$this -> request -> data = $this -> request -> data [ 'response' ];
}
if ( ! isset ( $this -> request -> data [ 'Event' ])) {
$this -> request -> data = array ( 'Event' => $this -> request -> data );
}
2023-11-15 07:37:11 +01:00
$fast_update = $this -> request -> param ( 'named.fast_update' );
2023-11-20 14:13:15 +01:00
if ( ! empty ( $this -> request -> data [ 'Event' ][ 'fast_update' ])) {
$fast_update = ( bool ) $this -> request -> data [ 'Event' ][ 'fast_update' ];
}
if ( $fast_update ) {
$this -> Event -> fast_update = true ;
$this -> Event -> Attribute -> fast_update = true ;
}
$result = $this -> Event -> _edit ( $this -> request -> data , $this -> Auth -> user (), $id , null , null , false );
2018-07-19 11:48:22 +02:00
if ( $result === true ) {
// REST users want to see the newly created event
2020-10-28 10:04:55 +01:00
$metadata = $this -> request -> param ( 'named.metadata' );
$results = $this -> Event -> fetchEvent ( $this -> Auth -> user (), [ 'eventid' => $id , 'metadata' => $metadata ]);
2018-07-19 11:48:22 +02:00
$event = $results [ 0 ];
2021-01-17 20:54:14 +01:00
return $this -> __restResponse ( $event );
2018-07-19 11:48:22 +02:00
} else {
$message = 'Error' ;
if ( $this -> _isRest ()) {
if ( isset ( $result [ 'error' ])) {
$errors = $result [ 'error' ];
} else {
2019-02-06 18:04:05 +01:00
$errors = $result ;
2018-07-19 11:48:22 +02:00
}
2019-02-06 18:04:05 +01:00
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'edit' , $id , $errors , $this -> response -> type ());
2018-07-19 11:48:22 +02:00
} else {
2019-02-10 13:08:12 +01:00
$this -> set ( array ( 'message' => $message , '_serialize' => array ( 'message' ))); // $this->Event->validationErrors
2018-07-19 11:48:22 +02:00
$this -> render ( 'edit' );
}
return false ;
}
}
// say what fields are to be updated
$fieldList = array ( 'date' , 'threat_level_id' , 'analysis' , 'info' , 'published' , 'distribution' , 'timestamp' , 'sharing_group_id' , 'extends_uuid' );
// always force the org, but do not force it for admins
if ( ! $this -> _isSiteAdmin ()) {
// set the same org as existed before
2020-11-02 13:02:22 +01:00
$this -> request -> data [ 'Event' ][ 'org_id' ] = $event [ 'Event' ][ 'org_id' ];
2018-07-19 11:48:22 +02:00
}
// we probably also want to remove the published flag
$this -> request -> data [ 'Event' ][ 'published' ] = 0 ;
2022-10-12 20:32:39 +02:00
$this -> request -> data [ 'Event' ][ 'timestamp' ] = time ();
2018-07-19 11:48:22 +02:00
if ( $this -> Event -> save ( $this -> request -> data , true , $fieldList )) {
$this -> Flash -> success ( __ ( 'The event has been saved' ));
$this -> redirect ( array ( 'action' => 'view' , $id ));
} else {
$this -> Flash -> error ( __ ( 'The event could not be saved. Please, try again.' ));
}
} else {
2020-11-02 13:02:22 +01:00
$this -> request -> data = $event ;
2018-07-19 11:48:22 +02:00
}
// combobox for distribution
$distributions = array_keys ( $this -> Event -> distributionDescriptions );
$distributions = $this -> _arrayToValuesIndexArray ( $distributions );
$this -> set ( 'distributions' , $distributions );
// even if the SG is not local, we still want the option to select the currently assigned SG
$sgs = $this -> Event -> SharingGroup -> fetchAllAuthorised ( $this -> Auth -> user (), 'name' , 1 );
$this -> set ( 'sharingGroups' , $sgs );
// tooltip for distribution
2019-11-12 14:54:41 +01:00
$fieldDesc = array ();
2018-07-19 11:48:22 +02:00
$distributionLevels = $this -> Event -> distributionLevels ;
if ( empty ( $sgs )) {
unset ( $distributionLevels [ 4 ]);
}
$this -> set ( 'distributionLevels' , $distributionLevels );
foreach ( $distributionLevels as $key => $value ) {
2019-11-12 14:54:41 +01:00
$fieldDesc [ 'distribution' ][ $key ] = $this -> Event -> distributionDescriptions [ $key ][ 'formdesc' ];
2018-07-19 11:48:22 +02:00
}
// combobox for risks
$threat_levels = $this -> Event -> ThreatLevel -> find ( 'all' );
$this -> set ( 'threatLevels' , Set :: combine ( $threat_levels , '{n}.ThreatLevel.id' , '{n}.ThreatLevel.name' ));
2019-11-12 14:57:57 +01:00
$fieldDesc [ 'threat_level_id' ] = Set :: combine ( $threat_levels , '{n}.ThreatLevel.id' , '{n}.ThreatLevel.description' );
2018-07-19 11:48:22 +02:00
// combobox for analysis
$this -> set ( 'sharingGroups' , $sgs );
// tooltip for analysis
2019-11-12 14:54:41 +01:00
$analysisLevels = $this -> Event -> analysisLevels ;
foreach ( $analysisLevels as $key => $value ) {
$fieldDesc [ 'analysis' ][ $key ] = $this -> Event -> analysisDescriptions [ $key ][ 'formdesc' ];
2018-07-19 11:48:22 +02:00
}
2019-11-12 14:54:41 +01:00
$this -> set ( 'analysisLevels' , $analysisLevels );
$this -> set ( 'fieldDesc' , $fieldDesc );
2018-07-19 11:48:22 +02:00
$this -> set ( 'eventDescriptions' , $this -> Event -> fieldDescriptions );
2020-11-02 13:02:22 +01:00
$this -> set ( 'event' , $event );
2019-11-13 09:38:46 +01:00
$this -> render ( 'add' );
2018-07-19 11:48:22 +02:00
}
public function delete ( $id = null )
{
2022-10-26 16:50:21 +02:00
if ( $this -> request -> is ([ 'post' , 'put' , 'delete' ])) {
2018-07-19 11:48:22 +02:00
if ( isset ( $this -> request -> data [ 'id' ])) {
$this -> request -> data [ 'Event' ] = $this -> request -> data ;
}
if ( ! isset ( $id ) && isset ( $this -> request -> data [ 'Event' ][ 'id' ])) {
$idList = $this -> request -> data [ 'Event' ][ 'id' ];
if ( ! is_array ( $idList )) {
2021-07-02 12:41:36 +02:00
if ( is_numeric ( $idList ) || Validation :: uuid ( $idList )) {
2018-07-19 11:48:22 +02:00
$idList = array ( $idList );
} else {
2022-10-10 22:07:25 +02:00
$idList = $this -> _jsonDecode ( $idList );
2018-07-19 11:48:22 +02:00
}
}
2021-07-02 12:41:36 +02:00
if ( empty ( $idList )) {
2018-07-19 11:48:22 +02:00
throw new NotFoundException ( __ ( 'Invalid input.' ));
}
} else {
$idList = array ( $id );
}
2021-07-02 12:41:36 +02:00
2018-07-19 11:48:22 +02:00
$fails = array ();
$successes = array ();
foreach ( $idList as $eid ) {
$event = $this -> Event -> find ( 'first' , array (
2021-07-02 12:41:36 +02:00
'conditions' => Validation :: uuid ( $eid ) ? [ 'Event.uuid' => $eid ] : [ 'Event.id' => $eid ],
2021-10-18 13:55:47 +02:00
'recursive' => - 1 ,
2018-07-19 11:48:22 +02:00
));
if ( empty ( $event )) {
2021-07-02 12:41:36 +02:00
$fails [] = $eid ; // event not found
continue ;
2018-07-19 11:48:22 +02:00
}
2021-07-02 12:41:36 +02:00
if ( ! $this -> __canModifyEvent ( $event )) {
$fails [] = $eid ; // user don't have permission to delete this event
continue ;
}
$this -> Event -> insertLock ( $this -> Auth -> user (), $event [ 'Event' ][ 'id' ]);
if ( $this -> Event -> quickDelete ( $event )) {
$successes [] = $eid ;
2018-07-19 11:48:22 +02:00
} else {
2021-07-02 12:41:36 +02:00
$fails [] = $eid ;
2018-07-19 11:48:22 +02:00
}
2021-07-02 12:41:36 +02:00
}
if ( count ( $idList ) === 1 ) {
$message = empty ( $successes ) ? __ ( 'Event was not deleted.' ) : __ ( 'Event deleted.' );
2018-07-19 11:48:22 +02:00
} else {
2021-07-02 12:41:36 +02:00
$message = '' ;
2018-07-19 11:48:22 +02:00
if ( ! empty ( $successes )) {
2021-07-02 12:41:36 +02:00
$message .= __n ( '%s event deleted.' , '%s events deleted.' , count ( $successes ), count ( $successes ));
2018-07-19 11:48:22 +02:00
}
if ( ! empty ( $fails )) {
$message .= count ( $fails ) . ' event(s) could not be deleted due to insufficient privileges or the event not being found.' ;
}
}
if ( $this -> _isRest ()) {
if ( ! empty ( $successes )) {
return $this -> RestResponse -> saveSuccessResponse ( 'Events' , 'delete' , $id , $this -> response -> type (), $message );
} else {
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'delete' , false , $message , $this -> response -> type ());
}
} else {
if ( ! empty ( $successes )) {
$this -> Flash -> success ( $message );
} else {
$this -> Flash -> error ( $message );
}
$this -> redirect ( array ( 'action' => 'index' ));
}
} else {
2022-10-26 16:50:21 +02:00
$eventList = is_numeric ( $id ) ? [ $id ] : $this -> _jsonDecode ( $id );
2018-07-19 11:48:22 +02:00
$this -> request -> data [ 'Event' ][ 'id' ] = json_encode ( $eventList );
$this -> set ( 'idArray' , $eventList );
$this -> render ( 'ajax/eventDeleteConfirmationForm' );
}
}
2019-01-17 08:27:16 +01:00
public function unpublish ( $id = null )
{
2019-08-14 15:01:31 +02:00
$id = $this -> Toolbox -> findIdByUuid ( $this -> Event , $id );
2019-01-17 08:27:16 +01:00
$this -> Event -> id = $id ;
$this -> Event -> recursive = - 1 ;
$event = $this -> Event -> read ( null , $id );
2020-07-20 10:10:47 +02:00
if ( ! $this -> __canModifyEvent ( $this -> Event -> data )) {
throw new ForbiddenException ( __ ( 'You do not have the permission to do that.' ));
2019-01-17 08:27:16 +01:00
}
$this -> Event -> insertLock ( $this -> Auth -> user (), $id );
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
$fieldList = array ( 'published' , 'id' , 'info' );
$event [ 'Event' ][ 'published' ] = 0 ;
$result = $this -> Event -> save ( $event , array ( 'fieldList' => $fieldList ));
if ( $result ) {
$message = __ ( 'Event unpublished.' );
2019-03-05 12:24:56 +01:00
$kafkaTopic = Configure :: read ( 'Plugin.Kafka_event_publish_notifications_topic' );
if ( Configure :: read ( 'Plugin.Kafka_enable' ) && Configure :: read ( 'Plugin.Kafka_event_publish_notifications_enable' ) && ! empty ( $kafkaTopic )) {
$kafkaPubTool = $this -> Event -> getKafkaPubTool ();
$params = array ( 'eventid' => $id );
if ( Configure :: read ( 'Plugin.Kafka_include_attachments' )) {
$params [ 'includeAttachments' ] = 1 ;
}
$pubEvent = $this -> Event -> fetchEvent ( $this -> Auth -> user (), $params );
if ( ! empty ( $pubEvent )) {
$kafkaPubTool -> publishJson ( $kafkaTopic , $pubEvent [ 0 ], 'unpublish' );
}
}
2019-01-17 08:27:16 +01:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'events' , 'unpublish' , $id , false , $message );
} else {
$this -> Flash -> success ( $message );
$this -> redirect ( array ( 'action' => 'view' , $id ));
}
} else {
throw new MethodNotAllowedException ( 'Could not unpublish event.' );
}
} else {
$this -> set ( 'id' , $id );
$this -> set ( 'type' , 'unpublish' );
$this -> render ( 'ajax/eventPublishConfirmationForm' );
}
}
2019-11-22 21:53:51 +01:00
public function publishSightings ( $id = null )
{
2020-12-09 17:29:08 +01:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
2019-11-22 21:53:51 +01:00
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
2021-03-11 11:48:36 +01:00
$result = $this -> Event -> publishSightingsRouter ( $event [ 'Event' ][ 'id' ], $this -> Auth -> user ());
2019-11-22 21:53:51 +01:00
if ( ! Configure :: read ( 'MISP.background_jobs' )) {
if ( ! is_array ( $result )) {
// redirect to the view event page
$message = 'Sightings published' ;
} else {
$lastResult = array_pop ( $result );
$resultString = ( count ( $result ) > 0 ) ? implode ( ', ' , $result ) . ' and ' . $lastResult : $lastResult ;
$errors [ 'failed_servers' ] = $result ;
$message = sprintf ( 'Sightings published but not pushed to %s, re-try later. If the issue persists, make sure that the correct sync user credentials are used for the server link and that the sync user on the remote server has authentication privileges.' , $resultString );
}
} else {
// update the DB to set the published flag
// for background jobs, this should be done already
$fieldList = array ( 'id' , 'info' , 'sighting_timestamp' );
$event [ 'Event' ][ 'sighting_timestamp' ] = time ();
$this -> Event -> save ( $event , array ( 'fieldList' => $fieldList ));
$message = 'Job queued' ;
}
if ( $this -> _isRest ()) {
$this -> set ( 'name' , 'Publish Sightings' );
$this -> set ( 'message' , $message );
if ( ! empty ( $errors )) {
$this -> set ( 'errors' , $errors );
}
2020-12-09 17:29:08 +01:00
$this -> set ( 'url' , $this -> baseurl . '/events/publishSightings/' . $event [ 'Event' ][ 'id' ]);
$this -> set ( 'id' , $event [ 'Event' ][ 'id' ]);
2019-11-22 21:53:51 +01:00
$this -> set ( '_serialize' , array ( 'name' , 'message' , 'url' , 'id' , 'errors' ));
} else {
$this -> Flash -> success ( $message );
2020-12-09 17:29:08 +01:00
$this -> redirect ( array ( 'action' => 'view' , $event [ 'Event' ][ 'id' ]));
2019-11-22 21:53:51 +01:00
}
} else {
$this -> set ( 'id' , $id );
2019-11-25 16:21:42 +01:00
$this -> set ( 'type' , 'publishSightings' );
2019-11-22 21:53:51 +01:00
$this -> render ( 'ajax/eventPublishConfirmationForm' );
}
}
2018-07-19 11:48:22 +02:00
// Publishes the event without sending an alert email
public function publish ( $id = null )
{
2021-07-07 15:25:33 +02:00
$event = $this -> __prepareForPublish ( $id );
2018-07-19 11:48:22 +02:00
// only allow form submit CSRF protection.
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
2021-07-07 15:25:33 +02:00
$errors = array ();
2018-07-19 11:48:22 +02:00
// Performs all the actions required to publish an event
2021-07-07 15:25:33 +02:00
$result = $this -> Event -> publishRouter ( $event [ 'Event' ][ 'id' ], null , $this -> Auth -> user ());
2018-07-19 11:48:22 +02:00
if ( ! Configure :: read ( 'MISP.background_jobs' )) {
if ( ! is_array ( $result )) {
2022-05-04 01:23:13 +02:00
if ( $result === true ) {
$message = __ ( 'Event published without alerts' );
} else {
$message = __ ( 'Event publishing failed due to a blocking module failing. The reason for the failure: %s' , $result );
$errors [ 'Module' ] = 'Module failure.' ;
}
2018-07-19 11:48:22 +02:00
} else {
$lastResult = array_pop ( $result );
$resultString = ( count ( $result ) > 0 ) ? implode ( ', ' , $result ) . ' and ' . $lastResult : $lastResult ;
$errors [ 'failed_servers' ] = $result ;
2021-07-07 15:25:33 +02:00
$message = __ ( 'Event published but not pushed to %s, re-try later. If the issue persists, make sure that the correct sync user credentials are used for the server link and that the sync user on the remote server has authentication privileges.' , $resultString );
2018-07-19 11:48:22 +02:00
}
} else {
$message = 'Job queued' ;
}
if ( $this -> _isRest ()) {
if ( ! empty ( $errors )) {
2021-07-07 15:25:33 +02:00
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'publish' , $event [ 'Event' ][ 'id' ], $errors );
} else {
return $this -> RestResponse -> saveSuccessResponse ( 'Events' , 'publish' , $event [ 'Event' ][ 'id' ], false , $message );
2018-07-19 11:48:22 +02:00
}
} else {
2022-05-04 01:23:13 +02:00
if ( ! empty ( $errors )) {
$this -> Flash -> error ( $message );
} else {
$this -> Flash -> success ( $message );
}
2021-07-07 15:25:33 +02:00
$this -> redirect ( array ( 'action' => 'view' , $event [ 'Event' ][ 'id' ]));
2018-07-19 11:48:22 +02:00
}
} else {
2022-06-13 17:41:32 +02:00
$servers = $this -> Event -> listServerToPush ( $event );
2021-07-07 15:25:33 +02:00
$this -> set ( 'id' , $event [ 'Event' ][ 'id' ]);
2022-06-13 17:41:32 +02:00
$this -> set ( 'servers' , $servers );
2018-07-19 11:48:22 +02:00
$this -> set ( 'type' , 'publish' );
$this -> render ( 'ajax/eventPublishConfirmationForm' );
}
}
// Send out an alert email to all the users that wanted to be notified.
// Users with a GnuPG key will get the mail encrypted, other users will get the mail unencrypted
public function alert ( $id = null )
{
2021-07-07 15:25:33 +02:00
$event = $this -> __prepareForPublish ( $id );
2018-07-19 11:48:22 +02:00
// only allow form submit CSRF protection
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
2021-07-07 15:25:33 +02:00
$errors = array ();
2018-07-19 11:48:22 +02:00
// send out the email
2021-07-07 15:25:33 +02:00
$emailResult = $this -> Event -> sendAlertEmailRouter ( $event [ 'Event' ][ 'id' ], $this -> Auth -> user (), $event [ 'Event' ][ 'publish_timestamp' ]);
2018-07-19 11:48:22 +02:00
if ( is_bool ( $emailResult ) && $emailResult == true ) {
// Performs all the actions required to publish an event
2021-07-07 15:25:33 +02:00
$result = $this -> Event -> publishRouter ( $event [ 'Event' ][ 'id' ], null , $this -> Auth -> user ());
2018-07-19 11:48:22 +02:00
if ( ! is_array ( $result )) {
// redirect to the view event page
if ( Configure :: read ( 'MISP.background_jobs' )) {
$message = 'Job queued.' ;
} else {
$message = 'Email sent to all participants.' ;
}
} else {
$lastResult = array_pop ( $result );
$resultString = ( count ( $result ) > 0 ) ? implode ( ', ' , $result ) . ' and ' . $lastResult : $lastResult ;
$errors [ 'failed_servers' ] = $result ;
2021-07-07 15:25:33 +02:00
$message = __ ( 'Not published given no connection to %s but email sent to all participants.' , $resultString );
2018-07-19 11:48:22 +02:00
}
2022-08-05 14:17:41 +02:00
2018-07-19 11:48:22 +02:00
} elseif ( ! is_bool ( $emailResult )) {
// Performs all the actions required to publish an event
2021-07-07 15:25:33 +02:00
$result = $this -> Event -> publishRouter ( $event [ 'Event' ][ 'id' ], null , $this -> Auth -> user ());
2018-07-19 11:48:22 +02:00
if ( ! is_array ( $result )) {
2022-05-04 01:23:13 +02:00
if ( $result === true ) {
$message = __ ( 'Published but no email sent given GnuPG is not configured.' );
$errors [ 'GnuPG' ] = 'GnuPG not set up.' ;
} else {
$message = $result ;
$errors [ 'Module' ] = 'Module failure.' ;
}
2018-07-19 11:48:22 +02:00
// redirect to the view event page
} else {
$lastResult = array_pop ( $result );
$resultString = ( count ( $result ) > 0 ) ? implode ( ', ' , $result ) . ' and ' . $lastResult : $lastResult ;
$errors [ 'failed_servers' ] = $result ;
$errors [ 'GnuPG' ] = 'GnuPG not set up.' ;
2021-07-07 15:25:33 +02:00
$message = __ ( 'Not published given no connection to %s but no email sent given GnuPG is not configured.' , $resultString );
2018-07-19 11:48:22 +02:00
}
} else {
$message = 'Sending of email failed' ;
$errors [ 'email' ] = 'The sending of emails failed.' ;
}
if ( $this -> _isRest ()) {
if ( ! empty ( $errors )) {
2021-07-07 15:25:33 +02:00
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'alert' , $event [ 'Event' ][ 'id' ], $errors );
} else {
return $this -> RestResponse -> saveSuccessResponse ( 'Events' , 'alert' , $event [ 'Event' ][ 'id' ], false , $message );
2018-07-19 11:48:22 +02:00
}
} else {
2021-07-07 15:25:33 +02:00
if ( isset ( $errors [ 'failed_servers' ])) {
2018-07-19 11:48:22 +02:00
$this -> Flash -> error ( $message );
} else {
$this -> Flash -> success ( $message );
}
2021-07-07 15:25:33 +02:00
$this -> redirect ( array ( 'action' => 'view' , $event [ 'Event' ][ 'id' ]));
2018-07-19 11:48:22 +02:00
}
} else {
2022-06-13 17:41:32 +02:00
$servers = $this -> Event -> listServerToPush ( $event );
2021-07-07 15:25:33 +02:00
$this -> set ( 'id' , $event [ 'Event' ][ 'id' ]);
2022-06-13 17:41:32 +02:00
$this -> set ( 'servers' , $servers );
2018-07-19 11:48:22 +02:00
$this -> set ( 'type' , 'alert' );
$this -> render ( 'ajax/eventPublishConfirmationForm' );
}
}
2021-07-07 15:25:33 +02:00
/**
* @ param int | string $id Event ID or UUID
* @ return array
*/
private function __prepareForPublish ( $id )
{
if ( empty ( $id )) {
throw new NotFoundException ( __ ( 'Invalid event.' ));
}
$event = $this -> Event -> find ( 'first' , [
'conditions' => Validation :: uuid ( $id ) ? [ 'Event.uuid' => $id ] : [ 'Event.id' => $id ],
'recursive' => - 1 ,
2023-12-18 09:58:24 +01:00
'fields' => [ 'id' , 'info' , 'publish_timestamp' , 'orgc_id' , 'user_id' ],
2021-07-07 15:25:33 +02:00
]);
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Invalid event.' ));
}
2022-10-27 09:27:35 +02:00
if ( ! $this -> __canPublishEvent ( $event )) {
2021-07-07 15:25:33 +02:00
throw new MethodNotAllowedException ( __ ( 'You do not have the permission to do that.' ));
}
if ( ! $this -> _isRest ()) {
$this -> Event -> insertLock ( $this -> Auth -> user (), $event [ 'Event' ][ 'id' ]);
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
$publishable = $this -> Event -> checkIfPublishable ( $event [ 'Event' ][ 'id' ]);
if ( $publishable !== true ) {
$this -> Flash -> error ( __ ( 'Could not publish event - no tag for required taxonomies missing: %s' , implode ( ', ' , $publishable )));
$this -> redirect ([ 'action' => 'view' , $event [ 'Event' ][ 'id' ]]);
}
}
}
2023-12-18 09:58:24 +01:00
if (
Configure :: read ( 'MISP.block_publishing_for_same_creator' , false ) &&
$this -> Auth -> user ()[ 'id' ] == $event [ 'Event' ][ 'user_id' ]
) {
2023-12-18 10:10:45 +01:00
$message = __ ( 'Could not publish the event, the publishing user cannot be the same as the event creator as per this instance\'s configuration.' );
2023-12-18 09:58:24 +01:00
if ( ! $this -> _isRest ()) {
$this -> Flash -> error ( $message );
}
throw new MethodNotAllowedException ( $message );
}
2021-07-07 15:25:33 +02:00
return $event ;
}
2018-07-19 11:48:22 +02:00
// Send out an contact email to the person who posted the event.
// Users with a GnuPG key will get the mail encrypted, other users will get the mail unencrypted
public function contact ( $id = null )
{
2020-12-05 14:26:38 +01:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id , [ 'contain' => [ 'Orgc' ]]);
if ( empty ( $event )) {
2018-07-19 11:48:22 +02:00
throw new NotFoundException ( __ ( 'Invalid event' ));
}
// User has filled in his contact form, send out the email.
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' )) {
2019-08-21 17:48:51 +02:00
if ( ! isset ( $this -> request -> data [ 'Event' ])) {
$this -> request -> data = array ( 'Event' => $this -> request -> data );
}
2018-07-19 11:48:22 +02:00
$message = $this -> request -> data [ 'Event' ][ 'message' ];
2019-08-21 17:48:51 +02:00
if ( empty ( $message )) {
2020-02-27 02:43:04 +01:00
$error = __ ( 'You must specify a message.' );
2019-08-21 17:48:51 +02:00
if ( $this -> _isRest ()) {
throw new MethodNotAllowedException ( $error );
} else {
$this -> Flash -> error ( $error );
2020-12-05 14:26:38 +01:00
$this -> redirect ( array ( 'action' => 'contact' , $event [ 'Event' ][ 'id' ]));
2019-08-21 17:48:51 +02:00
}
}
2019-08-28 14:07:55 +02:00
$creator_only = false ;
if ( isset ( $this -> request -> data [ 'Event' ][ 'person' ])) {
$creator_only = $this -> request -> data [ 'Event' ][ 'person' ];
}
2018-07-19 11:48:22 +02:00
$user = $this -> Auth -> user ();
2020-08-21 15:43:27 +02:00
$user = $this -> Event -> User -> fillKeysToUser ( $user );
2019-08-21 17:48:51 +02:00
2020-12-05 14:26:38 +01:00
$success = $this -> Event -> sendContactEmailRouter ( $event [ 'Event' ][ 'id' ], $message , $creator_only , $user );
2019-08-21 17:48:51 +02:00
if ( $success ) {
$return_message = __ ( 'Email sent to the reporter.' );
if ( $this -> _isRest ()) {
2020-12-05 14:26:38 +01:00
return $this -> RestResponse -> saveSuccessResponse ( 'Events' , 'contact' , $event [ 'Event' ][ 'id' ], $this -> response -> type (), $return_message );
2019-08-21 17:48:51 +02:00
} else {
$this -> Flash -> success ( $return_message );
// redirect to the view event page
2020-12-05 14:26:38 +01:00
$this -> redirect ( array ( 'action' => 'view' , $event [ 'Event' ][ 'id' ]));
2019-08-21 17:48:51 +02:00
}
2018-07-19 11:48:22 +02:00
} else {
2019-08-21 17:48:51 +02:00
$return_message = __ ( 'Sending of email failed.' );
if ( $this -> _isRest ()) {
2020-12-05 14:26:38 +01:00
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'contact' , $event [ 'Event' ][ 'id' ], $return_message , $this -> response -> type ());
2019-08-21 17:48:51 +02:00
} else {
$this -> Flash -> error ( $return_message , 'default' , array (), 'error' );
// redirect to the view event page
2020-12-05 14:26:38 +01:00
$this -> redirect ( array ( 'action' => 'view' , $event [ 'Event' ][ 'id' ]));
2019-08-21 17:48:51 +02:00
}
2018-07-19 11:48:22 +02:00
}
}
2020-12-05 14:26:38 +01:00
$this -> set ( 'event' , $event );
$this -> set ( 'mayModify' , $this -> __canModifyEvent ( $event ));
2018-07-19 11:48:22 +02:00
}
2018-09-05 17:56:27 +02:00
public function automation ( $legacy = false )
2018-07-19 11:48:22 +02:00
{
// Simply display a static view
App :: uses ( 'BroExport' , 'Export' );
$export = new BroExport ();
$temp = $export -> mispTypes ;
$broTypes = array ( 'all' => 'All types listed below.' );
foreach ( $temp as $broType => $mispTypes ) {
foreach ( $mispTypes as $mT ) {
$broTypes [ $broType ][] = $mT [ 0 ];
}
$broTypes [ $broType ] = implode ( ', ' , $broTypes [ $broType ]);
}
$this -> loadModel ( 'Server' );
$this -> set ( 'command_line_functions' , $this -> Server -> command_line_functions );
$this -> set ( 'broTypes' , $broTypes );
// generate the list of Attribute types
$this -> loadModel ( 'Attribute' );
$this -> set ( 'sigTypes' , array_keys ( $this -> Attribute -> typeDefinitions ));
$this -> loadModel ( 'Server' );
2022-02-02 15:00:08 +01:00
if ( empty ( Configure :: read ( 'Security.advanced_authkeys' ))) {
$authkey = $this -> Event -> User -> find ( 'first' , [
'fields' => [ 'authkey' ],
'conditions' => [ 'User.id' => $this -> Auth -> user ()[ 'id' ]],
'recursive' => - 1
])[ 'User' ][ 'authkey' ];
$this -> set ( 'authkey' , $authkey );
}
2018-07-19 11:48:22 +02:00
$rpzSettings = $this -> Server -> retrieveCurrentSettings ( 'Plugin' , 'RPZ_' );
$this -> set ( 'rpzSettings' , $rpzSettings );
2022-05-19 14:26:04 +02:00
$this -> set ( 'hashTypes' , array_keys ( Attribute :: FILE_HASH_TYPES ));
2018-11-23 14:11:33 +01:00
if ( $legacy ) {
$this -> render ( 'legacy_automation' );
}
2018-07-19 11:48:22 +02:00
}
public function export ()
{
$filesize_units = array ( 'B' , 'KB' , 'MB' , 'GB' , 'TB' );
if ( $this -> _isSiteAdmin ()) {
2019-04-29 15:14:14 +02:00
$this -> Flash -> info ( __ ( 'Warning, you are logged in as a site admin, any export that you generate will contain the FULL UNRESTRICTED data-set. If you would like to generate an export for your own organisation, please log in with a different user.' ));
2018-07-19 11:48:22 +02:00
}
// Check if the background jobs are enabled - if not, fall back to old export page.
2024-01-31 14:26:22 +01:00
if ( Configure :: read ( 'MISP.background_jobs' ) && ! Configure :: read ( 'MISP.disable_cached_exports' , true )) {
2018-07-19 11:48:22 +02:00
$now = time ();
// as a site admin we'll use the ADMIN identifier, not to overwrite the cached files of our own org with a file that includes too much data.
$org_name = $this -> _isSiteAdmin () ? 'ADMIN' : $this -> Auth -> user ( 'Organisation' )[ 'name' ];
2020-06-22 11:10:25 +02:00
$conditions = $this -> Event -> createEventConditions ( $this -> Auth -> user ());
2018-07-19 11:48:22 +02:00
$this -> Event -> recursive = - 1 ;
$newestEvent = $this -> Event -> find ( 'first' , array (
'conditions' => $conditions ,
'fields' => 'timestamp' ,
'order' => 'Event.timestamp DESC' ,
));
$newestEventPublished = $this -> Event -> find ( 'first' , array (
'conditions' => array ( 'AND' => array ( $conditions , array ( 'published' => 1 ))),
'fields' => 'timestamp' ,
'order' => 'Event.timestamp DESC' ,
));
$this -> loadModel ( 'Job' );
2022-04-10 09:48:48 +02:00
$exportTypes = $this -> Event -> exportTypes ();
foreach ( $exportTypes as $k => $type ) {
2018-07-19 11:48:22 +02:00
if ( $type [ 'requiresPublished' ]) {
$tempNewestEvent = $newestEventPublished ;
} else {
$tempNewestEvent = $newestEvent ;
}
$job = $this -> Job -> find ( 'first' , array (
'fields' => array ( 'id' , 'progress' ),
'conditions' => array (
'job_type' => 'cache_' . $k ,
'org_id' => $this -> _isSiteAdmin () ? 0 : $this -> Auth -> user ( 'org_id' )
),
'order' => array ( 'Job.id' => 'desc' )
));
2018-09-03 18:06:23 +02:00
$dir = new Folder ( APP . 'tmp/cached_exports/' . $k , true );
2018-07-19 11:48:22 +02:00
if ( $k === 'text' ) {
// Since all of the text export files are generated together, we might as well just check for a single one md5.
$file = new File ( $dir -> pwd () . DS . 'misp.text_md5.' . $org_name . $type [ 'extension' ]);
} else {
$file = new File ( $dir -> pwd () . DS . 'misp.' . $k . '.' . $org_name . $type [ 'extension' ]);
}
if ( ! $file -> readable ()) {
if ( empty ( $tempNewestEvent )) {
$lastModified = 'No valid events' ;
2022-04-10 09:48:48 +02:00
$exportTypes [ $k ][ 'recommendation' ] = 0 ;
2018-07-19 11:48:22 +02:00
} else {
$lastModified = 'N/A' ;
2022-04-10 09:48:48 +02:00
$exportTypes [ $k ][ 'recommendation' ] = 1 ;
2018-07-19 11:48:22 +02:00
}
} else {
$filesize = $file -> size ();
$filesize_unit_index = 0 ;
while ( $filesize > 1024 ) {
$filesize_unit_index ++ ;
$filesize = $filesize / 1024 ;
}
2022-04-10 09:48:48 +02:00
$exportTypes [ $k ][ 'filesize' ] = round ( $filesize , 1 ) . $filesize_units [ $filesize_unit_index ];
2018-07-19 11:48:22 +02:00
$fileChange = $file -> lastChange ();
$lastModified = $this -> __timeDifference ( $now , $fileChange );
if ( empty ( $tempNewestEvent ) || $fileChange > $tempNewestEvent [ 'Event' ][ 'timestamp' ]) {
if ( empty ( $tempNewestEvent )) {
$lastModified = 'No valid events' ;
}
2022-04-10 09:48:48 +02:00
$exportTypes [ $k ][ 'recommendation' ] = 0 ;
2018-07-19 11:48:22 +02:00
} else {
2022-04-10 09:48:48 +02:00
$exportTypes [ $k ][ 'recommendation' ] = 1 ;
2018-07-19 11:48:22 +02:00
}
}
2022-04-10 09:48:48 +02:00
$exportTypes [ $k ][ 'lastModified' ] = $lastModified ;
2018-07-19 11:48:22 +02:00
if ( ! empty ( $job )) {
2022-04-10 09:48:48 +02:00
$exportTypes [ $k ][ 'job_id' ] = $job [ 'Job' ][ 'id' ];
$exportTypes [ $k ][ 'progress' ] = $job [ 'Job' ][ 'progress' ];
2018-07-19 11:48:22 +02:00
} else {
2022-04-10 09:48:48 +02:00
$exportTypes [ $k ][ 'job_id' ] = - 1 ;
$exportTypes [ $k ][ 'progress' ] = 0 ;
2018-07-19 11:48:22 +02:00
}
}
2022-05-19 14:26:04 +02:00
} else {
$exportTypes = [];
2018-07-19 11:48:22 +02:00
}
2022-05-19 14:26:04 +02:00
2022-04-10 09:48:48 +02:00
$this -> set ( 'sigTypes' , array_keys ( $this -> Event -> Attribute -> typeDefinitions ));
$this -> set ( 'export_types' , $exportTypes );
2018-07-19 11:48:22 +02:00
}
public function downloadExport ( $type , $extra = null )
{
2024-01-31 14:26:22 +01:00
if ( Configure :: read ( 'MISP.disable_cached_exports' , true )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ( __ ( 'This feature is currently disabled' ));
}
if ( $this -> _isSiteAdmin ()) {
$org = 'ADMIN' ;
} else {
$org = $this -> Auth -> user ( 'Organisation' )[ 'name' ];
}
$this -> autoRender = false ;
if ( $extra != null ) {
$extra = '_' . $extra ;
}
2022-04-10 09:48:48 +02:00
$exportType = $this -> Event -> exportTypes ()[ $type ];
$this -> response -> type ( $exportType [ 'extension' ]);
$path = 'tmp/cached_exports/' . $type . DS . 'misp.' . strtolower ( $exportType [ 'type' ]) . $extra . '.' . $org . $exportType [ 'extension' ];
2018-07-19 11:48:22 +02:00
$this -> response -> file ( $path , array ( 'download' => true ));
}
private function __timeDifference ( $now , $then )
{
$periods = array ( " second " , " minute " , " hour " , " day " , " week " , " month " , " year " );
$lengths = array ( " 60 " , " 60 " , " 24 " , " 7 " , " 4.35 " , " 12 " );
$difference = $now - $then ;
for ( $j = 0 ; $difference >= $lengths [ $j ] && $j < count ( $lengths ) - 1 ; $j ++ ) {
$difference /= $lengths [ $j ];
}
$difference = round ( $difference );
if ( $difference != 1 ) {
$periods [ $j ] .= " s " ;
}
return $difference . " " . $periods [ $j ] . " ago " ;
}
2022-05-21 14:20:42 +02:00
public function restSearchExport ( $id = null , $returnFormat = null )
2022-03-10 10:18:39 +01:00
{
2022-06-16 09:19:53 +02:00
if ( $returnFormat === null ) {
$exportFormats = [
'attack' => __ ( 'Attack matrix' ),
'attack-sightings' => __ ( 'Attack matrix by sightings' ),
'context' => __ ( 'Aggregated context data' ),
'context-markdown' => __ ( 'Aggregated context data as Markdown' ),
'csv' => __ ( 'CSV' ),
'hashes' => __ ( 'Hashes' ),
'hosts' => __ ( 'Hosts file' ),
'json' => __ ( 'MISP JSON' ),
'netfilter' => __ ( 'Netfilter' ),
'opendata' => __ ( 'Open data' ),
'openioc' => __ ( 'OpenIOC' ),
'rpz' => __ ( 'RPZ' ),
'snort' => __ ( 'Snort rules' ),
'stix' => __ ( 'STIX 1 XML' ),
'stix-json' => __ ( 'STIX 1 JSON' ),
'stix2' => __ ( 'STIX 2' ),
'suricata' => __ ( 'Suricata rules' ),
'text' => __ ( 'Text file' ),
'xml' => __ ( 'MISP XML' ),
'yara' => __ ( 'YARA rules' ),
'yara-json' => __ ( 'YARA rules (JSON)' ),
];
$idList = is_numeric ( $id ) ? [ $id ] : $this -> _jsonDecode ( $id );
2022-03-10 12:10:37 +01:00
if ( empty ( $idList )) {
throw new NotFoundException ( __ ( 'Invalid input.' ));
}
$this -> set ( 'idList' , $idList );
2022-06-16 09:19:53 +02:00
$this -> set ( 'exportFormats' , $exportFormats );
2022-03-10 12:10:37 +01:00
$this -> render ( 'ajax/eventRestSearchExportConfirmationForm' );
} else {
2022-06-16 16:35:40 +02:00
$returnFormat = ! isset ( $this -> Event -> validFormats [ $returnFormat ]) ? 'json' : $returnFormat ;
2022-03-10 12:10:37 +01:00
$idList = $id ;
2022-03-10 10:18:39 +01:00
if ( ! is_array ( $idList )) {
if ( is_numeric ( $idList ) || Validation :: uuid ( $idList )) {
$idList = array ( $idList );
} else {
2022-05-21 14:20:42 +02:00
$idList = $this -> _jsonDecode ( $idList );
2022-03-10 10:18:39 +01:00
}
}
if ( empty ( $idList )) {
throw new NotFoundException ( __ ( 'Invalid input.' ));
}
$filters = [
2022-06-16 16:35:40 +02:00
'eventid' => $idList ,
'published' => [ true , false ], // fetch published and unpublished events
2022-03-10 10:18:39 +01:00
];
$elementCounter = 0 ;
$renderView = false ;
2022-06-16 16:35:40 +02:00
$responseType = $this -> Event -> validFormats [ $returnFormat ][ 0 ];
2022-03-10 10:18:39 +01:00
$final = $this -> Event -> restSearch ( $this -> Auth -> user (), $returnFormat , $filters , false , false , $elementCounter , $renderView );
2022-06-16 09:19:53 +02:00
if ( $renderView ) {
2022-10-19 10:11:06 +02:00
$final = JsonTool :: decode ( $final -> intoString ());
2022-06-16 09:19:53 +02:00
$this -> set ( $final );
2022-03-18 09:14:10 +01:00
$this -> set ( 'responseType' , $responseType );
$this -> set ( 'returnFormat' , $returnFormat );
2022-03-10 10:18:39 +01:00
$this -> set ( 'renderView' , $renderView );
$this -> render ( '/Events/eventRestSearchExportResult' );
} else {
$filename = $this -> RestSearch -> getFilename ( $filters , 'Event' , $responseType );
2022-03-10 12:10:37 +01:00
return $this -> RestResponse -> viewData ( $final , $responseType , false , true , $filename , [
'X-Result-Count' => $elementCounter ,
'X-Export-Module-Used' => $returnFormat ,
'X-Response-Format' => $responseType
]);
2022-03-10 10:18:39 +01:00
}
}
}
2018-07-19 11:48:22 +02:00
public function xml ( $key , $eventid = false , $withAttachment = false , $tags = false , $from = false , $to = false , $last = false )
{
2019-11-29 10:11:30 +01:00
$this -> _legacyAPIRemap ( array (
'paramArray' => array (
'key' , 'eventid' , 'withAttachment' , 'tags' , 'from' , 'to' , 'last'
),
'request' => $this -> request ,
'named_params' => $this -> params [ 'named' ],
'ordered_url_params' => func_get_args (),
'injectedParams' => array (
'returnFormat' => 'xml'
)
));
return $this -> restSearch ();
2018-07-19 11:48:22 +02:00
}
2019-11-29 10:11:30 +01:00
public function nids ()
2018-07-19 11:48:22 +02:00
{
2019-11-29 10:11:30 +01:00
$this -> _legacyAPIRemap ( array (
'paramArray' => array (
'format' , 'key' , 'id' , 'continue' , 'tags' , 'from' , 'to' , 'last' ,
'type' , 'enforceWarninglist' , 'includeAllTags' , 'eventid'
),
'request' => $this -> request ,
'named_params' => $this -> params [ 'named' ],
'ordered_url_params' => func_get_args ()
));
if ( empty ( $this -> _legacyParams [ 'returnFormat' ])) {
$this -> _legacyParams [ 'returnFormat' ] = 'suricata' ;
2018-07-19 11:48:22 +02:00
}
2019-11-29 10:11:30 +01:00
return $this -> restSearch ();
2018-07-19 11:48:22 +02:00
}
2019-11-29 10:11:30 +01:00
public function hids ( $type )
2018-07-19 11:48:22 +02:00
{
2019-11-29 10:11:30 +01:00
$typeMappings = array (
'md5' => array ( 'malware-sample' , 'md5' , 'filename|md5' ),
'sha1' => array ( 'sha1' , 'filename|sha1' ),
'sha256' => array ( 'sha256' , 'filename|sha256' )
);
$ordered_url_params = func_get_args ();
unset ( $ordered_url_params [ 0 ]);
$ordered_url_params = array_values ( $ordered_url_params );
$this -> scopeOverride = 'Attribute' ;
$this -> _legacyAPIRemap ( array (
'paramArray' => array (
'key' , 'id' , 'withAttachment' , 'tags' , 'from' , 'to' , 'last'
),
'request' => $this -> request ,
'named_params' => $this -> params [ 'named' ],
'ordered_url_params' => $ordered_url_params ,
'injectedParams' => array (
'returnFormat' => 'hashes' ,
'type' => ( isset ( $typeMappings [ $type ])) ? $typeMappings [ $type ] : $type
)
));
return $this -> restSearch ();
2018-07-19 11:48:22 +02:00
}
2019-11-26 19:03:02 +01:00
// DEPRECATED - use restSearch with "returnFormat":"csv"
public function csv ( $key )
2018-07-19 11:48:22 +02:00
{
2019-11-26 19:03:02 +01:00
$this -> _legacyAPIRemap ( array (
'paramArray' => array (
'key' , 'eventid' , 'ignore' , 'tags' , 'category' , 'type' , 'includeContext' ,
'from' , 'to' , 'last' , 'headerless' , 'enforceWarninglist' , 'value' , 'timestamp'
),
'key' => $key ,
2018-08-06 10:49:45 +02:00
'request' => $this -> request ,
'named_params' => $this -> params [ 'named' ],
2019-11-26 19:03:02 +01:00
'ordered_url_params' => func_get_args (),
'injectedParams' => array (
2020-04-06 10:14:45 +02:00
'returnFormat' => 'csv' ,
2020-04-06 11:49:39 +02:00
'to_ids' => '1' ,
'published' => '1'
2019-11-26 19:03:02 +01:00
)
));
return $this -> restSearch ();
2018-07-19 11:48:22 +02:00
}
public function _addIOCFile ( $id )
{
if ( ! empty ( $this -> data ) && $this -> data [ 'Event' ][ 'submittedioc' ][ 'size' ] > 0 &&
is_uploaded_file ( $this -> data [ 'Event' ][ 'submittedioc' ][ 'tmp_name' ])) {
if ( ! $this -> Event -> checkFilename ( $this -> data [ 'Event' ][ 'submittedioc' ][ 'name' ])) {
throw new Exception ( __ ( 'Filename not allowed.' ));
}
// Load event and populate the event data
$this -> Event -> id = $id ;
$this -> Event -> recursive = - 1 ;
if ( ! $this -> Event -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$this -> Event -> read ( null , $id );
$saveEvent [ 'Event' ] = $this -> Event -> data [ 'Event' ];
$saveEvent [ 'Event' ][ 'published' ] = false ;
$dist = '5' ;
if ( Configure :: read ( 'MISP.default_attribute_distribution' ) != null ) {
if ( Configure :: read ( 'MISP.default_attribute_distribution' ) === 'event' ) {
$dist = '5' ;
} else {
$dist = '' ;
$dist .= Configure :: read ( 'MISP.default_attribute_distribution' );
}
}
// read XML
2022-03-06 23:51:25 +01:00
App :: uses ( 'FileAccessTool' , 'Tools' );
$xmlFileData = FileAccessTool :: readFromFile ( $this -> data [ 'Event' ][ 'submittedioc' ][ 'tmp_name' ], $this -> data [ 'Event' ][ 'submittedioc' ][ 'size' ]);
2018-07-19 11:48:22 +02:00
$event = $this -> IOCImport -> readXML ( $xmlFileData , $id , $dist , $this -> data [ 'Event' ][ 'submittedioc' ][ 'name' ]);
// make some changes to have $saveEvent in the format that is needed to save the event together with its attributes
$fails = $event [ 'Fails' ];
$saveEvent [ 'Attribute' ] = $event [ 'Attribute' ];
// we've already stored these elsewhere, unset them so we can extract the event related data
unset ( $event [ 'Attribute' ]);
unset ( $event [ 'Fails' ]);
// add the original openIOC file as an attachment
$saveEvent [ 'Attribute' ][] = array (
'category' => 'External analysis' ,
'uuid' => CakeText :: uuid (),
'type' => 'attachment' ,
2023-04-12 14:54:15 +02:00
'sharing_group_id' => '0' ,
2018-07-19 11:48:22 +02:00
'value' => $this -> data [ 'Event' ][ 'submittedioc' ][ 'name' ],
'to_ids' => false ,
'distribution' => $dist ,
'data' => base64_encode ( $xmlFileData ),
'comment' => 'OpenIOC import source file'
);
// LATER we might want to let an ioc create the event data automatically in a later version
// save the event related data into $saveEvent['Event']
//$saveEvent['Event'] = $event;
//$saveEvent['Event']['id'] = $id;
$fieldList = array (
'Event' => array ( 'published' , 'timestamp' ),
2023-04-12 14:54:15 +02:00
'Attribute' => array ( 'event_id' , 'category' , 'type' , 'value' , 'value1' , 'value2' , 'to_ids' , 'uuid' , 'distribution' , 'timestamp' , 'comment' , 'sharing_group_id' )
2018-07-19 11:48:22 +02:00
);
// Save it all
$saveResult = $this -> Event -> saveAssociated ( $saveEvent , array ( 'validate' => true , 'fieldList' => $fieldList ));
// set stuff for the view and render the showIOCResults view.
$this -> set ( 'attributes' , $saveEvent [ 'Attribute' ]);
if ( isset ( $fails )) {
$this -> set ( 'fails' , $fails );
}
$this -> set ( 'eventId' , $id );
$this -> set ( 'graph' , $event [ 'Graph' ]);
$this -> set ( 'saveEvent' , $saveEvent );
$this -> render ( 'showIOCResults' );
}
}
public function downloadOpenIOCEvent ( $key , $eventid , $enforceWarninglist = false )
{
// return a downloadable text file called misp.openIOC.<eventId>.ioc for individual events
// TODO implement mass download of all events - maybe in a zip file?
2019-02-10 13:08:12 +01:00
$this -> response -> type ( 'text' ); // set the content type
2018-07-19 11:48:22 +02:00
if ( $eventid == null ) {
throw new Exception ( __ ( 'Not yet implemented' ));
}
$this -> layout = 'text/default' ;
if ( $key != 'download' ) {
2021-09-26 12:23:23 +02:00
$user = $this -> _checkAuthUser ( $key );
2018-07-19 11:48:22 +02:00
if ( ! $user ) {
throw new UnauthorizedException ( __ ( 'This authentication key is not authorized to be used for exports. Contact your administrator.' ));
}
} else {
if ( ! $this -> Auth -> user ( 'id' )) {
throw new UnauthorizedException ( __ ( 'You have to be logged in to do that.' ));
}
}
// get the event if it exists and load it together with its attributes
$this -> Event -> id = $eventid ;
if ( ! $this -> Event -> exists ()) {
throw new NotFoundException ( __ ( 'Invalid event or not authorised.' ));
}
$event = $this -> Event -> fetchEvent ( $this -> Auth -> user (), $options = array ( 'eventid' => $eventid , 'to_ids' => 1 , 'enforceWarninglist' => $enforceWarninglist ));
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Invalid event or not authorised.' ));
}
2020-09-01 15:59:38 +02:00
$this -> loadModel ( 'Allowedlist' );
$temp = $this -> Allowedlist -> removeAllowedlistedFromArray ( array ( $event [ 0 ]), false );
2018-07-19 11:48:22 +02:00
$event = $temp [ 0 ];
// send the event and the vars needed to check authorisation to the Component
App :: uses ( 'IOCExportTool' , 'Tools' );
$this -> IOCExport = new IOCExportTool ();
$final = $this -> IOCExport -> buildAll ( $this -> Auth -> user (), $event );
$this -> response -> type ( 'xml' );
$this -> autoRender = false ;
$this -> response -> body ( $final );
$this -> response -> download ( 'misp.openIOC' . $eventid . '.ioc' );
return $this -> response ;
}
public function proposalEventIndex ()
{
$this -> loadModel ( 'ShadowAttribute' );
$conditions = array ( 'ShadowAttribute.deleted' => 0 );
if ( ! $this -> _isSiteAdmin ()) {
$conditions [] = array ( 'ShadowAttribute.event_org_id' => $this -> Auth -> user ( 'org_id' ));
}
2021-04-23 12:05:50 +02:00
$result = $this -> ShadowAttribute -> find ( 'column' , [
'fields' => [ 'event_id' ],
'conditions' => $conditions ,
'unique' => true ,
]);
2018-07-19 11:48:22 +02:00
$this -> Event -> recursive = - 1 ;
2021-04-23 12:05:50 +02:00
2018-07-19 11:48:22 +02:00
if ( empty ( $result )) {
2021-04-23 12:05:50 +02:00
$conditions = array ( 'Event.id' => - 1 );
} else {
$conditions = array ( 'Event.id' => $result );
2018-07-19 11:48:22 +02:00
}
$this -> paginate = array (
2021-04-23 12:05:50 +02:00
'fields' => array ( 'Event.id' , 'Event.org_id' , 'Event.orgc_id' , 'Event.publish_timestamp' , 'Event.distribution' , 'Event.info' , 'Event.date' , 'Event.published' ),
'conditions' => $conditions ,
'contain' => array (
'User' => array (
'fields' => array (
'User.email'
)),
'ShadowAttribute' => array (
'fields' => array (
'ShadowAttribute.id' , 'ShadowAttribute.org_id' , 'ShadowAttribute.event_id'
2018-07-19 11:48:22 +02:00
),
2021-04-23 12:05:50 +02:00
'conditions' => array (
'ShadowAttribute.deleted' => 0
),
),
)
);
2018-07-19 11:48:22 +02:00
$events = $this -> paginate ();
$orgIds = array ();
foreach ( $events as $k => $event ) {
$orgs = array ();
foreach ( $event [ 'ShadowAttribute' ] as $sa ) {
if ( ! in_array ( $sa [ 'org_id' ], $orgs )) {
$orgs [] = $sa [ 'org_id' ];
}
if ( ! in_array ( $sa [ 'org_id' ], $orgIds )) {
$orgIds [] = $sa [ 'org_id' ];
}
}
$events [ $k ][ 'orgArray' ] = $orgs ;
$events [ $k ][ 'Event' ][ 'proposal_count' ] = count ( $event [ 'ShadowAttribute' ]);
}
$orgs = $this -> Event -> Orgc -> find ( 'list' , array (
'conditions' => array ( 'Orgc.id' => $orgIds ),
'fields' => array ( 'Orgc.id' , 'Orgc.name' )
));
$this -> set ( 'orgs' , $orgs );
$this -> set ( 'events' , $events );
$this -> set ( 'eventDescriptions' , $this -> Event -> fieldDescriptions );
$this -> set ( 'analysisLevels' , $this -> Event -> analysisLevels );
$this -> set ( 'distributionLevels' , $this -> Event -> distributionLevels );
}
public function reportValidationIssuesEvents ()
{
// search for validation problems in the events
if ( ! self :: _isSiteAdmin ()) {
throw new NotFoundException ();
}
$results = $this -> Event -> reportValidationIssuesEvents ();
$result = $results [ 0 ];
$count = $results [ 1 ];
$this -> set ( 'result' , $result );
$this -> set ( 'count' , $count );
}
public function addTag ( $id = false , $tag_id = false )
{
$rearrangeRules = array (
2022-10-12 20:32:39 +02:00
'request' => false ,
'Event' => false ,
'tag_id' => 'tag' ,
'event_id' => 'event' ,
'id' => 'event'
2018-07-19 11:48:22 +02:00
);
$RearrangeTool = new RequestRearrangeTool ();
$this -> request -> data = $RearrangeTool -> rearrangeArray ( $this -> request -> data , $rearrangeRules );
if ( $id === false ) {
$id = $this -> request -> data [ 'event' ];
}
2023-12-19 12:25:17 +01:00
$conditions = [ 'Event.id' => $id ];
if ( Validation :: uuid ( $id )) {
$conditions = [ 'Event.uuid' => $id ];
}
$event = $this -> Event -> find (
'first' ,
[
'recursive' => - 1 ,
'conditions' => $conditions
]
);
2019-03-20 11:21:40 +01:00
if ( empty ( $event )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'Invalid event.' )), 'status' => 200 , 'type' => 'json' ));
2018-07-19 11:48:22 +02:00
}
2023-12-19 12:25:17 +01:00
$id = $event [ 'Event' ][ 'id' ];
2019-07-08 11:39:41 +02:00
$local = ! empty ( $this -> params [ 'named' ][ 'local' ]);
2019-03-20 11:21:40 +01:00
if ( ! $this -> request -> is ( 'post' )) {
2019-07-08 11:39:41 +02:00
$this -> set ( 'local' , $local );
2019-03-20 11:21:40 +01:00
$this -> set ( 'object_id' , $id );
$this -> set ( 'scope' , 'Event' );
$this -> layout = false ;
$this -> autoRender = false ;
$this -> render ( '/Events/add_tag' );
} else {
if ( $tag_id === false ) {
$tag_id = $this -> request -> data [ 'tag' ];
}
2020-07-22 08:45:51 +02:00
if ( ! $this -> __canModifyTag ( $event , $local )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'You don\'t have permission to do that.' )), 'status' => 200 , 'type' => 'json' ));
2019-03-20 11:21:40 +01:00
}
if ( ! is_numeric ( $tag_id )) {
if ( preg_match ( '/^collection_[0-9]+$/i' , $tag_id )) {
$tagChoice = explode ( '_' , $tag_id )[ 1 ];
$this -> loadModel ( 'TagCollection' );
$tagCollection = $this -> TagCollection -> fetchTagCollection ( $this -> Auth -> user (), array ( 'conditions' => array ( 'TagCollection.id' => $tagChoice )));
if ( empty ( $tagCollection )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'Invalid Tag Collection.' )), 'status' => 200 , 'type' => 'json' ));
}
2019-01-09 16:09:05 +01:00
$tag_id_list = array ();
2019-03-20 11:21:40 +01:00
foreach ( $tagCollection [ 0 ][ 'TagCollectionTag' ] as $tagCollectionTag ) {
$tag_id_list [] = $tagCollectionTag [ 'tag_id' ];
2019-01-09 16:09:05 +01:00
}
} else {
2019-03-20 11:21:40 +01:00
$tag_ids = json_decode ( $tag_id );
if ( $tag_ids !== null ) { // can decode json
$tag_id_list = array ();
foreach ( $tag_ids as $tag_id ) {
if ( preg_match ( '/^collection_[0-9]+$/i' , $tag_id )) {
$tagChoice = explode ( '_' , $tag_id )[ 1 ];
$this -> loadModel ( 'TagCollection' );
$tagCollection = $this -> TagCollection -> fetchTagCollection ( $this -> Auth -> user (), array ( 'conditions' => array ( 'TagCollection.id' => $tagChoice )));
if ( empty ( $tagCollection )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'Invalid Tag Collection.' )), 'status' => 200 , 'type' => 'json' ));
}
foreach ( $tagCollection [ 0 ][ 'TagCollectionTag' ] as $tagCollectionTag ) {
$tag_id_list [] = $tagCollectionTag [ 'tag_id' ];
}
} else {
$tag_id_list [] = $tag_id ;
}
}
} else {
2021-10-24 10:31:04 +02:00
$tagId = $this -> Event -> EventTag -> Tag -> lookupTagIdForUser ( $this -> Auth -> user (), trim ( $tag_id ));
if ( empty ( $tagId )) {
2019-03-20 11:21:40 +01:00
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'Invalid Tag.' )), 'status' => 200 , 'type' => 'json' ));
}
2021-10-24 10:31:04 +02:00
$tag_id = $tagId ;
2019-01-09 16:09:05 +01:00
}
2019-01-01 16:38:57 +01:00
}
2018-07-19 11:48:22 +02:00
}
2019-03-20 11:21:40 +01:00
$this -> autoRender = false ;
2020-08-15 15:48:39 +02:00
$success = 0 ;
$fails = [];
2019-03-20 11:21:40 +01:00
if ( empty ( $tag_id_list )) {
$tag_id_list = array ( $tag_id );
}
2020-08-15 15:48:39 +02:00
if ( empty ( $tag_id_list )) {
return new CakeResponse ( array ( 'body' => json_encode ([ 'saved' => false , 'errors' => __ ( 'Nothing to add.' )]), 'status' => 200 , 'type' => 'json' ));
}
$this -> loadModel ( 'Taxonomy' );
2019-03-20 11:21:40 +01:00
foreach ( $tag_id_list as $tag_id ) {
2022-10-26 20:48:41 +02:00
$conditions = $this -> Event -> EventTag -> Tag -> createConditions ( $this -> Auth -> user ());
$conditions [ 'Tag.id' ] = $tag_id ;
2019-03-20 11:21:40 +01:00
$tag = $this -> Event -> EventTag -> Tag -> find ( 'first' , array (
2020-08-15 15:48:39 +02:00
'conditions' => $conditions ,
2019-03-20 11:21:40 +01:00
'recursive' => - 1 ,
2021-10-28 11:59:06 +02:00
'fields' => array ( 'Tag.name' , 'Tag.local_only' )
2019-03-20 11:21:40 +01:00
));
2020-08-15 15:48:39 +02:00
if ( ! $tag ) {
$fails [ $tag_id ] = __ ( 'Tag not found.' );
continue ;
}
2022-10-12 20:32:39 +02:00
$found = $this -> Event -> EventTag -> hasAny ([
'event_id' => $id ,
'tag_id' => $tag_id
]);
if ( $found ) {
2020-08-15 15:48:39 +02:00
$fails [ $tag_id ] = __ ( 'Tag is already attached to this event.' );
2019-03-20 11:21:40 +01:00
continue ;
}
2022-10-12 20:32:39 +02:00
$tagsOnEvent = $this -> Event -> EventTag -> find ( 'column' , array (
2019-11-04 11:54:22 +01:00
'conditions' => array (
2019-11-04 14:55:43 +01:00
'EventTag.event_id' => $id ,
'EventTag.local' => $local
2019-11-04 11:54:22 +01:00
),
'contain' => 'Tag' ,
'fields' => array ( 'Tag.name' ),
'recursive' => - 1
));
2022-10-12 20:32:39 +02:00
$exclusiveTestPassed = $this -> Taxonomy -> checkIfNewTagIsAllowedByTaxonomy ( $tag [ 'Tag' ][ 'name' ], $tagsOnEvent );
2019-11-04 15:46:53 +01:00
if ( ! $exclusiveTestPassed ) {
2020-08-15 15:48:39 +02:00
$fails [ $tag_id ] = __ ( 'Tag is not allowed due to taxonomy exclusivity settings' );
2019-11-04 11:54:22 +01:00
continue ;
}
2021-10-28 11:59:06 +02:00
if ( $tag [ 'Tag' ][ 'local_only' ] && ! $local ) {
$fails [ $tag_id ] = __ ( 'Invalid Tag. This tag can only be set as a local tag.' );
continue ;
}
2019-03-20 11:21:40 +01:00
$this -> Event -> EventTag -> create ();
2019-07-08 11:39:41 +02:00
if ( $this -> Event -> EventTag -> save ( array ( 'event_id' => $id , 'tag_id' => $tag_id , 'local' => $local ))) {
if ( ! $local ) {
2022-10-12 20:32:39 +02:00
$this -> Event -> unpublishEvent ( $event );
2019-07-08 11:39:41 +02:00
}
2019-03-20 11:21:40 +01:00
$log = ClassRegistry :: init ( 'Log' );
2019-07-08 11:39:41 +02:00
$log -> createLogEntry (
$this -> Auth -> user (),
'tag' ,
'Event' ,
$id ,
sprintf (
'Attached%s tag (%s) "%s" to event (%s)' ,
$local ? ' local' : '' ,
$tag_id ,
$tag [ 'Tag' ][ 'name' ],
$id
),
sprintf (
'Event (%s) tagged as Tag (%s)%s' ,
$id ,
$tag_id ,
$local ? ' locally' : ''
)
);
2020-08-15 15:48:39 +02:00
++ $success ;
2019-03-20 11:21:40 +01:00
} else {
2020-08-15 15:48:39 +02:00
$fails [ $tag_id ] = __ ( 'Tag could not be added.' );
2019-03-20 11:21:40 +01:00
}
2019-01-01 16:38:57 +01:00
}
2020-08-15 15:48:39 +02:00
if ( $success && empty ( $fails )) {
$body = [ 'saved' => true , 'success' => __n ( 'Tag added.' , 'Tags added.' , $success ), 'check_publish' => true ];
} else if ( $success && ! empty ( $fails )) {
$message = __n ( 'Tag added' , '%s tags added' , $success , $success );
$message .= __ ( ', but %s could not be added: %s' , count ( $fails ), implode ( ', ' , $fails ));
$body = [ 'saved' => true , 'success' => $message , 'check_publish' => true ];
2019-01-01 16:38:57 +01:00
} else {
2020-08-15 15:48:39 +02:00
$body = array ( 'saved' => false , 'errors' => implode ( ', ' , $fails ));
2019-01-01 16:38:57 +01:00
}
2020-08-15 15:48:39 +02:00
return new CakeResponse ( array ( 'body' => json_encode ( $body ), 'status' => 200 , 'type' => 'json' ));
2018-07-19 11:48:22 +02:00
}
}
public function removeTag ( $id = false , $tag_id = false , $galaxy = false )
{
if ( ! $this -> request -> is ( 'post' )) {
2020-08-15 15:49:17 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
if ( ! $event ) {
throw new NotFoundException ( __ ( 'Invalid event.' ));
}
$eventTag = $this -> Event -> EventTag -> find ( 'first' , array (
'conditions' => array (
'event_id' => $event [ 'Event' ][ 'id' ],
'tag_id' => $tag_id ,
),
'contain' => [ 'Tag' ],
'recursive' => - 1 ,
));
if ( ! $eventTag ) {
throw new NotFoundException ( __ ( 'Invalid tag.' ));
}
$this -> set ( 'is_local' , $eventTag [ 'EventTag' ][ 'local' ]);
$this -> set ( 'tag' , $eventTag );
$this -> set ( 'id' , $event [ 'Event' ][ 'id' ]);
2018-07-19 11:48:22 +02:00
$this -> set ( 'tag_id' , $tag_id );
$this -> set ( 'model' , 'Event' );
2020-08-15 15:49:17 +02:00
$this -> set ( 'model_name' , $event [ 'Event' ][ 'info' ]);
2018-07-19 11:48:22 +02:00
$this -> render ( '/Attributes/ajax/tagRemoveConfirmation' );
} else {
$rearrangeRules = array (
2022-10-12 20:32:39 +02:00
'request' => false ,
'Event' => false ,
'tag_id' => 'tag' ,
'event_id' => 'event' ,
'id' => 'event'
2018-07-19 11:48:22 +02:00
);
$RearrangeTool = new RequestRearrangeTool ();
$this -> request -> data = $RearrangeTool -> rearrangeArray ( $this -> request -> data , $rearrangeRules );
if ( $id === false ) {
$id = $this -> request -> data [ 'event' ];
}
if ( $tag_id === false ) {
$tag_id = $this -> request -> data [ 'tag' ];
}
if ( empty ( $tag_id )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'Invalid ' . ( $galaxy ? 'Galaxy' : 'Tag' ) . '.' )), 'status' => 200 , 'type' => 'json' ));
}
if ( ! is_numeric ( $tag_id )) {
$tag = $this -> Event -> EventTag -> Tag -> find ( 'first' , array ( 'recursive' => - 1 , 'conditions' => array ( 'LOWER(Tag.name) LIKE' => strtolower ( trim ( $tag_id )))));
if ( empty ( $tag )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'Invalid ' . ( $galaxy ? 'Galaxy' : 'Tag' ) . '.' )), 'status' => 200 , 'type' => 'json' ));
}
$tag_id = $tag [ 'Tag' ][ 'id' ];
}
if ( ! is_numeric ( $id )) {
$id = $this -> request -> data [ 'Event' ][ 'id' ];
}
$this -> Event -> recursive = - 1 ;
$event = $this -> Event -> read ( array (), $id );
$eventTag = $this -> Event -> EventTag -> find ( 'first' , array (
'conditions' => array (
'event_id' => $id ,
'tag_id' => $tag_id
),
'recursive' => - 1 ,
));
2020-07-22 08:45:51 +02:00
if ( ! $eventTag ) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'Invalid event - ' . ( $galaxy ? 'galaxy' : 'tag' ) . ' combination.' )), 'status' => 200 , 'type' => 'json' ));
}
2019-07-08 11:39:41 +02:00
// org should allow to (un)tag too, so that an event that gets pushed can be (un)tagged locally by the owning org
2020-07-22 08:45:51 +02:00
if ( ! $this -> __canModifyTag ( $event , $eventTag [ 'EventTag' ][ 'local' ])) {
2019-07-08 11:39:41 +02:00
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'You don\'t have permission to do that.' )), 'status' => 200 , 'type' => 'json' ));
}
$this -> Event -> insertLock ( $this -> Auth -> user (), $id );
2018-07-19 11:48:22 +02:00
$tag = $this -> Event -> EventTag -> Tag -> find ( 'first' , array (
'conditions' => array ( 'Tag.id' => $tag_id ),
'recursive' => - 1 ,
'fields' => array ( 'Tag.name' )
));
if ( $this -> Event -> EventTag -> delete ( $eventTag [ 'EventTag' ][ 'id' ])) {
2019-11-13 14:07:12 +01:00
if ( empty ( $eventTag [ 'EventTag' ][ 'local' ])) {
2022-10-12 20:32:39 +02:00
$this -> Event -> unpublishEvent ( $event );
2019-11-13 14:07:12 +01:00
}
2018-07-19 11:48:22 +02:00
$log = ClassRegistry :: init ( 'Log' );
$log -> createLogEntry ( $this -> Auth -> user (), 'tag' , 'Event' , $id , 'Removed tag (' . $tag_id . ') "' . $tag [ 'Tag' ][ 'name' ] . '" from event (' . $id . ')' , 'Event (' . $id . ') untagged of Tag (' . $tag_id . ')' );
2019-11-13 14:07:12 +01:00
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => true , 'success' => ( $galaxy ? 'Galaxy' : 'Tag' ) . ' removed.' , 'check_publish' => empty ( $eventTag [ 'EventTag' ][ 'local' ]))), 'status' => 200 , 'type' => 'json' ));
2018-07-19 11:48:22 +02:00
} else {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => ( $galaxy ? 'Galaxy' : 'Tag' ) . ' could not be removed.' )), 'status' => 200 , 'type' => 'json' ));
}
}
}
/*
* adhereToWarninglists is used when querying this function via the API
* possible options :
* - false : ( default ) ignore warninglists
* - 'soft' : Unset the IDS flag of all attributes hitting on a warninglist item
* - true / 'hard' : Block attributes from being added that have a hit in the warninglists
* returnMetaAttributes is a flag that will force the API to return the results of the
* parsing directly for external further processing . The flag is a simple boolean flag ( 0 || 1 )
*/
public function freeTextImport ( $id , $adhereToWarninglists = false , $returnMetaAttributes = false )
{
2022-04-15 14:31:17 +02:00
$this -> request -> allowMethod ([ 'post' , 'get' ]);
2020-07-20 10:10:47 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
if ( empty ( $event )) {
2022-04-15 14:31:17 +02:00
throw new NotFoundException ( __ ( 'Invalid event.' ));
2020-07-20 10:10:47 +02:00
}
$this -> set ( 'event_id' , $event [ 'Event' ][ 'id' ]);
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'get' )) {
2022-04-28 14:51:21 +02:00
$this -> layout = false ;
2020-07-20 10:10:47 +02:00
$this -> request -> data [ 'Attribute' ][ 'event_id' ] = $event [ 'Event' ][ 'id' ];
2018-07-19 11:48:22 +02:00
2022-04-15 14:31:17 +02:00
} else if ( $this -> request -> is ( 'post' )) {
2018-07-19 11:48:22 +02:00
App :: uses ( 'ComplexTypeTool' , 'Tools' );
$complexTypeTool = new ComplexTypeTool ();
$this -> loadModel ( 'Warninglist' );
$complexTypeTool -> setTLDs ( $this -> Warninglist -> fetchTLDLists ());
2022-10-03 21:12:23 +02:00
$complexTypeTool -> setSecurityVendorDomains ( $this -> Warninglist -> fetchSecurityVendorDomains ());
2018-07-19 11:48:22 +02:00
if ( ! isset ( $this -> request -> data [ 'Attribute' ])) {
$this -> request -> data = array ( 'Attribute' => $this -> request -> data );
}
if ( ! isset ( $this -> request -> data [ 'Attribute' ][ 'value' ])) {
$this -> request -> data [ 'Attribute' ] = array ( 'value' => $this -> request -> data [ 'Attribute' ]);
}
if ( isset ( $this -> request -> data [ 'Attribute' ][ 'adhereToWarninglists' ])) {
$adhereToWarninglists = $this -> request -> data [ 'Attribute' ][ 'adhereToWarninglists' ];
}
2022-04-15 14:31:17 +02:00
$resultArray = $complexTypeTool -> checkFreeText ( $this -> request -> data [ 'Attribute' ][ 'value' ]);
2022-10-03 20:22:22 +02:00
foreach ( $resultArray as & $attribute ) {
$attribute [ 'to_ids' ] = $this -> Event -> Attribute -> typeDefinitions [ $attribute [ 'default_type' ]][ 'to_ids' ];
}
2018-07-19 11:48:22 +02:00
if ( $this -> _isRest ()) {
2022-04-15 19:28:57 +02:00
// Keep this 'types' format for rest response, but it is not necessary for UI
foreach ( $resultArray as $key => $r ) {
$temp = array ();
foreach ( $r [ 'types' ] as $type ) {
$temp [ $type ] = $type ;
}
$resultArray [ $key ][ 'types' ] = $temp ;
}
2018-07-19 11:48:22 +02:00
if ( $returnMetaAttributes || ! empty ( $this -> request -> data [ 'Attribute' ][ 'returnMetaAttributes' ])) {
return $this -> RestResponse -> viewData ( $resultArray , $this -> response -> type ());
} else {
return $this -> __pushFreetext (
$resultArray ,
2020-07-20 12:57:45 +02:00
$event ,
2018-07-19 11:48:22 +02:00
isset ( $this -> request -> data [ 'Attribute' ][ 'distribution' ]) ? $this -> request -> data [ 'Attribute' ][ 'distribution' ] : false ,
isset ( $this -> request -> data [ 'Attribute' ][ 'sharing_group_id' ]) ? $this -> request -> data [ 'Attribute' ][ 'sharing_group_id' ] : false ,
$adhereToWarninglists
);
}
}
2021-03-10 15:42:06 +01:00
$this -> Event -> Attribute -> fetchRelated ( $this -> Auth -> user (), $resultArray );
2018-07-19 11:48:22 +02:00
$typeCategoryMapping = array ();
foreach ( $this -> Event -> Attribute -> categoryDefinitions as $k => $cat ) {
foreach ( $cat [ 'types' ] as $type ) {
$typeCategoryMapping [ $type ][ $k ] = $k ;
}
}
$distributions = $this -> Event -> Attribute -> distributionLevels ;
$sgs = $this -> Event -> SharingGroup -> fetchAllAuthorised ( $this -> Auth -> user (), 'name' , 1 );
if ( empty ( $sgs )) {
unset ( $distributions [ 4 ]);
}
2020-07-20 10:10:47 +02:00
$this -> set ( 'proposals' , ! $this -> __canModifyEvent ( $event ));
2018-07-19 11:48:22 +02:00
$this -> set ( 'distributions' , $distributions );
$this -> set ( 'sgs' , $sgs );
$this -> set ( 'event' , $event );
2020-07-20 12:57:45 +02:00
$this -> set ( 'mayModify' , $this -> __canModifyEvent ( $event ));
2021-01-10 20:23:44 +01:00
$this -> set ( 'typeDefinitions' , $this -> Event -> Attribute -> typeDefinitions );
2018-07-19 11:48:22 +02:00
$this -> set ( 'typeCategoryMapping' , $typeCategoryMapping );
2022-10-01 11:49:57 +02:00
$this -> set ( 'defaultAttributeDistribution' , $this -> Event -> Attribute -> defaultDistribution ());
2018-07-19 11:48:22 +02:00
$this -> set ( 'resultArray' , $resultArray );
$this -> set ( 'importComment' , '' );
2021-06-29 13:38:33 +02:00
$this -> set ( 'title_for_layout' , __ ( 'Freetext Import Results' ));
$this -> set ( 'title' , __ ( 'Freetext Import Results' ));
2020-09-07 10:05:56 +02:00
$this -> set ( 'missingTldLists' , $this -> Warninglist -> missingTldLists ());
2018-07-19 11:48:22 +02:00
$this -> render ( 'resolved_attributes' );
}
}
2020-07-20 12:57:45 +02:00
private function __pushFreetext ( $attributes , array $event , $distribution = false , $sg = false , $adhereToWarninglists = false )
2018-07-19 11:48:22 +02:00
{
if ( $distribution === false ) {
if ( Configure :: read ( 'MISP.default_attribute_distribution' ) != null ) {
2021-10-09 23:32:51 +02:00
$distribution = $this -> Event -> Attribute -> defaultDistribution ();
2018-07-19 11:48:22 +02:00
} else {
$distribution = 0 ;
}
}
// prepare the default choices
foreach ( $attributes as $k => $attribute ) {
$attribute [ 'type' ] = $attribute [ 'default_type' ];
unset ( $attribute [ 'default_type' ]);
unset ( $attribute [ 'types' ]);
if ( isset ( $attribute [ 'default_category' ])) {
$attribute [ 'category' ] = $attribute [ 'default_category' ];
unset ( $attribute [ 'default_category' ]);
} else {
2021-01-10 20:23:44 +01:00
$attribute [ 'category' ] = $this -> Event -> Attribute -> typeDefinitions [ $attribute [ 'type' ]][ 'default_category' ];
2018-07-19 11:48:22 +02:00
}
$attribute [ 'distribution' ] = $distribution ;
2020-07-20 12:57:45 +02:00
$attribute [ 'event_id' ] = $event [ 'Event' ][ 'id' ];
2018-07-19 11:48:22 +02:00
$attributes [ $k ] = $attribute ;
}
// actually save the attribute now
2020-07-20 12:57:45 +02:00
$proposals = ! $this -> __canModifyEvent ( $event );
$temp = $this -> Event -> processFreeTextDataRouter ( $this -> Auth -> user (), $attributes , $event [ 'Event' ][ 'id' ], '' , $proposals , $adhereToWarninglists , empty ( Configure :: read ( 'MISP.background_jobs' )));
2019-07-31 15:57:25 +02:00
if ( empty ( Configure :: read ( 'MISP.background_jobs' ))) {
$attributes = $temp ;
}
2018-07-19 11:48:22 +02:00
// FIXME $attributes does not contain the onteflyattributes
$attributes = array_values ( $attributes );
return $this -> RestResponse -> viewData ( $attributes , $this -> response -> type ());
}
public function saveFreeText ( $id )
{
2022-04-15 18:13:58 +02:00
$this -> request -> allowMethod ([ 'post' ]);
2020-07-20 12:57:45 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
if ( ! $event ) {
throw new NotFoundException ( __ ( 'Invalid event.' ));
}
2020-10-11 12:04:47 +02:00
$this -> Event -> insertLock ( $this -> Auth -> user (), $id );
2022-04-15 18:13:58 +02:00
$attributes = $this -> _jsonDecode ( $this -> request -> data [ 'Attribute' ][ 'JsonObject' ]);
$defaultComment = $this -> request -> data [ 'Attribute' ][ 'default_comment' ];
2020-10-11 12:04:47 +02:00
$proposals = ! $this -> __canModifyEvent ( $event ) || ( isset ( $this -> request -> data [ 'Attribute' ][ 'force' ]) && $this -> request -> data [ 'Attribute' ][ 'force' ]);
2022-04-15 18:13:58 +02:00
$flashMessage = $this -> Event -> processFreeTextDataRouter ( $this -> Auth -> user (), $attributes , $id , $defaultComment , $proposals );
2020-10-11 12:04:47 +02:00
$this -> Flash -> info ( $flashMessage );
if ( $this -> request -> is ( 'ajax' )) {
return $this -> RestResponse -> viewData ( $flashMessage , $this -> response -> type ());
2018-07-19 11:48:22 +02:00
} else {
2020-10-11 12:04:47 +02:00
$this -> redirect ( array ( 'controller' => 'events' , 'action' => 'view' , $id ));
2018-07-19 11:48:22 +02:00
}
}
2019-11-29 10:11:30 +01:00
public function stix2 ()
2018-07-19 11:48:22 +02:00
{
2019-11-26 19:03:02 +01:00
$this -> _legacyAPIRemap ( array (
'paramArray' => array (
'key' , 'id' , 'withAttachment' , 'tags' , 'from' , 'to' , 'last'
),
'request' => $this -> request ,
'named_params' => $this -> params [ 'named' ],
'ordered_url_params' => func_get_args (),
'injectedParams' => array (
'returnFormat' => 'stix2'
),
'alias' => array (
'id' => 'eventid'
)
));
return $this -> restSearch ();
2018-07-19 11:48:22 +02:00
}
2019-11-29 10:11:30 +01:00
public function stix ()
2018-07-19 11:48:22 +02:00
{
2019-11-26 19:03:02 +01:00
$this -> _legacyAPIRemap ( array (
'paramArray' => array (
'key' , 'id' , 'withAttachment' , 'tags' , 'from' , 'to' , 'last'
),
'request' => $this -> request ,
'named_params' => $this -> params [ 'named' ],
'ordered_url_params' => func_get_args (),
'injectedParams' => array (
'returnFormat' => 'stix'
),
'alias' => array (
'id' => 'eventid'
)
));
return $this -> restSearch ();
2018-07-19 11:48:22 +02:00
}
public function filterEventIdsForPush ()
{
2022-03-12 19:22:41 +01:00
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ( __ ( 'This endpoint requires a POST request.' ));
}
$incomingUuids = [];
$incomingEvents = [];
foreach ( $this -> request -> data as $event ) {
$incomingUuids [] = $event [ 'Event' ][ 'uuid' ];
$incomingEvents [ $event [ 'Event' ][ 'uuid' ]] = $event [ 'Event' ][ 'timestamp' ];
}
$events = $this -> Event -> find ( 'all' , [
'conditions' => [ 'Event.uuid' => $incomingUuids ],
'recursive' => - 1 ,
'fields' => [ 'Event.uuid' , 'Event.timestamp' , 'Event.locked' ],
]);
foreach ( $events as $event ) {
if ( $event [ 'Event' ][ 'timestamp' ] >= $incomingEvents [ $event [ 'Event' ][ 'uuid' ]]) {
unset ( $incomingEvents [ $event [ 'Event' ][ 'uuid' ]]);
continue ;
}
if ( $event [ 'Event' ][ 'locked' ] == 0 ) {
unset ( $incomingEvents [ $event [ 'Event' ][ 'uuid' ]]);
2018-07-19 11:48:22 +02:00
}
}
2022-03-12 19:22:41 +01:00
return $this -> RestResponse -> viewData ( array_keys ( $incomingEvents ), $this -> response -> type ());
2018-07-19 11:48:22 +02:00
}
public function checkuuid ( $uuid )
{
if ( ! $this -> userRole [ 'perm_sync' ]) {
throw new MethodNotAllowedException ( __ ( 'You do not have the permission to do that.' ));
}
$events = $this -> Event -> find ( 'first' , array (
'conditions' => array ( 'Event.uuid' => $uuid ),
'recursive' => - 1 ,
'fields' => array ( 'Event.uuid' ),
));
$this -> set ( 'result' , array ( 'result' => empty ( $events )));
}
public function pushProposals ( $uuid )
{
$message = " " ;
$success = true ;
$counter = 0 ;
if ( ! $this -> userRole [ 'perm_sync' ] || ! $this -> userRole [ 'perm_add' ]) {
throw new MethodNotAllowedException ( __ ( 'You do not have the permission to do that.' ));
}
if ( $this -> request -> is ( 'post' )) {
$event = $this -> Event -> find ( 'first' , array (
'conditions' => array ( 'Event.uuid' => $uuid ),
'contains' => array ( 'ShadowAttribute' , 'Attribute' => array (
'fields' => array ( 'id' , 'uuid' , 'event_id' ),
)),
'fields' => array ( 'Event.uuid' , 'Event.id' ),
));
if ( empty ( $event )) {
$message = " Event not found. " ;
$success = false ;
} else {
foreach ( $this -> request -> data as $k => $sa ) {
if ( isset ( $event [ 'ShadowAttribute' ])) {
foreach ( $event [ 'ShadowAttribute' ] as $oldk => $oldsa ) {
if ( $sa [ 'event_uuid' ] == $oldsa [ 'event_uuid' ] && $sa [ 'value' ] == $oldsa [ 'value' ] && $sa [ 'type' ] == $oldsa [ 'type' ] && $sa [ 'category' ] == $oldsa [ 'category' ] && $sa [ 'to_ids' ] == $oldsa [ 'to_ids' ]) {
if ( $oldsa [ 'timestamp' ] < $sa [ 'timestamp' ]) {
$this -> Event -> ShadowAttribute -> delete ( $oldsa [ 'id' ]);
} else {
continue 2 ;
}
}
}
}
$sa [ 'event_id' ] = $event [ 'Event' ][ 'id' ];
if ( $sa [ 'old_id' ] != 0 ) {
foreach ( $event [ 'Attribute' ] as $attribute ) {
if ( $sa [ 'uuid' ] == $attribute [ 'uuid' ]) {
$sa [ 'old_id' ] = $attribute [ 'id' ];
}
}
}
if ( isset ( $sa [ 'id' ])) {
unset ( $sa [ 'id' ]);
}
$this -> Event -> ShadowAttribute -> create ();
if ( ! $this -> Event -> ShadowAttribute -> save ( array ( 'ShadowAttribute' => $sa ))) {
$message = " Some of the proposals could not be saved. " ;
$success = false ;
} else {
$counter ++ ;
}
if ( ! $sa [ 'deleted' ]) {
2021-07-27 15:09:23 +02:00
$this -> Event -> ShadowAttribute -> sendProposalAlertEmail ( $event [ 'Event' ][ 'id' ]);
2018-07-19 11:48:22 +02:00
}
}
}
if ( $success ) {
if ( $counter ) {
$message = $counter . " Proposal(s) added. " ;
} else {
$message = " Nothing to update. " ;
}
}
$this -> set ( 'data' , array ( 'success' => $success , 'message' => $message , 'counter' => $counter ));
$this -> set ( '_serialize' , 'data' );
}
}
public function exportChoice ( $id )
{
2020-07-20 10:10:47 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
2018-07-19 11:48:22 +02:00
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Event not found or you are not authorised to view it.' ));
}
2020-12-07 22:30:16 +01:00
$id = $event [ 'Event' ][ 'id' ];
2018-07-19 11:48:22 +02:00
$exports = array (
'json' => array (
2024-02-14 08:36:28 +01:00
'url' => $this -> baseurl . '/events/restSearch/json/includeAnalystData:1/eventid:' . $id . '.json' ,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'MISP JSON (metadata + all attributes)' ),
2020-12-07 22:30:16 +01:00
'requiresPublished' => false ,
'checkbox' => true ,
2022-09-22 13:15:56 +02:00
'checkbox_text' => __ ( 'Encode Attachments' ),
2024-02-14 08:36:28 +01:00
'checkbox_set' => $this -> baseurl . '/events/restSearch/json/withAttachments:1/includeAnalystData:1/eventid:' . $id . '.json' ,
2022-09-22 13:15:56 +02:00
'checkbox_default' => true ,
),
'xml' => array (
'url' => $this -> baseurl . '/events/restSearch/xml/eventid:' . $id . '.xml' ,
'text' => __ ( 'MISP XML (metadata + all attributes)' ),
'requiresPublished' => false ,
'checkbox' => true ,
'checkbox_text' => __ ( 'Encode Attachments' ),
'checkbox_set' => $this -> baseurl . '/events/restSearch/xml/eventid:' . $id . '/withAttachments:1.xml' ,
'checkbox_default' => true ,
2018-07-19 11:48:22 +02:00
),
'openIOC' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/restSearch/openioc/to_ids:1/published:1/eventid:' . $id . '.json' ,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'OpenIOC (all indicators marked to IDS)' ),
2020-12-07 22:30:16 +01:00
'requiresPublished' => false ,
'checkbox' => false ,
2018-07-19 11:48:22 +02:00
),
'csv' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/restSearch/returnFormat:csv/to_ids:1/published:1/includeContext:0/eventid:' . $id ,
'text' => 'CSV' ,
'requiresPublished' => false ,
'checkbox' => true ,
2022-09-22 13:15:56 +02:00
'checkbox_text' => __ ( 'Include non-IDS marked attributes' ),
'checkbox_set' => $this -> baseurl . '/events/restSearch/returnFormat:csv/to_ids:1||0/published:1||0/includeContext:0/eventid:' . $id ,
2018-07-19 11:48:22 +02:00
),
'csv_with_context' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/restSearch/returnFormat:csv/to_ids:1/published:1/includeContext:1/eventid:' . $id ,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'CSV with additional context' ),
2020-12-07 22:30:16 +01:00
'requiresPublished' => false ,
'checkbox' => true ,
2022-09-22 13:15:56 +02:00
'checkbox_text' => __ ( 'Include non-IDS marked attributes' ),
'checkbox_set' => $this -> baseurl . '/events/restSearch/returnFormat:csv/to_ids:1||0/published:1||0/includeContext:1/eventid:' . $id ,
2018-07-19 11:48:22 +02:00
),
'stix_xml' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/restSearch/stix/eventid:' . $id ,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'STIX 1 XML (metadata + all attributes)' ),
2020-12-07 22:30:16 +01:00
'requiresPublished' => false ,
'checkbox' => true ,
2022-09-22 13:15:56 +02:00
'checkbox_text' => __ ( 'Encode Attachments' ),
'checkbox_set' => $this -> baseurl . '/events/restSearch/stix/eventid:' . $id . '/withAttachments:1' ,
2018-07-19 11:48:22 +02:00
),
'stix_json' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/restSearch/stix-json/eventid:' . $id ,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'STIX 1 JSON (metadata + all attributes)' ),
2020-12-07 22:30:16 +01:00
'requiresPublished' => false ,
'checkbox' => true ,
2022-09-22 13:15:56 +02:00
'checkbox_text' => __ ( 'Encode Attachments' ),
'checkbox_set' => $this -> baseurl . '/events/restSearch/stix-json/withAttachments:1/eventid:' . $id ,
2018-07-19 11:48:22 +02:00
),
2019-01-22 11:54:52 +01:00
'stix2_json' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/restSearch/stix2/eventid:' . $id ,
'text' => 'STIX 2' ,
'requiresPublished' => false ,
'checkbox' => true ,
2022-09-22 13:15:56 +02:00
'checkbox_text' => __ ( 'Encode Attachments' ),
'checkbox_set' => $this -> baseurl . '/events/restSearch/stix2/eventid:' . $id . '/withAttachments:1' ,
2018-07-19 11:48:22 +02:00
),
'rpz' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/attributes/restSearch/returnFormat:rpz/published:1||0/eventid:' . $id ,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'RPZ Zone file' ),
2020-12-07 22:30:16 +01:00
'requiresPublished' => false ,
'checkbox' => false ,
2018-07-19 11:48:22 +02:00
),
'suricata' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/restSearch/returnFormat:suricata/published:1||0/eventid:' . $id ,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'Suricata rules' ),
2020-12-07 22:30:16 +01:00
'requiresPublished' => false ,
'checkbox' => false ,
2018-07-19 11:48:22 +02:00
),
'snort' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/restSearch/returnFormat:snort/published:1||0/eventid:' . $id ,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'Snort rules' ),
2020-12-07 22:30:16 +01:00
'requiresPublished' => false ,
'checkbox' => false ,
2018-07-19 11:48:22 +02:00
),
'bro' => array (
2023-02-17 16:14:00 +01:00
'url' => $this -> baseurl . '/attributes/bro/download/all/false/' . $id ,
// 'url' => $this->baseurl . '/attributes/restSearch/returnFormat:bro/published:1||0/eventid:' . $id,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'Bro rules' ),
2020-12-07 22:30:16 +01:00
'requiresPublished' => false ,
2022-09-22 13:15:56 +02:00
'checkbox' => false ,
2018-07-19 11:48:22 +02:00
),
'text' => array (
2022-09-22 13:15:56 +02:00
'text' => __ ( 'Export all attribute values as a text file' ),
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/attributes/restSearch/returnFormat:text/published:1||0/eventid:' . $id ,
'requiresPublished' => false ,
'checkbox' => true ,
2022-09-22 13:15:56 +02:00
'checkbox_text' => __ ( 'Include non-IDS marked attributes' ),
'checkbox_set' => $this -> baseurl . '/attributes/restSearch/returnFormat:text/published:1||0/to_ids:1||0/eventid:' . $id ,
2018-07-19 11:48:22 +02:00
),
);
if ( $event [ 'Event' ][ 'published' ] == 0 ) {
foreach ( $exports as $k => $export ) {
if ( $export [ 'requiresPublished' ]) {
unset ( $exports [ $k ]);
}
}
$exports [ 'csv' ] = array (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/events/restSearch/returnFormat:csv/includeContext:0/eventid:' . $id ,
2022-09-22 13:15:56 +02:00
'text' => __ ( 'CSV (event not published, IDS flag ignored)' ),
2018-07-19 11:48:22 +02:00
'requiresPublished' => false ,
2022-09-22 13:15:56 +02:00
'checkbox' => false ,
2018-07-19 11:48:22 +02:00
);
}
$this -> loadModel ( 'Module' );
$modules = $this -> Module -> getEnabledModules ( $this -> Auth -> user (), false , 'Export' );
if ( is_array ( $modules ) && ! empty ( $modules )) {
foreach ( $modules [ 'modules' ] as $module ) {
$exports [ $module [ 'name' ]] = array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/exportModule/' . $module [ 'name' ] . '/' . $id ,
'text' => Inflector :: humanize ( $module [ 'name' ]),
'requiresPublished' => true ,
'checkbox' => false ,
2018-07-19 11:48:22 +02:00
);
}
}
$this -> set ( 'exports' , $exports );
$this -> set ( 'id' , $id );
$this -> render ( 'ajax/exportChoice' );
}
public function importChoice ( $id = false , $scope = 'event' )
{
2022-09-22 13:15:56 +02:00
if ( $scope === 'event' ) {
2020-07-20 10:10:47 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
2018-07-19 11:48:22 +02:00
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Event not found or you are not authorised to view it.' ));
}
$imports = array (
2022-09-22 13:15:56 +02:00
'MISP JSON' => array (
'url' => $this -> baseurl . '/events/populate/' . $id ,
'text' => __ ( 'Populate using a JSON file containing MISP event content data' ),
'ajax' => false
),
'freetext' => array (
'url' => $this -> baseurl . '/events/freeTextImport/' . $id ,
'text' => __ ( 'Freetext Import' ),
'ajax' => true ,
'target' => 'popover_form'
),
'template' => array (
'url' => $this -> baseurl . '/templates/templateChoices/' . $id ,
'text' => __ ( 'Populate using a Template' ),
'ajax' => true ,
'target' => 'popover_form'
),
'OpenIOC' => array (
'url' => $this -> baseurl . '/events/addIOC/' . $id ,
'text' => __ ( 'OpenIOC Import' ),
'ajax' => false ,
),
'ThreatConnect' => array (
'url' => $this -> baseurl . '/attributes/add_threatconnect/' . $id ,
'text' => __ ( 'ThreatConnect Import' ),
'ajax' => false
),
'Forensic analysis' => array (
'url' => $this -> baseurl . '/events/upload_analysis_file/' . $id ,
'text' => __ ( '(Experimental) Forensic analysis - Mactime' ),
'ajax' => false ,
)
2018-07-19 11:48:22 +02:00
);
$this -> loadModel ( 'Module' );
$modules = $this -> Module -> getEnabledModules ( $this -> Auth -> user (), false , 'Import' );
if ( is_array ( $modules ) && ! empty ( $modules )) {
2021-07-02 09:31:02 +02:00
foreach ( $modules [ 'modules' ] as $module ) {
2018-07-19 11:48:22 +02:00
$imports [ $module [ 'name' ]] = array (
2022-09-22 13:15:56 +02:00
'url' => $this -> baseurl . '/events/importModule/' . $module [ 'name' ] . '/' . $id ,
'text' => Inflector :: humanize ( $module [ 'name' ]),
'ajax' => false ,
2018-07-19 11:48:22 +02:00
);
}
}
} else {
$imports = array (
'MISP' => array (
2022-09-22 13:15:56 +02:00
'url' => $this -> baseurl . '/events/add_misp_export' ,
'text' => __ ( 'MISP standard (recommended exchange format - lossless)' ),
'ajax' => false ,
'bold' => true ,
2018-07-19 11:48:22 +02:00
),
'STIX' => array (
2022-09-22 13:15:56 +02:00
'url' => $this -> baseurl . '/events/upload_stix' ,
2023-04-19 16:32:39 +02:00
'text' => __ ( 'STIX 1.x format (lossy)' ),
2022-09-22 13:15:56 +02:00
'ajax' => false ,
2018-07-19 11:48:22 +02:00
),
'STIX2' => array (
2022-09-22 13:15:56 +02:00
'url' => $this -> baseurl . '/events/upload_stix/2' ,
2023-04-19 16:32:39 +02:00
'text' => __ ( 'STIX 2.x format (lossy)' ),
2022-09-22 13:15:56 +02:00
'ajax' => false ,
2018-07-19 11:48:22 +02:00
)
);
}
$this -> set ( 'imports' , $imports );
$this -> set ( 'id' , $id );
$this -> render ( 'ajax/importChoice' );
}
// API for pushing samples to MISP
// Either send it to an existing event, or let MISP create a new one automatically
public function upload_sample ( $event_id = null , $advanced = false )
{
$this -> loadModel ( 'Log' );
$hashes = array ( 'md5' => 'malware-sample' , 'sha1' => 'filename|sha1' , 'sha256' => 'filename|sha256' );
$categoryDefinitions = $this -> Event -> Attribute -> categoryDefinitions ;
$categories = array ();
foreach ( $categoryDefinitions as $k => $v ) {
if ( in_array ( 'malware-sample' , $v [ 'types' ]) && ! in_array ( $k , $categories )) {
$categories [] = $k ;
}
}
$default_distribution = ! empty ( Configure :: read ( 'MISP.default_attribute_distribution' )) ? Configure :: read ( 'MISP.default_attribute_distribution' ) : 5 ;
if ( $default_distribution == 'event' ) {
$default_distribution = 5 ;
}
// #TODO i18n
$parameter_options = array (
'distribution' => array ( 'valid_options' => array ( 0 , 1 , 2 , 3 , 5 ), 'default' => $default_distribution ),
'threat_level_id' => array ( 'valid_options' => array ( 1 , 2 , 3 , 4 ), 'default' => 4 ),
'analysis' => array ( 'valid_options' => array ( 0 , 1 , 2 ), 'default' => 0 ),
'info' => array ( 'default' => 'Malware samples uploaded on ' . date ( 'Y-m-d' )),
'to_ids' => array ( 'valid_options' => array ( 0 , 1 ), 'default' => 1 ),
'category' => array ( 'valid_options' => $categories , 'default' => 'Payload installation' ),
'comment' => array ( 'default' => '' )
);
if ( ! $this -> userRole [ 'perm_auth' ]) {
throw new MethodNotAllowedException ( __ ( 'This functionality requires API key access.' ));
}
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ( __ ( 'Please POST the samples as described on the automation page.' ));
}
if ( $this -> response -> type () === 'application/json' ) {
$data = $this -> request -> input ( 'json_decode' , true );
} elseif ( $this -> response -> type () === 'application/xml' ) {
$data = $this -> request -> data ;
} else {
throw new BadRequestException ( __ ( 'Please POST the samples as described on the automation page.' ));
}
if ( isset ( $data [ 'request' ])) {
$data = $data [ 'request' ];
}
foreach ( $parameter_options as $k => $v ) {
if ( isset ( $data [ $k ])) {
if ( isset ( $v [ 'valid_options' ]) && ! in_array ( $data [ $k ], $v [ 'valid_options' ])) {
$data [ 'settings' ][ $k ] = $v [ 'default' ];
} else {
$data [ 'settings' ][ $k ] = $data [ $k ];
}
unset ( $data [ $k ]);
} else {
$data [ 'settings' ][ $k ] = $v [ 'default' ];
}
}
if ( isset ( $data [ 'files' ])) {
foreach ( $data [ 'files' ] as $k => $file ) {
if ( ! isset ( $file [ 'filename' ]) || ! isset ( $file [ 'data' ])) {
unset ( $data [ 'files' ][ $k ]);
} else {
$data [ 'files' ][ $k ][ 'md5' ] = md5 ( base64_decode ( $file [ 'data' ]));
}
}
}
if ( empty ( $data [ 'files' ])) {
throw new BadRequestException ( __ ( 'No samples received, or samples not in the correct format. Please refer to the API documentation on the automation page.' ));
}
if ( isset ( $event_id )) {
$data [ 'settings' ][ 'event_id' ] = $event_id ;
}
if ( isset ( $data [ 'settings' ][ 'event_id' ])) {
$this -> Event -> id = $data [ 'settings' ][ 'event_id' ];
if ( ! $this -> Event -> exists ()) {
throw new NotFoundException ( __ ( 'Event not found' ));
}
}
if ( isset ( $data [ 'advanced' ])) {
$advanced = $data [ 'advanced' ];
}
// check if the user has permission to create attributes for an event, if the event ID has been passed
// If not, create an event
if ( isset ( $data [ 'settings' ][ 'event_id' ]) && ! empty ( $data [ 'settings' ][ 'event_id' ]) && is_numeric ( $data [ 'settings' ][ 'event_id' ])) {
$conditions = array ( 'Event.id' => $data [ 'settings' ][ 'event_id' ]);
if ( ! $this -> _isSiteAdmin ()) {
$conditions [] = array ( 'Event.orgc_id' => $this -> Auth -> user ( 'org_id' ));
if ( ! $this -> userRole [ 'perm_modify_org' ]) {
$conditions [] = array ( 'Event.user_id' => $this -> Auth -> user ( 'id' ));
}
}
$event = $this -> Event -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => $conditions ,
'fields' => array ( 'id' ),
));
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Event not found.' ));
}
$this -> Event -> insertLock ( $this -> Auth -> user (), $event [ 'Event' ][ 'id' ]);
$this -> Event -> id = $data [ 'settings' ][ 'event_id' ];
$date = new DateTime ();
$this -> Event -> saveField ( 'timestamp' , $date -> getTimestamp ());
$this -> Event -> saveField ( 'published' , 0 );
} else {
$this -> Event -> create ();
if ( $data [ 'settings' ][ 'distribution' ] == 5 ) {
throw new BadRequestException ( __ ( 'Distribution level 5 is not supported when uploading a sample without passing an event ID. Distribution level 5 is meant to take on the distribution level of an existing event.' ));
}
$result = $this -> Event -> save (
array (
'info' => $data [ 'settings' ][ 'info' ],
'analysis' => $data [ 'settings' ][ 'analysis' ],
'threat_level_id' => $data [ 'settings' ][ 'threat_level_id' ],
'distribution' => $data [ 'settings' ][ 'distribution' ],
'date' => date ( 'Y-m-d' ),
'orgc_id' => $this -> Auth -> user ( 'org_id' ),
'org_id' => $this -> Auth -> user ( 'org_id' ),
'user_id' => $this -> Auth -> user ( 'id' ),
)
);
if ( ! $result ) {
2023-12-07 15:17:58 +01:00
$this -> Log -> saveOrFailSilently ( array (
2018-07-19 11:48:22 +02:00
'org' => $this -> Auth -> user ( 'Organisation' )[ 'name' ],
'model' => 'Event' ,
'model_id' => 0 ,
'email' => $this -> Auth -> user ( 'email' ),
'action' => 'upload_sample' ,
'user_id' => $this -> Auth -> user ( 'id' ),
'title' => 'Error: Failed to create event using the upload sample functionality' ,
'change' => 'There was an issue creating an event (' . $data [ 'settings' ][ 'info' ] . '). The validation errors were: ' . json_encode ( $this -> Event -> validationErrors ),
));
throw new BadRequestException ( __ ( 'The creation of a new event with the supplied information has failed.' ));
}
$data [ 'settings' ][ 'event_id' ] = $this -> Event -> id ;
$event_id = $this -> Event -> id ;
}
if ( ! isset ( $data [ 'settings' ][ 'to_ids' ]) || ! in_array ( $data [ 'settings' ][ 'to_ids' ], array ( '0' , '1' , 0 , 1 ))) {
$data [ 'settings' ][ 'to_ids' ] = 1 ;
}
$successCount = 0 ;
$errors = array ();
App :: uses ( 'FileAccessTool' , 'Tools' );
foreach ( $data [ 'files' ] as $file ) {
2019-07-08 12:51:37 +02:00
$tmpdir = Configure :: read ( 'MISP.tmpdir' ) ? Configure :: read ( 'MISP.tmpdir' ) : APP . 'tmp' ;
2021-10-03 23:53:03 +02:00
$tmpfile = FileAccessTool :: createTempFile ( $tmpdir , $prefix = 'MISP_upload' );
FileAccessTool :: writeToFile ( $tmpfile , base64_decode ( $file [ 'data' ]));
2018-07-19 11:48:22 +02:00
$tmpfile = new File ( $tmpfile );
if ( $advanced ) {
$result = $this -> Event -> Attribute -> advancedAddMalwareSample (
$event_id ,
$data [ 'settings' ],
$file [ 'filename' ],
$tmpfile
);
if ( $result ) {
$successCount ++ ;
} else {
$errors [] = $file [ 'filename' ];
}
} else {
$result = $this -> Event -> Attribute -> simpleAddMalwareSample (
$event_id ,
$data [ 'settings' ],
$file [ 'filename' ],
$tmpfile
);
if ( $result ) {
$successCount ++ ;
} else {
$errors [] = $file [ 'filename' ];
}
}
if ( ! empty ( $result )) {
foreach ( $result [ 'Object' ] as $object ) {
if ( isset ( $data [ 'settings' ][ 'distribution' ])) {
$object [ 'distribution' ] = $data [ 'settings' ][ 'distribution' ];
}
$object [ 'sharing_group_id' ] = isset ( $data [ 'settings' ][ 'sharing_group_id' ]) ? $data [ 'settings' ][ 'sharing_group_id' ] : 0 ;
if ( ! empty ( $object [ 'Attribute' ])) {
foreach ( $object [ 'Attribute' ] as $k => $attribute ) {
if ( $attribute [ 'value' ] == $tmpfile -> name ) {
$object [ 'Attribute' ][ $k ][ 'value' ] = $file [ 'filename' ];
}
if ( isset ( $data [ 'settings' ][ 'distribution' ])) {
$object [ 'Attribute' ][ $k ][ 'distribution' ] = $data [ 'settings' ][ 'distribution' ];
}
$object [ 'Attribute' ][ $k ][ 'sharing_group_id' ] = isset ( $data [ 'settings' ][ 'sharing_group_id' ]) ? $data [ 'settings' ][ 'sharing_group_id' ] : 0 ;
}
}
$this -> loadModel ( 'MispObject' );
$this -> MispObject -> captureObject ( array ( 'Object' => $object ), $event_id , $this -> Auth -> user ());
}
if ( ! empty ( $result [ 'ObjectReference' ])) {
foreach ( $result [ 'ObjectReference' ] as $reference ) {
$this -> MispObject -> ObjectReference -> smartSave ( $reference , $event_id );
}
}
}
2021-10-03 23:53:03 +02:00
FileAccessTool :: deleteFile ( $tmpfile -> path );
2018-07-19 11:48:22 +02:00
}
if ( ! empty ( $errors )) {
$this -> set ( 'errors' , $errors );
if ( $successCount > 0 ) {
$this -> set ( 'name' , 'Partial success' );
$this -> set ( 'message' , 'Successfuly saved ' . $successCount . ' sample(s), but some samples could not be saved.' );
2020-08-17 15:52:32 +02:00
$this -> set ( 'url' , $this -> baseurl . '/events/view/' . $data [ 'settings' ][ 'event_id' ]);
2018-07-19 11:48:22 +02:00
$this -> set ( 'id' , $data [ 'settings' ][ 'event_id' ]);
$this -> set ( '_serialize' , array ( 'name' , 'message' , 'url' , 'id' , 'errors' ));
} else {
$this -> set ( 'name' , 'Failed' );
$this -> set ( 'message' , 'Failed to save any of the supplied samples.' );
$this -> set ( '_serialize' , array ( 'name' , 'message' , 'errors' ));
}
} else {
$this -> set ( 'name' , 'Success' );
$this -> set ( 'message' , 'Success, saved all attributes.' );
2020-08-17 15:52:32 +02:00
$this -> set ( 'url' , $this -> baseurl . '/events/view/' . $data [ 'settings' ][ 'event_id' ]);
2018-07-19 11:48:22 +02:00
$this -> set ( 'id' , $data [ 'settings' ][ 'event_id' ]);
$this -> set ( '_serialize' , array ( 'name' , 'message' , 'url' , 'id' ));
}
$this -> view ( $data [ 'settings' ][ 'event_id' ]);
$this -> render ( 'view' );
}
public function viewGraph ( $id )
{
2022-05-02 09:50:22 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
2018-07-19 11:48:22 +02:00
if ( empty ( $event )) {
2021-07-02 09:31:02 +02:00
throw new NotFoundException ( __ ( 'Invalid Event.' ));
2018-07-19 11:48:22 +02:00
}
2022-05-02 09:50:22 +02:00
$this -> set ( 'event' , $event );
2018-07-19 11:48:22 +02:00
$this -> set ( 'scope' , 'event' );
2022-05-02 09:50:22 +02:00
$this -> set ( 'mayModify' , $this -> __canModifyEvent ( $event ));
$this -> set ( 'mayPublish' , $this -> __canPublishEvent ( $event ));
$this -> set ( 'id' , $event [ 'Event' ][ 'id' ]);
2018-07-19 11:48:22 +02:00
}
/*
public function deleteNode ( $id ) {
if ( ! $this -> request -> is ( 'post' )) throw new MethodNotAllowedException ( __ ( 'Only POST requests are allowed.' ));
App :: uses ( 'CorrelationGraphTool' , 'Tools' );
$grapher = new CorrelationGraphTool ();
$grapher -> construct ( $this -> Event , $this -> Taxonomy , $this -> GalaxyCluster , $this -> Auth -> user (), $this -> request -> data );
$json = $grapher -> deleteNode ( $id );
}
*/
public function updateGraph ( $id , $type = 'event' )
{
2022-05-15 11:29:12 +02:00
$user = $this -> _closeSession ();
2018-07-19 11:48:22 +02:00
$validTools = array ( 'event' , 'galaxy' , 'tag' );
2022-05-15 11:29:12 +02:00
if ( ! in_array ( $type , $validTools , true )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ( __ ( 'Invalid type.' ));
}
$this -> loadModel ( 'Taxonomy' );
$this -> loadModel ( 'GalaxyCluster' );
App :: uses ( 'CorrelationGraphTool' , 'Tools' );
$grapher = new CorrelationGraphTool ();
$data = $this -> request -> is ( 'post' ) ? $this -> request -> data : array ();
2022-05-15 11:29:12 +02:00
$grapher -> construct ( $this -> Event , $this -> Taxonomy , $this -> GalaxyCluster , $user , $data );
2018-07-19 11:48:22 +02:00
$json = $grapher -> buildGraphJson ( $id , $type );
array_walk_recursive ( $json , function ( & $item , $key ) {
if ( ! mb_detect_encoding ( $item , 'utf-8' , true )) {
$item = utf8_encode ( $item );
}
});
2022-05-15 11:29:12 +02:00
return $this -> RestResponse -> viewData ( $json , 'json' );
2018-07-19 11:48:22 +02:00
}
2022-05-15 11:29:12 +02:00
private function __genDistributionGraph ( $id , $type = 'event' , $extended = 0 , $user = null )
2020-10-14 09:44:33 +02:00
{
2018-07-19 11:48:22 +02:00
$validTools = array ( 'event' );
if ( ! in_array ( $type , $validTools )) {
throw new MethodNotAllowedException ( __ ( 'Invalid type.' ));
}
2020-10-14 09:44:33 +02:00
$this -> loadModel ( 'Server' );
2020-12-28 18:11:24 +01:00
$servers = $this -> Server -> find ( 'column' , array (
'fields' => array ( 'Server.name' ),
2018-07-19 11:48:22 +02:00
));
2021-11-23 14:53:27 +01:00
App :: uses ( 'DistributionGraphTool' , 'Tools' );
$user = $user ? : $this -> Auth -> user ();
$grapher = new DistributionGraphTool ( $this -> Event , $servers , $user , $extended );
2018-07-19 11:48:22 +02:00
$json = $grapher -> get_distributions_graph ( $id );
array_walk_recursive ( $json , function ( & $item , $key ) {
if ( ! mb_detect_encoding ( $item , 'utf-8' , true )) {
$item = utf8_encode ( $item );
}
});
2019-03-12 08:15:27 +01:00
return $json ;
}
2019-06-13 09:16:34 +02:00
public function getEventTimeline ( $id , $type = 'event' )
{
$validTools = array ( 'event' );
if ( ! in_array ( $type , $validTools )) {
throw new MethodNotAllowedException ( 'Invalid type.' );
}
App :: uses ( 'EventTimelineTool' , 'Tools' );
$grapher = new EventTimelineTool ();
$data = $this -> request -> is ( 'post' ) ? $this -> request -> data : array ();
$dataFiltering = array_key_exists ( 'filtering' , $data ) ? $data [ 'filtering' ] : array ();
2020-04-23 10:08:34 +02:00
$scope = isset ( $data [ 'scope' ]) ? $data [ 'scope' ] : 'seen' ;
2019-06-13 09:16:34 +02:00
$extended = isset ( $this -> params [ 'named' ][ 'extended' ]) ? 1 : 0 ;
$grapher -> construct ( $this -> Event , $this -> Auth -> user (), $dataFiltering , $extended );
2020-04-23 10:08:34 +02:00
if ( $scope == 'seen' ) {
$json = $grapher -> get_timeline ( $id );
} elseif ( $scope == 'sightings' ) {
$json = $grapher -> get_sighting_timeline ( $id );
}
2019-06-13 09:16:34 +02:00
array_walk_recursive ( $json , function ( & $item , $key ) {
if ( ! mb_detect_encoding ( $item , 'utf-8' , true )) {
$item = utf8_encode ( $item );
}
});
2021-07-02 09:31:20 +02:00
return $this -> RestResponse -> viewData ( $json , 'json' );
2019-06-13 09:16:34 +02:00
}
2019-03-12 08:15:27 +01:00
public function getDistributionGraph ( $id , $type = 'event' )
{
2022-05-15 11:29:12 +02:00
$user = $this -> _closeSession ();
2019-03-12 08:15:27 +01:00
$extended = isset ( $this -> params [ 'named' ][ 'extended' ]) ? 1 : 0 ;
2022-05-15 11:29:12 +02:00
$json = $this -> __genDistributionGraph ( $id , $type , $extended , $user );
2021-07-02 09:31:20 +02:00
return $this -> RestResponse -> viewData ( $json , 'json' );
2018-07-19 11:48:22 +02:00
}
public function getEventGraphReferences ( $id , $type = 'event' )
{
$validTools = array ( 'event' );
if ( ! in_array ( $type , $validTools )) {
throw new MethodNotAllowedException ( __ ( 'Invalid type.' ));
}
$this -> loadModel ( 'Tag' );
App :: uses ( 'EventGraphTool' , 'Tools' );
$grapher = new EventGraphTool ();
$data = $this -> request -> is ( 'post' ) ? $this -> request -> data : array ();
$extended = isset ( $this -> params [ 'named' ][ 'extended' ]) ? 1 : 0 ;
$grapher -> construct ( $this -> Event , $this -> Tag , $this -> Auth -> user (), $data [ 'filtering' ], $extended );
$json = $grapher -> get_references ( $id );
array_walk_recursive ( $json , function ( & $item , $key ) {
if ( ! mb_detect_encoding ( $item , 'utf-8' , true )) {
$item = utf8_encode ( $item );
}
});
2021-07-02 09:31:20 +02:00
return $this -> RestResponse -> viewData ( $json , 'json' );
2018-07-19 11:48:22 +02:00
}
public function getEventGraphTags ( $id , $type = 'event' )
{
$validTools = array ( 'event' );
if ( ! in_array ( $type , $validTools )) {
throw new MethodNotAllowedException ( __ ( 'Invalid type.' ));
}
$this -> loadModel ( 'Tag' );
App :: uses ( 'EventGraphTool' , 'Tools' );
$grapher = new EventGraphTool ();
$data = $this -> request -> is ( 'post' ) ? $this -> request -> data : array ();
$extended = isset ( $this -> params [ 'named' ][ 'extended' ]) ? 1 : 0 ;
$grapher -> construct ( $this -> Event , $this -> Tag , $this -> Auth -> user (), $data [ 'filtering' ], $extended );
$json = $grapher -> get_tags ( $id );
array_walk_recursive ( $json , function ( & $item , $key ) {
if ( ! mb_detect_encoding ( $item , 'utf-8' , true )) {
$item = utf8_encode ( $item );
}
});
2021-07-02 09:31:20 +02:00
return $this -> RestResponse -> viewData ( $json , 'json' );
2018-07-19 11:48:22 +02:00
}
public function getEventGraphGeneric ( $id , $type = 'event' )
{
$validTools = array ( 'event' );
if ( ! in_array ( $type , $validTools )) {
throw new MethodNotAllowedException ( __ ( 'Invalid type.' ));
}
$this -> loadModel ( 'Tag' );
App :: uses ( 'EventGraphTool' , 'Tools' );
$grapher = new EventGraphTool ();
$data = $this -> request -> is ( 'post' ) ? $this -> request -> data : array ();
$extended = isset ( $this -> params [ 'named' ][ 'extended' ]) ? 1 : 0 ;
$grapher -> construct ( $this -> Event , $this -> Tag , $this -> Auth -> user (), $data [ 'filtering' ], $extended );
if ( ! array_key_exists ( 'keyType' , $data )) {
$keyType = '' ; // empty key
} else {
$keyType = $data [ 'keyType' ];
}
$json = $grapher -> get_generic_from_key ( $id , $keyType );
array_walk_recursive ( $json , function ( & $item , $key ) {
if ( ! mb_detect_encoding ( $item , 'utf-8' , true )) {
$item = utf8_encode ( $item );
}
});
2021-07-02 09:31:20 +02:00
return $this -> RestResponse -> viewData ( $json , 'json' );
2018-07-19 11:48:22 +02:00
}
public function getReferenceData ( $uuid , $type = 'reference' )
{
$validTools = array ( 'reference' );
if ( ! in_array ( $type , $validTools )) {
throw new MethodNotAllowedException ( __ ( 'Invalid type.' ));
}
App :: uses ( 'EventGraphTool' , 'Tools' );
$grapher = new EventGraphTool ();
$data = $this -> request -> is ( 'post' ) ? $this -> request -> data : array ();
$grapher -> construct_for_ref ( $this -> Event -> Object , $this -> Auth -> user ());
$json = $grapher -> get_reference_data ( $uuid );
array_walk_recursive ( $json , function ( & $item , $key ) {
if ( ! mb_detect_encoding ( $item , 'utf-8' , true )) {
$item = utf8_encode ( $item );
}
});
2021-07-02 09:31:20 +02:00
return $this -> RestResponse -> viewData ( $json , 'json' );
2018-07-19 11:48:22 +02:00
}
public function getObjectTemplate ( $type = 'templates' )
{
$validTools = array ( 'templates' );
if ( ! in_array ( $type , $validTools )) {
throw new MethodNotAllowedException ( __ ( 'Invalid type.' ));
}
App :: uses ( 'EventGraphTool' , 'Tools' );
$eventGraphTool = new EventGraphTool ();
$data = $this -> request -> is ( 'post' ) ? $this -> request -> data : array ();
$eventGraphTool -> construct_for_ref ( $this -> Event -> Object , $this -> Auth -> user ());
$json = $eventGraphTool -> get_object_templates ();
array_walk_recursive ( $json , function ( & $item , $key ) {
if ( ! mb_detect_encoding ( $item , 'utf-8' , true )) {
$item = utf8_encode ( $item );
}
});
2021-07-02 09:31:20 +02:00
return $this -> RestResponse -> viewData ( $json , 'json' );
2018-07-19 11:48:22 +02:00
}
2022-04-28 09:50:15 +02:00
public function viewGalaxyMatrix ( $scope_id , $galaxy_id , $scope = 'event' , $disable_picking = false , $extended = false )
2018-07-19 11:48:22 +02:00
{
$this -> loadModel ( 'Galaxy' );
2019-02-15 09:24:52 +01:00
$mitreAttackGalaxyId = $this -> Galaxy -> getMitreAttackGalaxyId ();
2020-10-20 19:52:47 +02:00
if ( $galaxy_id === 'mitre-attack' ) { // specific case for MITRE ATTACK matrix
$galaxy_id = $mitreAttackGalaxyId ;
}
$matrixData = $this -> Galaxy -> getMatrix ( $galaxy_id ); // throws exception if matrix not found
$local = ! empty ( $this -> params [ 'named' ][ 'local' ]);
$this -> set ( 'local' , $local );
2018-07-19 11:48:22 +02:00
2019-02-15 09:24:52 +01:00
$tabs = $matrixData [ 'tabs' ];
$matrixTags = $matrixData [ 'matrixTags' ];
$killChainOrders = $matrixData [ 'killChain' ];
$instanceUUID = $matrixData [ 'instance-uuid' ];
2018-07-19 11:48:22 +02:00
2019-01-17 11:19:40 +01:00
if ( $scope == 'event' ) {
$eventId = $scope_id ;
} elseif ( $scope == 'attribute' ) {
2021-02-15 15:05:23 +01:00
if ( $scope_id == 'selected' ) {
if ( empty ( $this -> params [ 'named' ][ 'eventid' ])) {
throw new Exception ( " Invalid Event. " );
}
$eventId = $this -> params [ 'named' ][ 'eventid' ];
} else {
$attribute = $this -> Event -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array (
'conditions' => array ( 'Attribute.id' => $scope_id ),
'fields' => array ( 'event_id' ),
'flatten' => 1 ,
));
if ( empty ( $attribute )) {
throw new Exception ( " Invalid Attribute. " );
}
$attribute = $attribute [ 0 ];
$eventId = $attribute [ 'Attribute' ][ 'event_id' ];
2019-01-17 11:19:40 +01:00
}
} elseif ( $scope == 'tag_collection' ) {
$eventId = 0 ; // no event_id for tag_collection, consider all events
} else {
throw new Exception ( " Invalid options. " );
}
2019-12-18 15:07:41 +01:00
if ( $scope !== 'tag_collection' ) {
2022-04-28 09:50:15 +02:00
$event = $this -> Event -> fetchEvent ( $this -> Auth -> user (), array ( 'eventid' => $eventId , 'metadata' => true , 'extended' => $extended ));
2019-12-18 15:07:41 +01:00
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Event not found or you are not authorised to view it.' ));
}
2022-04-28 09:50:15 +02:00
if ( $extended ) {
$eventIds = array ();
$eventIds [] = $eventId ;
foreach ( $event [ 0 ][ 'Event' ][ 'extensionEvents' ] as $extensionEvent ) {
$eventIds [] = $extensionEvent [ 'id' ];
}
$eventId = $eventIds ;
}
2019-12-18 15:07:41 +01:00
$scoresDataAttr = $this -> Event -> Attribute -> AttributeTag -> getTagScores ( $this -> Auth -> user (), $eventId , $matrixTags );
$scoresDataEvent = $this -> Event -> EventTag -> getTagScores ( $eventId , $matrixTags );
$maxScore = 0 ;
$scoresData = array ();
foreach ( array_keys ( $scoresDataAttr [ 'scores' ] + $scoresDataEvent [ 'scores' ]) as $key ) {
$sum = ( isset ( $scoresDataAttr [ 'scores' ][ $key ]) ? $scoresDataAttr [ 'scores' ][ $key ] : 0 ) + ( isset ( $scoresDataEvent [ 'scores' ][ $key ]) ? $scoresDataEvent [ 'scores' ][ $key ] : 0 );
$scoresData [ $key ] = $sum ;
$maxScore = max ( $maxScore , $sum );
}
$scores = $scoresData ;
} else {
$scores = $scoresData = array ();
2018-07-19 11:48:22 +02:00
}
2019-02-15 14:41:55 +01:00
// FIXME: temporary fix: add the score of deprecated mitre galaxies to the new one (for the stats)
if ( $matrixData [ 'galaxy' ][ 'id' ] == $mitreAttackGalaxyId ) {
$mergedScore = array ();
foreach ( $scoresData as $tag => $v ) {
$predicateValue = explode ( ':' , $tag , 2 )[ 1 ];
$predicateValue = explode ( '=' , $predicateValue , 2 );
$predicate = $predicateValue [ 0 ];
$clusterValue = $predicateValue [ 1 ];
$mappedTag = '' ;
$mappingWithoutExternalId = array ();
2019-02-15 15:03:03 +01:00
if ( $predicate == 'mitre-attack-pattern' ) {
2019-02-15 14:41:55 +01:00
$mappedTag = $tag ;
$name = explode ( " " , $tag );
$name = join ( " " , array_slice ( $name , 0 , - 2 )); // remove " - external_id"
$mappingWithoutExternalId [ $name ] = $tag ;
} else {
$name = explode ( " " , $clusterValue );
$name = join ( " " , array_slice ( $name , 0 , - 2 )); // remove " - external_id"
if ( isset ( $mappingWithoutExternalId [ $name ])) {
$mappedTag = $mappingWithoutExternalId [ $name ];
} else {
$adjustedTagName = $this -> Galaxy -> GalaxyCluster -> find ( 'list' , array (
'group' => array ( 'GalaxyCluster.id' , 'GalaxyCluster.tag_name' ),
'conditions' => array ( 'GalaxyCluster.tag_name LIKE' => 'misp-galaxy:mitre-attack-pattern=' . $name . '% T%' ),
'fields' => array ( 'GalaxyCluster.tag_name' )
));
$adjustedTagName = array_values ( $adjustedTagName )[ 0 ];
$mappingWithoutExternalId [ $name ] = $adjustedTagName ;
$mappedTag = $mappingWithoutExternalId [ $name ];
}
}
if ( isset ( $mergedScore [ $mappedTag ])) {
$mergedScore [ $mappedTag ] += $v ;
} else {
$mergedScore [ $mappedTag ] = $v ;
}
}
$scores = $mergedScore ;
2019-02-26 09:07:21 +01:00
$maxScore = ! empty ( $mergedScore ) ? max ( array_values ( $mergedScore )) : 0 ;
2019-02-15 14:41:55 +01:00
}
// end FIXME
2018-07-19 11:48:22 +02:00
2019-05-13 15:07:38 +02:00
$this -> Galaxy -> sortMatrixByScore ( $tabs , $scores );
2018-07-19 11:48:22 +02:00
if ( $this -> _isRest ()) {
2019-02-15 09:24:52 +01:00
$json = array ( 'matrix' => $tabs , 'scores' => $scores , 'instance-uuid' => $instanceUUID );
2021-07-02 09:31:20 +02:00
return $this -> RestResponse -> viewData ( $json , 'json' );
}
2018-07-19 11:48:22 +02:00
2021-07-02 09:31:20 +02:00
if ( ! $this -> request -> is ( 'ajax' )) {
throw new MethodNotAllowedException ( __ ( 'Invalid method.' ));
}
2019-02-12 13:59:51 +01:00
2021-07-02 09:31:20 +02:00
App :: uses ( 'ColourGradientTool' , 'Tools' );
$gradientTool = new ColourGradientTool ();
$colours = $gradientTool -> createGradientFromValues ( $scores );
$this -> set ( 'eventId' , $eventId );
$this -> set ( 'target_type' , $scope );
$this -> set ( 'columnOrders' , $killChainOrders );
$this -> set ( 'tabs' , $tabs );
$this -> set ( 'scores' , $scores );
$this -> set ( 'maxScore' , $maxScore );
if ( ! empty ( $colours )) {
$this -> set ( 'colours' , $colours [ 'mapping' ]);
$this -> set ( 'interpolation' , $colours [ 'interpolation' ]);
2018-07-19 11:48:22 +02:00
}
2021-07-02 09:31:20 +02:00
$this -> set ( 'pickingMode' , ! $disable_picking );
$this -> set ( 'target_id' , $scope_id );
if ( $matrixData [ 'galaxy' ][ 'id' ] == $mitreAttackGalaxyId ) {
$this -> set ( 'defaultTabName' , 'mitre-attack' );
$this -> set ( 'removeTrailling' , 2 );
}
$this -> render ( '/Elements/view_galaxy_matrix' );
2018-07-19 11:48:22 +02:00
}
2020-07-07 10:37:31 +02:00
// Displays all the cluster relations for the provided event
2020-07-07 14:49:09 +02:00
public function viewClusterRelations ( $eventId )
2020-05-11 11:32:45 +02:00
{
$event = $this -> Event -> fetchEvent ( $this -> Auth -> user (), array ( 'eventid' => $eventId , 'flatten' => true ));
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Invalid Event.' ));
}
$event = $event [ 0 ];
$clusterIds = array ();
2020-07-07 07:58:03 +02:00
foreach ( $event [ 'Galaxy' ] as $galaxy ) {
foreach ( $galaxy [ 'GalaxyCluster' ] as $cluster ) {
2020-05-11 11:32:45 +02:00
$clusterIds [ $cluster [ 'id' ]] = $cluster [ 'id' ];
}
}
2020-07-07 07:58:03 +02:00
foreach ( $event [ 'Attribute' ] as $attribute ) {
foreach ( $attribute [ 'Galaxy' ] as $galaxy ) {
foreach ( $galaxy [ 'GalaxyCluster' ] as $cluster ) {
2020-05-11 11:32:45 +02:00
$clusterIds [ $cluster [ 'id' ]] = $cluster [ 'id' ];
}
}
}
$this -> loadModel ( 'GalaxyCluster' );
$clusters = $this -> GalaxyCluster -> fetchGalaxyClusters ( $this -> Auth -> user (), array ( 'conditions' => array ( 'GalaxyCluster.id' => $clusterIds )), $full = true );
2020-05-12 10:29:52 +02:00
App :: uses ( 'ClusterRelationsGraphTool' , 'Tools' );
2021-02-19 22:43:38 +01:00
$grapher = new ClusterRelationsGraphTool ( $this -> Auth -> user (), $this -> GalaxyCluster );
2020-07-07 15:56:29 +02:00
$relations = $grapher -> getNetwork ( $clusters , $keepNotLinkedClusters = true , $includeReferencingRelation = true );
2020-05-11 11:32:45 +02:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $relations , $this -> response -> type ());
}
$this -> set ( 'relations' , $relations );
2020-05-12 10:08:13 +02:00
$this -> set ( 'distributionLevels' , $this -> Event -> distributionLevels );
2020-05-11 11:32:45 +02:00
}
2018-07-19 11:48:22 +02:00
public function delegation_index ()
{
$this -> loadModel ( 'EventDelegation' );
$delegatedEvents = $this -> EventDelegation -> find ( 'list' , array (
'conditions' => array ( 'EventDelegation.org_id' => $this -> Auth -> user ( 'org_id' )),
'fields' => array ( 'event_id' )
));
$this -> Event -> contain ( array ( 'User.email' , 'EventTag' => array ( 'Tag' )));
$tags = $this -> Event -> EventTag -> Tag -> find ( 'all' , array ( 'recursive' => - 1 ));
$tagNames = array ( 'None' );
foreach ( $tags as $k => $v ) {
$tagNames [ $v [ 'Tag' ][ 'id' ]] = $v [ 'Tag' ][ 'name' ];
}
$this -> set ( 'tags' , $tagNames );
$this -> paginate = array (
'limit' => 60 ,
2019-02-10 13:08:12 +01:00
'maxLimit' => 9999 , // LATER we will bump here on a problem once we have more than 9999 events <- no we won't, this is the max a user van view/page.
2018-07-19 11:48:22 +02:00
'order' => array (
'Event.timestamp' => 'DESC'
),
'contain' => array (
'Org' => array ( 'fields' => array ( 'id' , 'name' )),
'Orgc' => array ( 'fields' => array ( 'id' , 'name' )),
'SharingGroup' => array ( 'fields' => array ( 'id' , 'name' )),
'ThreatLevel' => array ( 'fields' => array ( 'ThreatLevel.name' ))
),
'conditions' => array ( 'Event.id' => $delegatedEvents ),
);
$this -> set ( 'events' , $this -> paginate ());
2021-03-30 09:38:41 +02:00
$this -> set ( 'threatLevels' , $this -> Event -> ThreatLevel -> listThreatLevels ());
2018-07-19 11:48:22 +02:00
$this -> set ( 'eventDescriptions' , $this -> Event -> fieldDescriptions );
$this -> set ( 'analysisLevels' , $this -> Event -> analysisLevels );
$this -> set ( 'distributionLevels' , $this -> Event -> distributionLevels );
$shortDist = array ( 0 => 'Organisation' , 1 => 'Community' , 2 => 'Connected' , 3 => 'All' , 4 => ' sharing Group' );
$this -> set ( 'shortDist' , $shortDist );
$this -> set ( 'ajax' , false );
$this -> set ( 'simple' , true );
$this -> Event -> contain ( array ( 'User.email' , 'EventTag' => array ( 'Tag' )));
$tags = $this -> Event -> EventTag -> Tag -> find ( 'all' , array ( 'recursive' => - 1 ));
$tagNames = array ( 'None' );
foreach ( $tags as $k => $v ) {
$tagNames [ $v [ 'Tag' ][ 'id' ]] = $v [ 'Tag' ][ 'name' ];
}
$this -> set ( 'tags' , $tagNames );
$this -> render ( 'index' );
}
2023-07-11 16:36:20 +02:00
// expects a model ID, model type, the module to be used (optional) and the type of enrichment (optional)
public function queryEnrichment ( $id , $module = false , $type = 'Enrichment' , $model = 'Attribute' )
2018-07-19 11:48:22 +02:00
{
if ( ! Configure :: read ( 'Plugin.' . $type . '_services_enable' )) {
throw new MethodNotAllowedException ( __ ( '%s services are not enabled.' , $type ));
}
2023-07-11 16:36:20 +02:00
if ( ! in_array ( $model , array ( 'Attribute' , 'ShadowAttribute' , 'Object' , 'Event' ))) {
throw new MethodNotAllowedException ( __ ( 'Invalid model.' ));
2018-07-19 11:48:22 +02:00
}
2023-07-11 16:36:20 +02:00
2019-03-11 23:33:26 +01:00
$this -> loadModel ( 'Module' );
$enabledModules = $this -> Module -> getEnabledModules ( $this -> Auth -> user (), false , $type );
2023-07-11 16:36:20 +02:00
2019-03-11 23:33:26 +01:00
if ( ! is_array ( $enabledModules ) || empty ( $enabledModules )) {
2023-07-11 16:36:20 +02:00
throw new MethodNotAllowedException ( __ ( 'No valid %s options found for this %s.' , $type , strtolower ( $model )));
}
if ( $model === 'Attribute' || $model === 'ShadowAttribute' ) {
$attribute = $this -> Event -> Attribute -> fetchAttributes ( $this -> Auth -> user (), [
'conditions' => [
'Attribute.id' => $id
],
'flatten' => 1 ,
'includeEventTags' => 1 ,
'contain' => [ 'Event' => [ 'fields' => [ 'distribution' , 'sharing_group_id' ]]],
]);
if ( empty ( $attribute )) {
throw new MethodNotAllowedException ( __ ( 'Attribute not found or you are not authorised to see it.' ));
}
2019-03-11 23:33:26 +01:00
}
2023-07-11 16:36:20 +02:00
if ( $model === 'Object' ) {
$object = $this -> Event -> Object -> fetchObjects ( $this -> Auth -> user (), [
'conditions' => [
'Object.id' => $id
],
'flatten' => 1 ,
'includeEventTags' => 1 ,
'contain' => [ 'Event' => [ 'fields' => [ 'distribution' , 'sharing_group_id' ]]],
]);
if ( empty ( $object )) {
throw new MethodNotAllowedException ( __ ( 'Object not found or you are not authorised to see it.' ));
}
}
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'ajax' )) {
2023-07-11 16:36:20 +02:00
$modules = [];
if ( $model === 'Attribute' || $model === 'ShadowAttribute' ) {
foreach ( $enabledModules [ 'modules' ] as $module ) {
if ( in_array ( $attribute [ 0 ][ 'Attribute' ][ 'type' ], $module [ 'mispattributes' ][ 'input' ])) {
$modules [] = array ( 'name' => $module [ 'name' ], 'description' => $module [ 'meta' ][ 'description' ]);
}
2018-07-19 11:48:22 +02:00
}
}
2023-07-11 16:36:20 +02:00
if ( $model === 'Object' ) {
foreach ( $enabledModules [ 'modules' ] as $module ) {
if (
in_array ( $object [ 0 ][ 'Object' ][ 'name' ], $module [ 'mispattributes' ][ 'input' ]) ||
in_array ( $object [ 0 ][ 'Object' ][ 'uuid' ], $module [ 'mispattributes' ][ 'input' ])
) {
$modules [] = array ( 'name' => $module [ 'name' ], 'description' => $module [ 'meta' ][ 'description' ]);
}
}
2018-07-19 11:48:22 +02:00
}
2023-07-11 16:36:20 +02:00
$this -> set ( 'id' , $id );
$this -> set ( 'modules' , $modules );
2018-07-19 11:48:22 +02:00
$this -> set ( 'type' , $type );
2023-07-11 16:36:20 +02:00
$this -> set ( 'model' , $model );
2018-07-19 11:48:22 +02:00
$this -> render ( 'ajax/enrichmentChoice' );
} else {
2023-07-11 16:36:20 +02:00
$options = [];
$format = 'simplified' ;
2018-07-19 11:48:22 +02:00
foreach ( $enabledModules [ 'modules' ] as $temp ) {
if ( $temp [ 'name' ] == $module ) {
2021-06-29 13:38:33 +02:00
$format = ! empty ( $temp [ 'mispattributes' ][ 'format' ]) ? $temp [ 'mispattributes' ][ 'format' ] : 'simplified' ;
2018-07-19 11:48:22 +02:00
if ( isset ( $temp [ 'meta' ][ 'config' ])) {
foreach ( $temp [ 'meta' ][ 'config' ] as $conf ) {
$options [ $conf ] = Configure :: read ( 'Plugin.' . $type . '_' . $module . '_' . $conf );
}
}
2019-03-11 23:33:26 +01:00
break ;
2018-07-19 11:48:22 +02:00
}
}
2019-03-20 11:28:32 +01:00
$distributions = $this -> Event -> Attribute -> distributionLevels ;
$sgs = $this -> Event -> SharingGroup -> fetchAllAuthorised ( $this -> Auth -> user (), 'name' , 1 );
if ( empty ( $sgs )) {
unset ( $distributions [ 4 ]);
}
$this -> set ( 'distributions' , $distributions );
$this -> set ( 'sgs' , $sgs );
2021-06-29 13:38:33 +02:00
$this -> set ( 'title_for_layout' , __ ( 'Enrichment Results' ));
$this -> set ( 'title' , __ ( 'Enrichment Results' ));
2019-03-11 23:33:26 +01:00
if ( $format == 'misp_standard' ) {
2023-07-11 16:36:20 +02:00
if ( $model === 'Attribute' || $model === 'ShadowAttribute' ) {
$this -> __queryEnrichment ( $attribute , $module , $options , $type );
}
if ( $model === 'Object' ) {
$this -> __queryObjectEnrichment ( $object , $module , $options , $type );
}
2018-07-19 11:48:22 +02:00
} else {
2019-03-11 23:33:26 +01:00
$this -> __queryOldEnrichment ( $attribute , $module , $options , $type );
2018-07-19 11:48:22 +02:00
}
2019-03-11 23:33:26 +01:00
}
}
private function __queryEnrichment ( $attribute , $module , $options , $type )
{
2019-03-15 11:28:42 +01:00
if ( $this -> Event -> Attribute -> typeIsAttachment ( $attribute [ 0 ][ 'Attribute' ][ 'type' ])) {
$attribute [ 0 ][ 'Attribute' ][ 'data' ] = $this -> Event -> Attribute -> base64EncodeAttachment ( $attribute [ 0 ][ 'Attribute' ]);
}
2019-03-15 11:31:14 +01:00
$event_id = $attribute [ 0 ][ 'Event' ][ 'id' ];
$data = array ( 'module' => $module , 'attribute' => $attribute [ 0 ][ 'Attribute' ], 'event_id' => $event_id );
2019-03-11 23:33:26 +01:00
if ( ! empty ( $options )) {
$data [ 'config' ] = $options ;
}
2022-07-21 11:18:59 +02:00
$result = $this -> Module -> queryModuleServer ( $data , false , $type , false , $attribute [ 0 ]);
2019-03-20 11:18:22 +01:00
if ( ! $result ) {
2021-06-29 13:53:22 +02:00
throw new InternalErrorException ( __ ( '%s service not reachable.' , $type ));
2019-03-11 23:33:26 +01:00
}
if ( isset ( $result [ 'error' ])) {
$this -> Flash -> error ( $result [ 'error' ]);
}
if ( ! is_array ( $result )) {
throw new Exception ( $result );
}
2019-05-02 11:49:17 +02:00
$event = $this -> Event -> handleMispFormatFromModuleResult ( $result );
if ( empty ( $event [ 'Attribute' ]) && empty ( $event [ 'Object' ])) {
2019-03-18 18:05:18 +01:00
$this -> __handleSimplifiedFormat ( $attribute , $module , $options , $result , $type );
} else {
2019-05-02 11:45:43 +02:00
$importComment = ! empty ( $result [ 'comment' ]) ? $result [ 'comment' ] : $attribute [ 0 ][ 'Attribute' ][ 'value' ] . __ ( ': Enriched via the ' ) . $module . ( $type != 'Enrichment' ? ' ' . $type : '' ) . ' module' ;
$this -> set ( 'importComment' , $importComment );
2019-05-02 11:49:17 +02:00
$event [ 'Event' ] = $attribute [ 0 ][ 'Event' ];
2019-06-11 13:51:53 +02:00
$org_name = $this -> Event -> Orgc -> find ( 'first' , array (
'conditions' => array ( 'Orgc.id' => $event [ 'Event' ][ 'orgc_id' ]),
'fields' => array ( 'Orgc.name' )
));
$event [ 'Event' ][ 'orgc_name' ] = $org_name [ 'Orgc' ][ 'name' ];
2019-04-12 23:36:47 +02:00
if ( $attribute [ 0 ][ 'Object' ][ 'id' ]) {
$object_id = $attribute [ 0 ][ 'Object' ][ 'id' ];
2019-07-02 22:05:38 +02:00
$initial_object = $this -> Event -> fetchInitialObject ( $event_id , $object_id );
2023-07-11 16:36:20 +02:00
if ( ! empty ( $initial_object )) {
$event [ 'initialObject' ] = $initial_object ;
}
}
$this -> set ( 'event' , $event );
$this -> set ( 'menuItem' , 'enrichmentResults' );
$this -> set ( 'title_for_layout' , __ ( 'Enrichment Results' ));
$this -> set ( 'title' , __ ( 'Enrichment Results' ));
$this -> render ( 'resolved_misp_format' );
}
}
private function __queryObjectEnrichment ( $object , $module , $options , $type )
{
$object [ 0 ][ 'Object' ][ 'Attribute' ] = $object [ 0 ][ 'Attribute' ];
foreach ( $object [ 0 ][ 'Object' ][ 'Attribute' ] as & $attribute ) {
if ( $this -> Event -> Attribute -> typeIsAttachment ( $attribute [ 'type' ])) {
$attribute [ 'data' ] = $this -> Event -> Attribute -> base64EncodeAttachment ( $attribute );
}
}
$event_id = $object [ 0 ][ 'Event' ][ 'id' ];
$data = array ( 'module' => $module , 'object' => $object [ 0 ][ 'Object' ], 'event_id' => $event_id );
if ( ! empty ( $options )) {
$data [ 'config' ] = $options ;
}
$result = $this -> Module -> queryModuleServer ( $data , false , $type , false , $object [ 0 ]);
if ( ! $result ) {
throw new InternalErrorException ( __ ( '%s service not reachable.' , $type ));
}
if ( isset ( $result [ 'error' ])) {
$this -> Flash -> error ( $result [ 'error' ]);
}
if ( ! is_array ( $result )) {
throw new Exception ( $result );
}
$event = $this -> Event -> handleMispFormatFromModuleResult ( $result );
if ( empty ( $event [ 'Attribute' ]) && empty ( $event [ 'Object' ])) {
throw new NotImplementedException ( __ ( 'No Attribute or Object returned by the module.' ));
} else {
$importComment = ! empty ( $result [ 'comment' ]) ? $result [ 'comment' ] : $object [ 0 ][ 'Object' ][ 'value' ] . __ ( ': Enriched via the ' ) . $module . ( $type != 'Enrichment' ? ' ' . $type : '' ) . ' module' ;
$this -> set ( 'importComment' , $importComment );
$event [ 'Event' ] = $object [ 0 ][ 'Event' ];
$org_name = $this -> Event -> Orgc -> find ( 'first' , array (
'conditions' => array ( 'Orgc.id' => $event [ 'Event' ][ 'orgc_id' ]),
'fields' => array ( 'Orgc.name' )
));
$event [ 'Event' ][ 'orgc_name' ] = $org_name [ 'Orgc' ][ 'name' ];
if ( $attribute [ 0 ][ 'Object' ][ 'id' ]) {
$object_id = $attribute [ 0 ][ 'Object' ][ 'id' ];
$initial_object = $this -> Event -> fetchInitialObject ( $event_id , $object_id );
2019-04-17 11:56:35 +02:00
if ( ! empty ( $initial_object )) {
$event [ 'initialObject' ] = $initial_object ;
2019-04-12 23:36:47 +02:00
}
2019-03-18 18:05:18 +01:00
}
$this -> set ( 'event' , $event );
2019-04-25 16:28:42 +02:00
$this -> set ( 'menuItem' , 'enrichmentResults' );
2021-06-29 13:38:33 +02:00
$this -> set ( 'title_for_layout' , __ ( 'Enrichment Results' ));
$this -> set ( 'title' , __ ( 'Enrichment Results' ));
2019-04-25 16:28:42 +02:00
$this -> render ( 'resolved_misp_format' );
2019-03-18 18:05:18 +01:00
}
2019-03-11 23:33:26 +01:00
}
private function __queryOldEnrichment ( $attribute , $module , $options , $type )
{
$data = array ( 'module' => $module , $attribute [ 0 ][ 'Attribute' ][ 'type' ] => $attribute [ 0 ][ 'Attribute' ][ 'value' ], 'event_id' => $attribute [ 0 ][ 'Attribute' ][ 'event_id' ], 'attribute_uuid' => $attribute [ 0 ][ 'Attribute' ][ 'uuid' ]);
if ( $this -> Event -> Attribute -> typeIsAttachment ( $attribute [ 0 ][ 'Attribute' ][ 'type' ])) {
$data [ 'data' ] = $this -> Event -> Attribute -> base64EncodeAttachment ( $attribute [ 0 ][ 'Attribute' ]);
}
if ( ! empty ( $options )) {
$data [ 'config' ] = $options ;
}
2022-07-21 11:18:59 +02:00
$result = $this -> Module -> queryModuleServer ( $data , false , $type , false , $attribute [ 0 ]);
2019-03-11 23:33:26 +01:00
if ( ! $result ) {
2021-06-29 13:53:22 +02:00
throw new InternalErrorException ( __ ( '%s service not reachable.' , $type ));
2019-03-11 23:33:26 +01:00
}
if ( isset ( $result [ 'error' ])) {
$this -> Flash -> error ( $result [ 'error' ]);
}
if ( ! is_array ( $result )) {
throw new Exception ( $result );
}
2019-03-18 18:17:55 +01:00
$this -> __handleSimplifiedFormat ( $attribute , $module , $options , $result , $type );
2019-03-18 18:05:18 +01:00
}
2019-04-25 16:28:42 +02:00
private function __handleSimplifiedFormat ( $attribute , $module , $options , $result , $type , $event = false )
2019-03-18 18:05:18 +01:00
{
2019-03-11 23:33:26 +01:00
$resultArray = $this -> Event -> handleModuleResult ( $result , $attribute [ 0 ][ 'Attribute' ][ 'event_id' ]);
2019-04-16 14:26:18 +02:00
if ( ! empty ( $result [ 'comment' ])) {
2019-03-11 23:33:26 +01:00
$importComment = $result [ 'comment' ];
} else {
$importComment = $attribute [ 0 ][ 'Attribute' ][ 'value' ] . __ ( ': Enriched via the %s' , $module ) . ( $type != 'Enrichment' ? ' ' . $type : '' ) . ' module' ;
}
$typeCategoryMapping = array ();
foreach ( $this -> Event -> Attribute -> categoryDefinitions as $k => $cat ) {
foreach ( $cat [ 'types' ] as $type ) {
$typeCategoryMapping [ $type ][ $k ] = $k ;
2018-07-19 11:48:22 +02:00
}
2019-03-11 23:33:26 +01:00
}
2021-03-10 15:42:06 +01:00
$this -> Event -> Attribute -> fetchRelated ( $this -> Auth -> user (), $resultArray );
2019-03-11 23:33:26 +01:00
foreach ( $resultArray as $key => $result ) {
if ( isset ( $result [ 'data' ])) {
App :: uses ( 'FileAccessTool' , 'Tools' );
$tmpdir = Configure :: read ( 'MISP.tmpdir' ) ? Configure :: read ( 'MISP.tmpdir' ) : '/tmp' ;
2021-10-03 23:53:03 +02:00
$tempFile = FileAccessTool :: createTempFile ( $tmpdir , $prefix = 'MISP' );
FileAccessTool :: writeToFile ( $tempFile , $result [ 'data' ]);
2019-03-11 23:33:26 +01:00
$resultArray [ $key ][ 'data' ] = basename ( $tempFile ) . '|' . filesize ( $tempFile );
2018-07-19 11:48:22 +02:00
}
}
2019-03-11 23:33:26 +01:00
$this -> set ( 'type' , $type );
2019-03-18 18:17:55 +01:00
if ( ! $event ){
$this -> set ( 'event' , array ( 'Event' => $attribute [ 0 ][ 'Event' ]));
}
2019-03-11 23:33:26 +01:00
$this -> set ( 'resultArray' , $resultArray );
2021-01-10 20:23:44 +01:00
$this -> set ( 'typeDefinitions' , $this -> Event -> Attribute -> typeDefinitions );
2019-03-11 23:33:26 +01:00
$this -> set ( 'typeCategoryMapping' , $typeCategoryMapping );
2022-10-01 11:49:57 +02:00
$this -> set ( 'defaultAttributeDistribution' , $this -> Event -> Attribute -> defaultDistribution ());
2019-03-11 23:33:26 +01:00
$this -> set ( 'importComment' , $importComment );
2019-04-25 16:28:42 +02:00
$this -> render ( 'resolved_attributes' );
2018-07-19 11:48:22 +02:00
}
2019-04-04 23:29:13 +02:00
public function handleModuleResults ( $id )
2019-03-22 22:31:56 +01:00
{
2020-07-20 12:57:45 +02:00
if ( ! $this -> request -> is ( 'post' )) {
2019-04-04 16:22:02 +02:00
throw new MethodNotAllowedException ( 'This endpoint requires a POST request.' );
}
2020-07-20 12:57:45 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
if ( ! $event ) {
throw new NotFoundException ( __ ( 'Invalid event.' ));
}
if ( ! $this -> __canModifyEvent ( $event )) {
throw new ForbiddenException ( __ ( 'You don\'t have permission to do that.' ));
}
2022-10-10 22:07:25 +02:00
$resolved_data = $this -> _jsonDecode ( $this -> request -> data [ 'Event' ][ 'JsonObject' ]);
$data = $this -> _jsonDecode ( $this -> request -> data [ 'Event' ][ 'data' ]);
2020-07-20 12:57:45 +02:00
if ( ! empty ( $data [ 'initialObject' ])) {
$resolved_data [ 'initialObject' ] = $data [ 'initialObject' ];
}
unset ( $data );
$default_comment = $this -> request -> data [ 'Event' ][ 'default_comment' ];
$flashMessage = $this -> Event -> processModuleResultsDataRouter ( $this -> Auth -> user (), $resolved_data , $event [ 'Event' ][ 'id' ], $default_comment );
$this -> Flash -> info ( $flashMessage );
2020-10-15 19:01:01 +02:00
if ( $this -> request -> is ( 'ajax' )) {
return $this -> RestResponse -> viewData ( $flashMessage , $this -> response -> type ());
} else {
$this -> redirect ( array ( 'controller' => 'events' , 'action' => 'view' , $event [ 'Event' ][ 'id' ]));
}
2019-03-22 22:31:56 +01:00
}
2022-09-28 09:47:50 +02:00
public function importModule ( $moduleName , $eventId )
2018-07-19 11:48:22 +02:00
{
2020-07-20 12:57:45 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $eventId );
if ( ! $event ) {
throw new NotFoundException ( __ ( 'Invalid event.' ));
}
2021-03-02 14:44:41 +01:00
$mayModify = $this -> __canModifyEvent ( $event );
2020-07-20 12:57:45 +02:00
$eventId = $event [ 'Event' ][ 'id' ];
2018-07-19 11:48:22 +02:00
$this -> loadModel ( 'Module' );
2022-09-28 09:47:50 +02:00
$module = $this -> Module -> getEnabledModule ( $moduleName , 'Import' );
2018-07-19 11:48:22 +02:00
if ( ! is_array ( $module )) {
throw new MethodNotAllowedException ( $module );
}
if ( ! isset ( $module [ 'mispattributes' ][ 'inputSource' ])) {
$module [ 'mispattributes' ][ 'inputSource' ] = array ( 'paste' );
}
if ( $this -> request -> is ( 'post' )) {
2022-09-28 09:47:50 +02:00
$requestData = $this -> request -> data [ 'Event' ];
2018-07-19 11:48:22 +02:00
$fail = false ;
$modulePayload = array (
2022-09-28 09:47:50 +02:00
'module' => $module [ 'name' ],
'event_id' => $eventId ,
2018-07-19 11:48:22 +02:00
);
if ( isset ( $module [ 'meta' ][ 'config' ])) {
foreach ( $module [ 'meta' ][ 'config' ] as $conf ) {
$modulePayload [ 'config' ][ $conf ] = Configure :: read ( 'Plugin.Import_' . $moduleName . '_' . $conf );
}
}
2018-08-03 13:32:51 +02:00
if ( $moduleName === 'csvimport' ) {
2022-09-28 09:47:50 +02:00
if ( empty ( $requestData [ 'config' ][ 'header' ]) && $requestData [ 'config' ][ 'has_header' ] === '1' ) {
$requestData [ 'config' ][ 'header' ] = ' ' ;
2018-08-03 13:32:51 +02:00
}
2022-09-28 09:47:50 +02:00
if ( empty ( $requestData [ 'config' ][ 'special_delimiter' ])) {
$requestData [ 'config' ][ 'special_delimiter' ] = ' ' ;
2019-09-17 16:02:41 +02:00
}
2018-08-03 13:32:51 +02:00
}
2020-10-06 17:56:30 +02:00
if ( isset ( $module [ 'mispattributes' ][ 'userConfig' ])) {
foreach ( $module [ 'mispattributes' ][ 'userConfig' ] as $configName => $config ) {
if ( ! $fail ) {
if ( isset ( $config [ 'validation' ])) {
if ( $config [ 'validation' ] === '0' && $config [ 'type' ] == 'String' ) {
$validation = true ;
}
} else {
2022-09-28 09:47:50 +02:00
$validationMethod = Module :: CONFIG_TYPES [ $config [ 'type' ]][ 'validation' ];
$validation = $this -> Module -> { $validationMethod }( $requestData [ 'config' ][ $configName ]);
2018-07-19 11:48:22 +02:00
}
2020-10-06 17:56:30 +02:00
if ( $validation !== true ) {
$fail = ucfirst ( $configName ) . ': ' . $validation ;
} else {
if ( isset ( $config [ 'regex' ]) && ! empty ( $config [ 'regex' ])) {
2022-09-28 09:47:50 +02:00
$fail = preg_match ( $config [ 'regex' ], $requestData [ 'config' ][ $configName ]) ? false : ucfirst ( $configName ) . ': ' . 'Invalid setting' . ( $config [ 'errorMessage' ] ? ' - ' . $config [ 'errorMessage' ] : '' );
2020-10-06 17:56:30 +02:00
if ( ! empty ( $fail )) {
2022-09-28 09:47:50 +02:00
$modulePayload [ 'config' ][ $configName ] = $requestData [ 'config' ][ $configName ];
2020-10-06 17:56:30 +02:00
}
} else {
2022-09-28 09:47:50 +02:00
$modulePayload [ 'config' ][ $configName ] = $requestData [ 'config' ][ $configName ];
2018-07-19 11:48:22 +02:00
}
}
}
}
}
if ( ! $fail ) {
if ( ! empty ( $module [ 'mispattributes' ][ 'inputSource' ])) {
2022-09-28 09:47:50 +02:00
if ( ! isset ( $requestData [ 'source' ])) {
2018-07-19 11:48:22 +02:00
if ( in_array ( 'paste' , $module [ 'mispattributes' ][ 'inputSource' ])) {
2022-09-28 09:47:50 +02:00
$requestData [ 'source' ] = '0' ;
2018-07-19 11:48:22 +02:00
} else {
2022-09-28 09:47:50 +02:00
$requestData [ 'source' ] = '1' ;
2018-07-19 11:48:22 +02:00
}
}
2022-09-28 09:47:50 +02:00
if ( $requestData [ 'source' ] == '1' ) {
if ( isset ( $requestData [ 'data' ])) {
$modulePayload [ 'data' ] = base64_decode ( $requestData [ 'data' ]);
} elseif ( empty ( $requestData [ 'fileupload' ])) {
$fail = __ ( 'Invalid file upload.' );
2018-07-19 11:48:22 +02:00
} else {
2022-09-28 09:47:50 +02:00
$fileupload = $requestData [ 'fileupload' ];
if (( isset ( $fileupload [ 'error' ]) && $fileupload [ 'error' ] == 0 ) || ( ! empty ( $fileupload [ 'tmp_name' ]) && $fileupload [ 'tmp_name' ] != 'none' ) && is_uploaded_file ( $fileupload [ 'tmp_name' ])) {
2018-07-19 11:48:22 +02:00
$filename = basename ( $fileupload [ 'name' ]);
2022-09-28 09:47:50 +02:00
$modulePayload [ 'data' ] = FileAccessTool :: readAndDelete ( $fileupload [ 'tmp_name' ]);
2018-07-19 11:48:22 +02:00
} else {
2022-09-28 09:47:50 +02:00
$fail = __ ( 'Invalid file upload.' );
2018-07-19 11:48:22 +02:00
}
}
} else {
2022-09-28 09:47:50 +02:00
$modulePayload [ 'data' ] = $requestData [ 'paste' ];
2018-07-19 11:48:22 +02:00
}
} else {
$modulePayload [ 'data' ] = '' ;
}
if ( ! $fail ) {
$modulePayload [ 'data' ] = base64_encode ( $modulePayload [ 'data' ]);
if ( ! empty ( $filename )) {
$modulePayload [ 'filename' ] = $filename ;
}
2020-10-22 19:42:47 +02:00
$result = $this -> Module -> queryModuleServer ( $modulePayload , false , $moduleFamily = 'Import' );
2018-07-19 11:48:22 +02:00
if ( ! $result ) {
2021-06-29 13:53:22 +02:00
throw new InternalErrorException ( __ ( 'Import service not reachable.' ));
2018-07-19 11:48:22 +02:00
}
if ( isset ( $result [ 'error' ])) {
$this -> Flash -> error ( $result [ 'error' ]);
}
if ( ! is_array ( $result )) {
throw new Exception ( $result );
}
2019-05-02 11:49:17 +02:00
$importComment = ! empty ( $result [ 'comment' ]) ? $result [ 'comment' ] : 'Enriched via the ' . $module [ 'name' ] . ' module' ;
2020-01-06 16:44:58 +01:00
if ( ! empty ( $module [ 'mispattributes' ][ 'format' ]) && $module [ 'mispattributes' ][ 'format' ] === 'misp_standard' ) {
2022-11-10 16:22:33 +01:00
$resolvedEvent = $this -> Event -> handleMispFormatFromModuleResult ( $result );
$resolvedEvent [ 'Event' ] = $event [ 'Event' ];
2019-08-19 16:44:49 +02:00
if ( $this -> _isRest ()) {
2022-11-10 16:22:33 +01:00
$this -> Event -> processModuleResultsDataRouter ( $this -> Auth -> user (), $resolvedEvent , $eventId , $importComment );
return $this -> RestResponse -> viewData ( $resolvedEvent , $this -> response -> type ());
2019-08-19 16:44:49 +02:00
}
2022-11-10 16:22:33 +01:00
$this -> set ( 'event' , $resolvedEvent );
2019-05-02 11:49:17 +02:00
$this -> set ( 'menuItem' , 'importResults' );
$render_name = 'resolved_misp_format' ;
2018-07-19 11:48:22 +02:00
} else {
2019-05-02 11:49:17 +02:00
$resultArray = $this -> Event -> handleModuleResult ( $result , $eventId );
if ( $this -> _isRest ()) {
return $this -> __pushFreetext (
$resultArray ,
2020-07-20 12:57:45 +02:00
$event ,
2019-05-02 11:49:17 +02:00
false ,
false ,
'soft'
);
2018-07-19 11:48:22 +02:00
}
2019-05-02 11:49:17 +02:00
$typeCategoryMapping = array ();
foreach ( $this -> Event -> Attribute -> categoryDefinitions as $k => $cat ) {
foreach ( $cat [ 'types' ] as $type ) {
$typeCategoryMapping [ $type ][ $k ] = $k ;
}
}
2021-03-10 15:42:06 +01:00
$this -> Event -> Attribute -> fetchRelated ( $this -> Auth -> user (), $resultArray );
2020-07-20 12:57:45 +02:00
$this -> set ( 'event' , $event );
2019-05-02 11:49:17 +02:00
$this -> set ( 'resultArray' , $resultArray );
2021-01-10 20:23:44 +01:00
$this -> set ( 'typeDefinitions' , $this -> Event -> Attribute -> typeDefinitions );
2019-05-02 11:49:17 +02:00
$this -> set ( 'typeCategoryMapping' , $typeCategoryMapping );
2022-10-01 11:49:57 +02:00
$this -> set ( 'defaultAttributeDistribution' , $this -> Event -> Attribute -> defaultDistribution ());
2019-05-02 11:49:17 +02:00
$render_name = 'resolved_attributes' ;
2018-07-19 11:48:22 +02:00
}
2022-09-28 09:47:50 +02:00
$distributionData = $this -> Event -> Attribute -> fetchDistributionData ( $this -> Auth -> user ());
$this -> set ( 'distributions' , $distributionData [ 'levels' ]);
$this -> set ( 'sgs' , $distributionData [ 'sgs' ]);
2021-06-29 13:38:33 +02:00
$this -> set ( 'title' , __ ( 'Import Results' ));
$this -> set ( 'title_for_layout' , __ ( 'Import Results' ));
2018-07-19 11:48:22 +02:00
$this -> set ( 'importComment' , $importComment );
2019-05-02 11:49:17 +02:00
$this -> render ( $render_name );
2018-07-19 11:48:22 +02:00
}
2020-10-06 17:58:25 +02:00
}
if ( $fail ) {
2019-12-12 17:06:53 +01:00
$this -> Flash -> error ( $fail );
2018-07-19 11:48:22 +02:00
}
}
2022-09-28 09:47:50 +02:00
$this -> set ( 'configTypes' , Module :: CONFIG_TYPES );
2018-07-19 11:48:22 +02:00
$this -> set ( 'module' , $module );
$this -> set ( 'eventId' , $eventId );
2020-09-24 17:11:37 +02:00
$this -> set ( 'event' , $event );
2021-03-02 14:44:41 +01:00
$this -> set ( 'mayModify' , $mayModify );
2018-07-19 11:48:22 +02:00
}
public function exportModule ( $module , $id , $standard = false )
{
$result = $this -> Event -> export ( $this -> Auth -> user (), $module , array ( 'eventid' => $id , 'standard' => $standard ));
$this -> response -> body ( base64_decode ( $result [ 'data' ]));
$this -> response -> type ( $result [ 'response' ]);
$this -> response -> download ( 'misp.event.' . $id . '.' . $module . '.export.' . $result [ 'extension' ]);
return $this -> response ;
}
public function toggleCorrelation ( $id )
{
2020-05-15 09:05:50 +02:00
if ( ! $this -> _isSiteAdmin () && ! Configure :: read ( 'MISP.allow_disabling_correlation' )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ( __ ( 'Disabling the correlation is not permitted on this instance.' ));
}
2020-07-20 10:10:47 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
2018-07-19 11:48:22 +02:00
if ( empty ( $event )) {
2020-07-20 10:10:47 +02:00
throw new NotFoundException ( __ ( 'Invalid event' ));
2018-07-19 11:48:22 +02:00
}
2020-07-20 10:10:47 +02:00
if ( ! $this -> __canModifyEvent ( $event )) {
throw new ForbiddenException ( __ ( 'You don\'t have permission to do that.' ));
2018-07-19 11:48:22 +02:00
}
if ( $this -> request -> is ( 'post' )) {
if ( $event [ 'Event' ][ 'disable_correlation' ]) {
$event [ 'Event' ][ 'disable_correlation' ] = 0 ;
$this -> Event -> save ( $event );
2022-10-19 21:16:17 +02:00
$this -> Event -> Attribute -> Correlation -> generateCorrelation ( false , $event [ 'Event' ][ 'id' ]);
2018-07-19 11:48:22 +02:00
} else {
$event [ 'Event' ][ 'disable_correlation' ] = 1 ;
$this -> Event -> save ( $event );
2022-10-19 21:16:17 +02:00
$this -> Event -> Attribute -> Correlation -> purgeCorrelations ( $event [ 'Event' ][ 'id' ]);
2018-07-19 11:48:22 +02:00
}
if ( $this -> _isRest ()) {
2020-07-20 10:10:47 +02:00
return $this -> RestResponse -> saveSuccessResponse ( 'events' , 'toggleCorrelation' , $event [ 'Event' ][ 'id' ], false , 'Correlation ' . ( $event [ 'Event' ][ 'disable_correlation' ] ? 'disabled' : 'enabled' ) . '.' );
2018-07-19 11:48:22 +02:00
} else {
$this -> Flash -> success ( 'Correlation ' . ( $event [ 'Event' ][ 'disable_correlation' ] ? 'disabled' : 'enabled' ) . '.' );
2020-07-20 10:10:47 +02:00
$this -> redirect ( array ( 'controller' => 'events' , 'action' => 'view' , $event [ 'Event' ][ 'id' ]));
2018-07-19 11:48:22 +02:00
}
} else {
$this -> set ( 'event' , $event );
$this -> render ( 'ajax/toggle_correlation' );
}
}
public function checkPublishedStatus ( $id )
{
2022-05-15 11:29:12 +02:00
$user = $this -> _closeSession ();
$event = $this -> Event -> fetchSimpleEvent ( $user , $id , [ 'fields' => 'Event.published' ]);
2018-07-19 11:48:22 +02:00
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
2020-07-20 10:10:47 +02:00
return new CakeResponse ( array ( 'body' => $event [ 'Event' ][ 'published' ], 'status' => 200 , 'type' => 'txt' ));
2018-07-19 11:48:22 +02:00
}
// #TODO i18n
public function pushEventToZMQ ( $id )
{
2019-08-14 15:01:31 +02:00
$id = $this -> Toolbox -> findIdByUuid ( $this -> Event , $id );
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'Post' )) {
if ( Configure :: read ( 'Plugin.ZeroMQ_enable' )) {
$pubSubTool = $this -> Event -> getPubSubTool ();
2021-02-15 11:09:33 +01:00
$event = $this -> Event -> fetchEvent ( $this -> Auth -> user (), array ( 'eventid' => $id , 'includeAllTags' => true ));
2018-07-19 11:48:22 +02:00
if ( ! empty ( $event )) {
$pubSubTool -> publishEvent ( $event [ 0 ]);
$success = 1 ;
$message = 'Event published to ZMQ' ;
} else {
$message = 'Invalid event.' ;
}
} else {
$message = 'ZMQ event publishing not enabled.' ;
}
} else {
$message = 'This functionality is only available via POST requests' ;
}
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Events' , 'pushEventToZMQ' , $id , $this -> response -> type (), $message );
} else {
if ( ! empty ( $success )) {
$this -> Flash -> success ( $message );
} else {
$this -> Flash -> error ( $message );
}
$this -> redirect ( $this -> referer ());
}
}
2019-03-05 12:24:56 +01:00
public function pushEventToKafka ( $id )
{
if ( $this -> request -> is ( 'Post' )) {
$message = 'Kafka event publishing not enabled.' ;
if ( Configure :: read ( 'Plugin.Kafka_enable' )) {
$kafkaEventTopic = Configure :: read ( 'Plugin.Kafka_event_notifications_topic' );
$event = $this -> Event -> quickFetchEvent ( array ( 'eventid' => $id ));
if ( Configure :: read ( 'Plugin.Kafka_event_notifications_enable' ) && ! empty ( $kafkaEventTopic )) {
$kafkaPubTool = $this -> Event -> getKafkaPubTool ();
if ( ! empty ( $event )) {
$kafkaPubTool -> publishJson ( $kafkaEventTopic , $event , 'manual_publish' );
$success = 1 ;
$message = 'Event published to Kafka' ;
} else {
$success = 0 ;
$message = 'Invalid event.' ;
}
}
$kafkaPubTopic = Configure :: read ( 'Plugin.Kafka_event_publish_notifications_topic' );
if ( ! empty ( $event [ 'Event' ][ 'published' ]) && Configure :: read ( 'Plugin.Kafka_event_publish_notifications_enable' ) && ! empty ( $kafkaPubTopic )) {
$kafkaPubTool = $this -> Event -> getKafkaPubTool ();
2021-02-15 11:09:33 +01:00
$params = array ( 'eventid' => $id , 'includeAllTags' => true );
2019-03-05 12:24:56 +01:00
if ( Configure :: read ( 'Plugin.Kafka_include_attachments' )) {
$params [ 'includeAttachments' ] = 1 ;
}
$event = $this -> Event -> fetchEvent ( $this -> Auth -> user (), $params );
if ( ! empty ( $event )) {
$kafkaPubTool -> publishJson ( $kafkaPubTopic , $event [ 0 ], 'manual_publish' );
if ( ! isset ( $success )) {
$success = 1 ;
$message = 'Event published to Kafka' ;
}
} else {
$success = 0 ;
$message = 'Invalid event.' ;
}
}
}
} else {
$message = 'This functionality is only available via POST requests' ;
}
if ( $this -> _isRest ()) {
return $this -> RestResponse -> saveSuccessResponse ( 'Events' , 'pushEventToKafka' , $id , $this -> response -> type (), $message );
} else {
if ( ! empty ( $success )) {
$this -> Flash -> success ( $message );
} else {
$this -> Flash -> error ( $message );
}
$this -> redirect ( $this -> referer ());
}
}
2018-07-19 11:48:22 +02:00
public function getEventInfoById ( $id )
{
2022-05-21 13:10:39 +02:00
$user = $this -> _closeSession ();
2018-07-19 11:48:22 +02:00
if ( empty ( $id )) {
throw new MethodNotAllowedException ( __ ( 'Invalid ID.' ));
}
2022-05-21 13:10:39 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $user , $id , [
2020-07-19 16:22:16 +02:00
'fields' => [ 'Event.id' , 'Event.info' , 'Event.threat_level_id' , 'Event.analysis' ],
'contain' => [ 'EventTag' => [ 'Tag.id' , 'Tag.name' , 'Tag.colour' ], 'ThreatLevel.name' ],
]);
2018-07-19 11:48:22 +02:00
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $event , $this -> response -> type ());
}
2022-05-21 13:10:39 +02:00
if ( $this -> request -> is ( 'ajax' )) {
$this -> layout = false ;
}
$this -> set ( 'analysisLevels' , $this -> Event -> analysisLevels );
$this -> set ( 'validUuid' , Validation :: uuid ( $id ));
$this -> set ( 'id' , $id );
$this -> set ( 'event' , $event );
2018-07-19 11:48:22 +02:00
}
public function enrichEvent ( $id )
{
2020-07-20 10:10:47 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
if ( empty ( $event )) {
2018-07-19 11:48:22 +02:00
throw new MethodNotAllowedException ( __ ( 'Invalid Event' ));
}
2020-07-20 10:10:47 +02:00
if ( ! $this -> __canModifyEvent ( $event )) {
throw new ForbiddenException ( __ ( 'You do not have permission to do that.' ));
}
2018-07-19 11:48:22 +02:00
$this -> Event -> insertLock ( $this -> Auth -> user (), $event [ 'Event' ][ 'id' ]);
if ( $this -> request -> is ( 'post' )) {
$modules = array ();
2018-11-23 14:11:33 +01:00
if ( ! isset ( $this -> request -> data [ 'Event' ])) {
$this -> request -> data = array ( 'Event' => $this -> request -> data );
}
2018-07-19 11:48:22 +02:00
foreach ( $this -> request -> data [ 'Event' ] as $module => $enabled ) {
if ( $enabled ) {
$modules [] = $module ;
}
}
$result = $this -> Event -> enrichmentRouter ( array (
'user' => $this -> Auth -> user (),
'event_id' => $event [ 'Event' ][ 'id' ],
'modules' => $modules
));
if ( $this -> _isRest ()) {
} else {
if ( $result === true ) {
$result = __ ( 'Enrichment task queued for background processing. Check back later to see the results.' );
}
$this -> Flash -> success ( $result );
$this -> redirect ( '/events/view/' . $id );
}
} else {
$this -> loadModel ( 'Module' );
$modules = $this -> Module -> getEnabledModules ( $this -> Auth -> user (), 'expansion' );
2022-04-28 14:51:21 +02:00
$this -> layout = false ;
2018-07-19 11:48:22 +02:00
$this -> set ( 'modules' , $modules );
$this -> render ( 'ajax/enrich_event' );
}
}
2021-01-28 21:15:33 +01:00
public function addEventLock ( $id )
2018-07-19 11:48:22 +02:00
{
2021-01-28 21:15:33 +01:00
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ( 'This endpoint requires a POST request.' );
}
2021-03-08 10:22:55 +01:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
2021-01-28 21:15:33 +01:00
if ( empty ( $event )) {
throw new MethodNotAllowedException ( __ ( 'Invalid Event' ));
}
if ( ! $this -> __canModifyEvent ( $event )) {
throw new UnauthorizedException ( __ ( 'You do not have permission to do that.' ));
}
2018-07-19 11:48:22 +02:00
$this -> loadModel ( 'EventLock' );
2021-01-28 21:15:33 +01:00
$lockId = $this -> EventLock -> insertLockApi ( $event [ 'Event' ][ 'id' ], $this -> Auth -> user ());
return $this -> RestResponse -> viewData ([ 'lock_id' => $lockId ], $this -> response -> type ());
}
public function removeEventLock ( $id , $lockId )
2018-07-19 11:48:22 +02:00
{
2021-01-28 21:15:33 +01:00
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ( 'This endpoint requires a POST request.' );
}
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> User (), $id );
if ( empty ( $event )) {
throw new MethodNotAllowedException ( __ ( 'Invalid Event' ));
}
2018-07-19 11:48:22 +02:00
$this -> loadModel ( 'EventLock' );
2021-01-28 21:15:33 +01:00
$deleted = $this -> EventLock -> deleteApiLock ( $event [ 'Event' ][ 'id' ], $lockId , $this -> Auth -> user ());
return $this -> RestResponse -> viewData ([ 'deleted' => $deleted ], $this -> response -> type ());
}
2021-03-19 18:00:21 +01:00
public function checkLocks ( $id , $timestamp )
2021-01-28 21:15:33 +01:00
{
2022-05-05 14:29:15 +02:00
$user = $this -> _closeSession ();
2021-11-23 14:53:27 +01:00
2018-07-19 11:48:22 +02:00
$event = $this -> Event -> find ( 'first' , array (
'recursive' => - 1 ,
2021-03-19 18:00:21 +01:00
'conditions' => [ 'Event.id' => $id ],
2022-10-27 09:27:35 +02:00
'fields' => [ 'Event.orgc_id' , 'Event.timestamp' , 'Event.user_id' ],
2018-07-19 11:48:22 +02:00
));
2022-10-27 09:27:35 +02:00
// Return empty response if event not found or user don't have permission to modify it
if ( empty ( $event ) || ! $this -> __canModifyEvent ( $event , $user )) {
2021-03-19 18:00:21 +01:00
return new CakeResponse ([ 'status' => 204 ]);
}
$this -> loadModel ( 'EventLock' );
$locks = $this -> EventLock -> checkLock ( $user , $id );
$editors = [];
foreach ( $locks as $t ) {
if ( $t [ 'type' ] === 'user' && $t [ 'User' ][ 'id' ] !== $user [ 'id' ]) {
if ( ! $this -> _isSiteAdmin () && $t [ 'User' ][ 'org_id' ] != $user [ 'org_id' ]) {
$editors [] = __ ( 'another user' );
} else {
$editors [] = $t [ 'User' ][ 'email' ];
2018-07-19 11:48:22 +02:00
}
2021-03-19 18:00:21 +01:00
} else if ( $t [ 'type' ] === 'job' ) {
$editors [] = __ ( 'background job' );
} else if ( $t [ 'type' ] === 'api' ) {
$editors [] = __ ( 'external tool' );
2018-07-19 11:48:22 +02:00
}
}
2021-03-19 18:00:21 +01:00
$editors = array_unique ( $editors );
if ( $event [ 'Event' ][ 'timestamp' ] > $timestamp && empty ( $editors )) {
2022-10-27 09:27:35 +02:00
$message = __ ( '<b>Warning</b>: This event view is outdated. Please reload page to see the latest changes.' );
2021-03-19 18:00:21 +01:00
$this -> set ( 'class' , 'alert' );
} else if ( $event [ 'Event' ][ 'timestamp' ] > $timestamp ) {
2022-10-27 09:27:35 +02:00
$message = __ ( '<b>Warning</b>: This event view is outdated, because is currently being edited by: %s. Please reload page to see the latest changes.' , h ( implode ( ', ' , $editors )));
2021-03-19 18:00:21 +01:00
$this -> set ( 'class' , 'alert' );
} else if ( empty ( $editors )) {
return new CakeResponse ([ 'status' => 204 ]);
2018-07-19 11:48:22 +02:00
} else {
2021-03-19 18:00:21 +01:00
$message = __ ( 'This event is currently being edited by: %s' , h ( implode ( ', ' , $editors )));
$this -> set ( 'class' , 'alert alert-info' );
2018-07-19 11:48:22 +02:00
}
2021-01-28 21:15:33 +01:00
$this -> set ( 'message' , $message );
$this -> layout = false ;
$this -> render ( '/Events/ajax/event_lock' );
2018-07-19 11:48:22 +02:00
}
public function getEditStrategy ( $id )
{
// find the id of the event, change $id to it and proceed to read the event as if the ID was entered.
2022-10-27 09:27:35 +02:00
$event = $this -> Event -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => Validation :: uuid ( $id ) ? [ 'Event.uuid' => $id ] : [ 'Event.id' => $id ],
'fields' => array ( 'Event.id' , 'Event.uuid' , 'Event.orgc_id' , 'Event.user_id' )
));
2018-07-19 11:48:22 +02:00
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$response = array ( 'extensions' => array ());
2022-10-27 09:27:35 +02:00
if ( $this -> __canModifyEvent ( $event )) {
2018-07-19 11:48:22 +02:00
$response [ 'strategy' ] = 'edit' ;
} else {
$response [ 'strategy' ] = 'extend' ;
}
$extendedEvents = $this -> Event -> find ( 'all' , array (
'recursive' => - 1 ,
'fields' => array ( 'Event.id' , 'Event.info' , 'Event.uuid' ),
'conditions' => array (
'Event.extends_uuid' => $event [ 'Event' ][ 'uuid' ],
'Event.orgc_id' => $this -> Auth -> user ( 'org_id' )
)
));
foreach ( $extendedEvents as $extendedEvent ) {
$response [ 'extensions' ][] = $extendedEvent [ 'Event' ];
}
return $this -> RestResponse -> viewData ( $response , $this -> response -> type ());
}
2018-11-23 14:22:18 +01:00
public function upload_analysis_file ( $eventId )
{
$data = array ();
$this -> set ( 'eventId' , $eventId );
$this -> set ( 'file_uploaded' , " 0 " );
$this -> set ( 'file_name' , " " );
2018-11-23 15:31:24 +01:00
2018-11-23 14:22:18 +01:00
if ( ! $this -> userRole [ 'perm_modify' ]) {
throw new UnauthorizedException ( 'You do not have permission to do that.' );
}
2018-11-23 14:52:43 +01:00
if ( $this -> request -> is ( 'post' ) && ! empty ( $this -> request [ 'data' ][ 'Event' ][ 'analysis_file' ][ 'name' ])) {
2018-11-23 14:22:18 +01:00
$this -> set ( 'file_uploaded' , " 1 " );
$this -> set ( 'file_name' , $this -> request [ 'data' ][ 'Event' ][ 'analysis_file' ][ 'name' ]);
$this -> set ( 'file_content' , file_get_contents ( $this -> request [ 'data' ][ 'Event' ][ 'analysis_file' ][ 'tmp_name' ]));
//$result = $this->Event->upload_mactime($this->Auth->user(), );
} elseif ( $this -> request -> is ( 'post' ) && $this -> request [ 'data' ][ 'SelectedData' ][ 'mactime_data' ]) {
2018-12-12 11:16:00 +01:00
// Find the event that is to be updated
if ( Validation :: uuid ( $eventId )) {
$eventFindParams [ 'conditions' ][ 'Event.uuid' ] = $eventId ;
} elseif ( is_numeric ( $eventId )) {
$eventFindParams [ 'conditions' ][ 'Event.id' ] = $eventId ;
} else {
throw new NotFoundException ( __ ( 'Invalid event.' ));
}
$event = $this -> Event -> find ( 'first' , $eventFindParams );
2019-02-10 13:08:12 +01:00
if ( empty ( $event ) || ( ! $this -> _isSiteAdmin () && $event [ 'Event' ][ 'orgc_id' ] != $this -> Auth -> user ( 'org_id' ))) {
2018-12-12 11:16:00 +01:00
throw new NotFoundException ( __ ( 'Invalid event.' ));
}
$eventId = $event [ 'Event' ][ 'id' ];
2018-11-23 14:22:18 +01:00
$fileName = $this -> request [ 'data' ][ 'SelectedData' ][ 'mactime_file_name' ];
$fileData = $this -> request [ 'data' ][ 'SelectedData' ][ 'mactime_file_content' ];
$object = array ();
2019-02-10 13:08:12 +01:00
$data = json_decode ( $this -> request [ 'data' ][ 'SelectedData' ][ 'mactime_data' ], true );
$firstObject = 1 ;
2018-11-23 14:22:18 +01:00
foreach ( $data as $objectData ) {
$object [ 'Object' ] = array (
'name' => 'mactime-timeline-analysis' ,
'meta-category' => 'file' ,
'description' => 'Mactime template, used in forensic investigations to describe the timeline of a file activity' ,
'template_version' => 1 ,
2023-10-31 15:02:26 +01:00
'template_uuid' => '58149b06-eabe-4937-9dac-01d63f504e14'
2018-11-23 14:22:18 +01:00
);
2018-11-23 15:31:24 +01:00
2018-11-23 14:22:18 +01:00
$object [ 'Attribute' ] = array (
[
" event_id " => $eventId ,
" category " => " Other " ,
" type " => " text " ,
" to_ids " => false ,
" distribution " => " 5 " ,
" object_relation " => " filepath " ,
" value " => $objectData [ 'filepath' ]
],
[
" event_id " => $eventId ,
" category " => " Other " ,
" type " => " datetime " ,
" to_ids " => false ,
" distribution " => " 5 " ,
" object_relation " => " datetime " ,
" value " => $objectData [ 'time_accessed' ]
],
[
" event_id " => $eventId ,
" category " => " Other " ,
" type " => " text " ,
" to_ids " => false ,
" distribution " => " 5 " ,
" object_relation " => " fileSize " ,
" value " => $objectData [ 'file_size' ]
],
[
" event_id " => $eventId ,
" category " => " Other " ,
" type " => " text " ,
" to_ids " => false ,
" distribution " => " 5 " ,
" object_relation " => " activityType " ,
" value " => $objectData [ 'activity_type' ]
],
[
" event_id " => $eventId ,
" category " => " Other " ,
" type " => " text " ,
" to_ids " => false ,
" distribution " => " 5 " ,
" object_relation " => " filePermissions " ,
" value " => $objectData [ 'permissions' ]
],
[
" event_id " => $eventId ,
" category " => " External analysis " ,
" type " => " attachment " ,
" to_ids " => false ,
" distribution " => " 5 " ,
" object_relation " => " file " ,
" value " => $fileName ,
" data " => base64_encode ( $fileData ),
" comment " => " Mactime source file "
]
2018-11-23 15:31:24 +01:00
2018-11-23 14:22:18 +01:00
);
$this -> loadModel ( 'MispObject' );
2023-10-31 15:02:26 +01:00
$ObjectResult = $this -> MispObject -> saveObject ( $object , $eventId , false , $this -> Auth -> user ());
2018-11-23 14:22:18 +01:00
$temp = $this -> MispObject -> ObjectReference -> Object -> find ( 'first' , array (
'recursive' => - 1 ,
'fields' => array ( 'Object.uuid' , 'Object.id' ),
'conditions' => array ( 'Object.id' => $ObjectResult )
));
2018-11-23 15:31:24 +01:00
2018-11-23 14:52:43 +01:00
if ( $firstObject === 0 ) {
2018-11-23 14:22:18 +01:00
$objectRef [ 'referenced_id' ] = $PreviousObjRef [ 'Object' ][ 'id' ];
$objectRef [ 'referenced_uuid' ] = $PreviousObjRef [ 'Object' ][ 'uuid' ];
$objectRef [ 'object_id' ] = $ObjectResult ;
2018-11-23 14:52:43 +01:00
$objectRef [ 'relationship_type' ] = " preceded-by " ;
2018-11-23 14:22:18 +01:00
$this -> loadModel ( 'MispObject' );
2021-10-24 20:42:55 +02:00
$result = $this -> MispObject -> ObjectReference -> captureReference ( $objectRef , $eventId );
2018-11-23 14:22:18 +01:00
$objectRef [ 'referenced_id' ] = $temp [ 'Object' ][ 'id' ];
$objectRef [ 'referenced_uuid' ] = $temp [ 'Object' ][ 'uuid' ];
$objectRef [ 'object_id' ] = $PreviousObjRef [ 'Object' ][ 'id' ];
$objectRef [ 'relationship_type' ] = " followed-by " ;
$this -> loadModel ( 'MispObject' );
2021-10-24 20:42:55 +02:00
$result = $this -> MispObject -> ObjectReference -> captureReference ( $objectRef , $eventId );
2018-11-23 14:22:18 +01:00
$PreviousObjRef = $temp ;
} else {
$PreviousObjRef = $temp ;
$firstObject = 0 ;
}
}
$this -> redirect ( '/events/view/' . $eventId );
}
}
2019-06-04 19:45:28 +02:00
public function cullEmptyEvents ()
{
$eventIds = $this -> Event -> find ( 'list' , array (
'conditions' => array ( 'Event.published' => 1 ),
'fields' => array ( 'Event.id' , 'Event.uuid' ),
'recursive' => - 1
));
$count = 0 ;
2020-09-01 12:56:35 +02:00
$this -> Event -> skipBlocklist = true ;
2019-06-04 19:45:28 +02:00
foreach ( $eventIds as $eventId => $eventUuid ) {
$result = $this -> Event -> Attribute -> find ( 'first' , array (
'conditions' => array ( 'Attribute.event_id' => $eventId ),
'recursive' => - 1 ,
'fields' => array ( 'Attribute.id' , 'Attribute.event_id' )
));
if ( empty ( $result )) {
$this -> Event -> delete ( $eventId );
$count ++ ;
}
}
2020-09-01 12:56:35 +02:00
$this -> Event -> skipBlocklist = null ;
2019-06-04 19:45:28 +02:00
$message = __ ( '%s event(s) deleted.' , $count );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $message , $this -> response -> type ());
} else {
$this -> Flash -> success ( $message );
$this -> redirect ( $this -> referer ());
}
}
2020-09-15 23:54:59 +02:00
public function restoreDeletedEvents ( $force = false )
{
$startDate = '2020-07-31 00:00:00' ;
2020-09-16 10:01:31 +02:00
$this -> loadModel ( 'AdminSetting' );
$endDate = date ( 'Y-m-d H:i:s' , $this -> AdminSetting -> getSetting ( 'fix_login' ));
if ( empty ( $endDate )) {
$endDate = date ( 'Y-m-d H:i:s' , time ());
}
2020-09-15 23:54:59 +02:00
$this -> loadModel ( 'Log' );
$redis = $this -> Event -> setupRedis ();
if ( $force || ( $redis && ! $redis -> exists ( 'misp:event_recovery' ))) {
$deleted_events = $this -> Log -> findDeletedEvents ([ 'created BETWEEN ? AND ?' => [ $startDate , $endDate ]]);
$redis -> set ( 'misp:event_recovery' , json_encode ( $deleted_events ));
$redis -> expire ( 'misp:event_recovery' , 600 );
} else {
$deleted_events = json_decode ( $redis -> get ( 'misp:event_recovery' ), true );
}
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( $deleted_events , 'json' );
} else {
$this -> set ( 'data' , $deleted_events );
}
}
2020-09-18 13:42:52 +02:00
public function recoverEvent ( $id , $mock = false )
2020-09-15 23:54:59 +02:00
{
2020-09-19 18:35:15 +02:00
if ( $mock || ! Configure :: read ( 'MISP.background_jobs' )) {
2020-09-18 13:53:40 +02:00
if ( $this -> request -> is ( 'post' )) {
$this -> loadModel ( 'Log' );
$result = $this -> Log -> recoverDeletedEvent ( $id , $mock );
2020-09-18 15:49:48 +02:00
if ( $mock ) {
$message = __ ( 'Recovery simulation complete. Event #%s can be recovered using %s log entries.' , $id , $result );
} else {
$message = __ ( 'Recovery complete. Event #%s recovered, using %s log entries.' , $id , $result );
}
2020-09-18 13:53:40 +02:00
if ( $this -> _isRest ()) {
if ( $mock ) {
$results = $this -> Log -> mockLog ;
} else {
$results = $this -> Event -> fetchEvent ( $this -> Auth -> user (), [ 'eventid' => $id ]);
}
return $this -> RestResponse -> viewData ( $results , $this -> response -> type ());
2020-09-18 13:42:52 +02:00
} else {
2020-09-18 13:53:40 +02:00
$this -> Flash -> success ( $message );
2020-09-19 18:35:15 +02:00
if ( ! $mock ) {
$this -> redirect ([ 'action' => 'restoreDeletedEvents' ]);
}
2020-09-18 13:42:52 +02:00
}
2020-09-15 23:54:59 +02:00
} else {
2020-09-18 13:53:40 +02:00
$message = __ ( 'This action is only accessible via POST requests.' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( array ( 'message' => $message , 'error' => true ), $this -> response -> type ());
} else {
$this -> Flash -> error ( $message );
}
$this -> redirect ([ 'action' => 'restoreDeletedEvents' ]);
2020-09-15 23:54:59 +02:00
}
2020-09-18 13:53:40 +02:00
$this -> set ( 'data' , $this -> Log -> mockLog );
2020-09-15 23:54:59 +02:00
} else {
2020-09-18 13:53:40 +02:00
if ( $this -> request -> is ( 'post' )) {
$job_type = 'recover_event' ;
$function = 'recoverEvent' ;
$message = __ ( 'Bootstraping recovering of event %s' , $id );
$job = ClassRegistry :: init ( 'Job' );
$job -> create ();
$data = array (
2021-03-10 21:33:10 +01:00
'worker' => 'prio' ,
'job_type' => $job_type ,
'job_input' => sprintf ( 'Event ID: %s' , $id ),
'status' => 0 ,
'retries' => 0 ,
'org_id' => 0 ,
'org' => 'ADMIN' ,
'message' => $message
2020-09-18 13:53:40 +02:00
);
$job -> save ( $data );
$jobId = $job -> id ;
2021-10-27 11:33:32 +02:00
$this -> Event -> getBackgroundJobsTool () -> enqueue (
BackgroundJobsTool :: PRIO_QUEUE ,
BackgroundJobsTool :: CMD_EVENT ,
[
$function ,
$jobId ,
$id
],
true ,
2021-11-02 16:25:43 +01:00
$jobId
2020-09-18 13:53:40 +02:00
);
$message = __ ( 'Recover event job queued. Job ID: %s' , $jobId );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( array ( 'message' => $message ), $this -> response -> type ());
} else {
$this -> Flash -> success ( $message );
}
2020-09-15 23:54:59 +02:00
} else {
2020-09-18 13:53:40 +02:00
$message = __ ( 'This action is only accessible via POST requests.' );
if ( $this -> _isRest ()) {
return $this -> RestResponse -> viewData ( array ( 'message' => $message , 'error' => true ), $this -> response -> type ());
} else {
$this -> Flash -> error ( $message );
}
2020-09-15 23:54:59 +02:00
}
2020-09-18 13:42:52 +02:00
$this -> redirect ([ 'action' => 'restoreDeletedEvents' ]);
}
2020-09-15 23:54:59 +02:00
}
2020-11-05 16:08:17 +01:00
public function runTaxonomyExclusivityCheck ( $id )
{
2022-05-12 11:13:35 +02:00
if ( Configure :: read ( 'MISP.disable_taxonomy_consistency_checks' )) {
return $this -> RestResponse -> saveFailResponse ( 'Events' , 'runTaxonomyExclusivityCheck' , null , 'Taxonomy consistency checks are disabled, set `MISP.disable_taxonomy_consistency_checks` to `false` to enable them.' , 'json' );
}
2020-11-05 16:08:17 +01:00
$conditions = [];
if ( is_numeric ( $id )) {
$conditions = array ( 'eventid' => $id );
} else if ( Validation :: uuid ( $id )) {
$conditions = array ( 'event_uuid' => $id );
} else {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$conditions [ 'excludeLocalTags' ] = false ;
$conditions [ 'excludeGalaxy' ] = true ;
$event = $this -> Event -> fetchEvent ( $this -> Auth -> user (), $conditions );
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$event = $event [ 0 ];
$this -> loadModel ( 'Taxonomy' );
$allConflicts = [];
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $event [ 'EventTag' ]);
if ( ! empty ( $tagConflicts [ 'global' ]) || ! empty ( $tagConflicts [ 'local' ])) {
$tagConflicts [ 'Event' ] = $event [ 'Event' ];
$allConflicts [] = $tagConflicts ;
}
foreach ( $event [ 'Object' ] as $k => $object ) {
if ( isset ( $object [ 'Attribute' ])) {
foreach ( $object [ 'Attribute' ] as $k2 => $attribute ) {
$this -> Event -> Attribute -> removeGalaxyClusterTags ( $event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ]);
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
if ( ! empty ( $tagConflicts [ 'global' ]) || ! empty ( $tagConflicts [ 'local' ])) {
$tagConflicts [ 'Attribute' ] = $event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ];
unset ( $tagConflicts [ 'Attribute' ][ 'AttributeTag' ], $tagConflicts [ 'Attribute' ][ 'Galaxy' ], $tagConflicts [ 'Attribute' ][ 'ShadowAttribute' ]);
$allConflicts [] = $tagConflicts ;
}
}
}
}
foreach ( $event [ 'Attribute' ] as $k => $attribute ) {
$this -> Event -> Attribute -> removeGalaxyClusterTags ( $event [ 'Attribute' ][ $k ]);
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
if ( ! empty ( $tagConflicts [ 'global' ]) || ! empty ( $tagConflicts [ 'local' ])) {
$tagConflicts [ 'Attribute' ] = $event [ 'Attribute' ][ $k ];
unset ( $tagConflicts [ 'Attribute' ][ 'AttributeTag' ], $tagConflicts [ 'Attribute' ][ 'Galaxy' ], $tagConflicts [ 'Attribute' ][ 'ShadowAttribute' ]);
$allConflicts [] = $tagConflicts ;
}
}
return $this -> RestResponse -> viewData ( $allConflicts );
}
2021-01-17 20:54:14 +01:00
2021-09-26 12:23:23 +02:00
public function generateCount ()
{
if ( ! $this -> request -> is ( 'post' )) {
throw new MethodNotAllowedException ();
}
// do one SQL query with the counts
// loop over events, update in db
$this -> loadModel ( 'Attribute' );
$events = $this -> Attribute -> find ( 'all' , array (
'recursive' => - 1 ,
'fields' => array ( 'event_id' , 'count(event_id) as attribute_count' ),
'group' => array ( 'Attribute.event_id' ),
'order' => array ( 'Attribute.event_id ASC' ),
));
foreach ( $events as $k => $event ) {
$this -> Event -> read ( null , $event [ 'Attribute' ][ 'event_id' ]);
$this -> Event -> set ( 'attribute_count' , $event [ 0 ][ 'attribute_count' ]);
$this -> Event -> save ();
}
$this -> Flash -> success ( __ ( 'All done. attribute_count generated from scratch for ' . ( isset ( $k ) ? $k : 'no' ) . ' events.' ));
$this -> redirect ( array ( 'controller' => 'pages' , 'action' => 'display' , 'administration' ));
}
2021-01-17 20:54:14 +01:00
/**
* @ param array $event
2022-03-26 10:37:40 +01:00
* @ return CakeResponseFile
2021-01-17 20:54:14 +01:00
* @ throws Exception
*/
private function __restResponse ( array $event )
{
$tmpFile = new TmpFileTool ();
if ( $this -> request -> is ( 'json' )) {
App :: uses ( 'JSONConverterTool' , 'Tools' );
2022-03-14 00:30:44 +01:00
if ( $this -> RestResponse -> isAutomaticTool () && empty ( $event [ 'Event' ][ 'protected' ])) {
2021-12-14 22:35:44 +01:00
foreach ( JSONConverterTool :: streamConvert ( $event ) as $part ) {
2021-01-17 20:54:14 +01:00
$tmpFile -> write ( $part );
}
} else {
2021-12-14 22:35:44 +01:00
$tmpFile -> write ( JSONConverterTool :: convert ( $event ));
2021-01-17 20:54:14 +01:00
}
$format = 'json' ;
} elseif ( $this -> request -> is ( 'xml' )) {
App :: uses ( 'XMLConverterTool' , 'Tools' );
$converter = new XMLConverterTool ();
foreach ( $converter -> frameCollection ( $converter -> convert ( $event )) as $chunk ) {
$tmpFile -> write ( $chunk );
}
$format = 'xml' ;
} else {
throw new Exception ( " Invalid format, only JSON or XML is supported. " );
}
return $this -> RestResponse -> viewData ( $tmpFile , $format , false , true );
}
2022-03-13 12:35:58 +01:00
public function protect ( $id )
{
2022-03-26 10:37:40 +01:00
return $this -> __toggleProtect ( $id , true );
2022-03-13 12:35:58 +01:00
}
public function unprotect ( $id )
{
2022-03-26 10:37:40 +01:00
return $this -> __toggleProtect ( $id , false );
2022-03-13 12:35:58 +01:00
}
2022-03-26 10:37:40 +01:00
/**
* @ param string | int $id Event ID or UUID
* @ param bool $protect
* @ return CakeResponse | void
* @ throws Exception
*/
2022-03-13 12:35:58 +01:00
private function __toggleProtect ( $id , $protect )
{
2022-03-26 10:37:40 +01:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
if ( empty ( $event ) || ! $this -> __canModifyEvent ( $event )) {
2022-03-13 12:35:58 +01:00
throw new NotFoundException ( __ ( 'Invalid event' ));
}
if ( $this -> request -> is ( 'post' )) {
$event [ 'Event' ][ 'protected' ] = $protect ;
$event [ 'Event' ][ 'timestamp' ] = time ();
$event [ 'Event' ][ 'published' ] = false ;
if ( $this -> Event -> save ( $event )) {
$message = __ ( 'Event switched to %s mode.' , $protect ? __ ( 'protected' ) : __ ( 'unprotected' ));
if ( $this -> _isRest ()) {
2022-03-26 10:37:40 +01:00
return $this -> RestResponse -> saveSuccessResponse ( 'events' , $protect ? 'protect' : 'unprotect' , $event [ 'Event' ][ 'id' ], false , $message );
2022-03-13 12:35:58 +01:00
} else {
$this -> Flash -> success ( $message );
$this -> redirect ([ 'controller' => 'events' , 'action' => 'view' , $id ]);
}
} else {
$message = __ ( 'Something went wrong - could not switch event to %s mode.' , $protect ? __ ( 'protected' ) : __ ( 'unprotected' ));
if ( $this -> _isRest ()) {
2022-03-26 10:37:40 +01:00
return $this -> RestResponse -> saveFailResponse ( 'Events' , $protect ? 'protect' : 'unprotect' , $event [ 'Event' ][ 'id' ], $message );
2022-03-13 12:35:58 +01:00
} else {
$this -> Flash -> error ( $message );
2022-03-26 10:37:40 +01:00
$this -> redirect ([ 'controller' => 'events' , 'action' => 'view' , $event [ 'Event' ][ 'id' ]]);
2022-03-13 12:35:58 +01:00
}
}
} else {
2022-03-26 10:37:40 +01:00
$this -> set ( 'id' , $event [ 'Event' ][ 'id' ]);
2022-03-13 12:35:58 +01:00
$this -> set ( 'title' , $protect ? __ ( 'Protect event' ) : __ ( 'Remove event protection' ));
$this -> set (
'question' ,
$protect ?
__ ( 'Are you sure you want switch the event to protected mode? The event and its subsequent modifications will be rejected by MISP instances that you synchronise with, unless the hop through which the event is propagated has their signing key in the list of event signing keys.' ) :
__ ( 'Are you sure you want to switch the event to unprotected mode? Unprotected mode is the default behaviour of MISP events, with creation and modification being purely limited by the distribution mechanism and eligible sync users.' )
);
$this -> set ( 'actionName' , $protect ? __ ( 'Switch to protected mode' ) : __ ( 'Remove protected mode' ));
2022-04-28 14:51:21 +02:00
$this -> layout = false ;
2022-03-13 12:35:58 +01:00
$this -> render ( '/genericTemplates/confirm' );
}
}
2022-11-30 16:00:17 +01:00
/**
* @ param array $event
* @ return void
*/
private function __setHighlightedTags ( $event )
{
$this -> loadModel ( 'Taxonomy' );
2022-11-30 15:07:41 +01:00
$highlightedTags = $this -> Taxonomy -> getHighlightedTags ( $this -> Taxonomy -> getHighlightedTaxonomies (), $event [ 'EventTag' ]);
$this -> set ( 'highlightedTags' , $highlightedTags );
}
/**
*
* @ param array $events
* @ return array
*/
private function __attachHighlightedTagsToEvents ( $events )
{
$this -> loadModel ( 'Taxonomy' );
$highlightedTaxonomies = $this -> Taxonomy -> getHighlightedTaxonomies ();
foreach ( $events as $k => $event ) {
$events [ $k ][ 'Event' ][ 'highlightedTags' ] = $this -> Taxonomy -> getHighlightedTags ( $highlightedTaxonomies , $event [ 'EventTag' ]);
}
return $events ;
2022-11-30 16:00:17 +01:00
}
2015-04-10 15:23:53 +02:00
}