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 (
'Security' ,
'Email' ,
'RequestHandler' ,
'IOCImport' ,
);
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' ))
)
);
2019-11-06 21:20:04 +01:00
private $acceptedFilteringNamedParams = array (
'sort' , 'direction' , 'focus' , 'extended' , 'overrideLimit' , 'filterColumnsOverwrite' , 'attributeFilter' , 'extended' , 'page' ,
'searchFor' , 'proposal' , 'correlation' , 'warning' , 'deleted' , 'includeRelatedTags' , 'includeDecayScore' , 'distribution' ,
'taggedAttributes' , 'galaxyAttachedAttributes' , 'objectType' , 'attributeType' , 'focus' , 'extended' , 'overrideLimit' ,
'filterColumnsOverwrite' , 'feed' , 'server' , 'toIDS' , 'sighting' , 'includeSightingdb'
2019-02-13 11:30:05 +01:00
);
2019-02-13 14:59:49 +01:00
public $defaultFilteringRules = array (
'searchFor' => '' ,
'attributeFilter' => 'all' ,
'proposal' => 0 ,
'correlation' => 0 ,
'warning' => 0 ,
2020-11-10 14:30:28 +01: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' => '' ,
'galaxyAttachedAttributes' => ''
);
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
if ( isset ( $this -> params -> query [ 'uuid' ])) {
$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..
if ( ! $this -> _isSiteAdmin () && in_array ( $this -> action , $this -> paginationFunctions )) {
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 ));
}
}
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 )) {
$pieces = explode ( '|' , 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 ) {
$includeConditions [ 'OR' ][] = array ( 'lower(Attribute.value1) LIKE' => $i );
$includeConditions [ 'OR' ][] = array ( 'lower(Attribute.value2) LIKE' => $i );
}
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 ) {
$excludeConditions [ 'OR' ][] = array ( 'lower(Attribute.value1) LIKE' => $e );
$excludeConditions [ 'OR' ][] = array ( 'lower(Attribute.value2) LIKE' => $e );
}
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 ) {
$values [] = '%' . strtolower ( $v ) . '%' ;
}
// 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 ) {
$subconditions [] = array ( 'lower(value1) LIKE' => $v );
$subconditions [] = array ( 'lower(value2) LIKE' => $v );
$subconditions [] = array ( 'lower(Attribute.comment) LIKE' => $v );
}
$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-03-20 20:32:03 +01:00
private function __setIndexFilterConditions ( $passedArgs , & $urlparams )
2018-07-19 11:48:22 +02:00
{
$passedArgsArray = array ();
foreach ( $passedArgs as $k => $v ) {
if ( substr ( $k , 0 , 6 ) === 'search' ) {
if ( ! is_array ( $v )) {
if ( $urlparams != " " ) {
$urlparams .= " / " ;
}
$urlparams .= $k . " : " . $v ;
}
$searchTerm = strtolower ( substr ( $k , 6 ));
switch ( $searchTerm ) {
case 'all' :
if ( ! empty ( $passedArgs [ 'searchall' ])) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.id' => $this -> __quickFilter ( $passedArgs [ 'searchall' ]));
}
break ;
case 'attribute' :
$event_id_arrays = $this -> __filterOnAttributeValue ( $v );
2020-04-14 18:00:43 +02:00
if ( ! empty ( $event_id_arrays [ 0 ])) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.id' => $event_id_arrays [ 0 ]);
2018-07-19 11:48:22 +02:00
}
2020-04-14 18:00:43 +02:00
if ( ! empty ( $event_id_arrays [ 1 ])) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.id !=' => $event_id_arrays [ 1 ]);
2018-07-19 11:48:22 +02:00
}
break ;
case 'published' :
if ( $v == 2 ) {
continue 2 ;
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.' . substr ( $k , 6 ) . ' =' => $v );
break ;
case 'hasproposal' :
if ( $v == 2 ) {
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 ;
}
2020-04-14 18:00:43 +02:00
if ( is_array ( $v )) {
$pieces = $v ;
} else {
$pieces = explode ( '|' , $v );
}
$eventidConditions = array ();
2018-07-19 11:48:22 +02:00
foreach ( $pieces as $piece ) {
$piece = trim ( $piece );
if ( $piece [ 0 ] == '!' ) {
if ( strlen ( $piece ) == 37 ) {
2020-04-14 18:00:43 +02:00
$eventidConditions [ 'NOT' ][ 'uuid' ][] = substr ( $piece , 1 );
2018-07-19 11:48:22 +02:00
} else {
2020-04-14 18:00:43 +02:00
$eventidConditions [ 'NOT' ][ 'id' ][] = substr ( $piece , 1 );
2018-07-19 11:48:22 +02:00
}
} else {
if ( strlen ( $piece ) == 36 ) {
2020-04-14 18:00:43 +02:00
$eventidConditions [ 'OR' ][ 'uuid' ][] = $piece ;
2018-07-19 11:48:22 +02:00
} else {
2020-04-14 18:00:43 +02:00
$eventidConditions [ 'OR' ][ 'id' ][] = $piece ;
2018-07-19 11:48:22 +02:00
}
}
}
2020-04-14 18:00:43 +02:00
foreach ( $eventidConditions as $operator => $conditionForOperator ) {
foreach ( $conditionForOperator as $conditionKey => $conditionValue ) {
$lookupKey = 'Event.' . $conditionKey ;
if ( $operator === 'NOT' ) {
$lookupKey = $lookupKey . ' !=' ;
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( $lookupKey => $conditionValue );
}
}
2018-07-19 11:48:22 +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 ;
}
if ( preg_match ( '/^[0-9]+[mhdw]$/i' , $v )) {
$v = $this -> Event -> resolveTimeDelta ( $v );
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.timestamp >=' => $v );
break ;
case 'publish_timestamp' :
case 'publishtimestamp' :
if ( $v == " " ) {
continue 2 ;
}
if ( is_array ( $v ) && isset ( $v [ 0 ]) && isset ( $v [ 1 ])) {
if ( preg_match ( '/^[0-9]+[mhdw]$/i' , $v [ 0 ])) {
$v [ 0 ] = $this -> Event -> resolveTimeDelta ( $v [ 0 ]);
}
if ( preg_match ( '/^[0-9]+[mhdw]$/i' , $v [ 1 ])) {
$v [ 1 ] = $this -> Event -> resolveTimeDelta ( $v [ 1 ]);
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.publish_timestamp >=' => $v [ 0 ]);
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.publish_timestamp <=' => $v [ 1 ]);
} else {
if ( preg_match ( '/^[0-9]+[mhdw]$/i' , $v )) {
$v = $this -> Event -> resolveTimeDelta ( $v );
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.publish_timestamp >=' => $v );
}
break ;
case 'org' :
if ( $v == " " ) {
continue 2 ;
}
if ( ! Configure :: read ( 'MISP.showorg' )) {
continue 2 ;
}
$orgArray = $this -> Event -> Org -> find ( 'list' , array ( 'fields' => array ( 'Org.name' )));
$orgUuidArray = $this -> Event -> Org -> find ( 'list' , array ( 'fields' => array ( 'Org.uuid' )));
$orgArray = array_map ( 'strtoupper' , $orgArray );
// if the first character is '!', search for NOT LIKE the rest of the string (excluding the '!' itself of course)
2020-03-30 08:56:30 +02:00
if ( ! is_array ( $v )) {
$pieces = explode ( '|' , $v );
} else {
$pieces = $v ;
}
2018-07-19 11:48:22 +02:00
$test = array ();
foreach ( $pieces as $piece ) {
if ( $piece [ 0 ] == '!' ) {
if ( is_numeric ( substr ( $piece , 1 ))) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.orgc_id !=' => substr ( $piece , 1 ));
} else {
if ( Validation :: uuid ( substr ( $piece , 1 ))) {
$org_id = array_search ( substr ( $piece , 1 ), $orgUuidArray );
} else {
$org_id = array_search ( strtoupper ( substr ( $piece , 1 )), $orgArray );
}
if ( $org_id ) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.orgc_id !=' => $org_id );
}
}
} else {
if ( is_numeric ( $piece )) {
$test [ 'OR' ][] = array ( 'Event.orgc_id' => array ( 'Event.orgc_id' => $piece ));
} else {
if ( Validation :: uuid ( $piece )) {
$org_id = array_search ( $piece , $orgUuidArray );
} else {
$org_id = array_search ( strtoupper ( $piece ), $orgArray );
}
if ( $org_id ) {
$test [ 'OR' ][] = array ( 'Event.orgc_id' => $org_id );
} else {
$test [ 'OR' ][] = array ( 'Event.orgc_id' => - 1 );
}
}
}
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = $test ;
break ;
case 'sharinggroup' :
$pieces = explode ( '|' , $v );
$test = array ();
foreach ( $pieces as $piece ) {
if ( $piece [ 0 ] == '!' ) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.sharing_group_id !=' => substr ( $piece , 1 ));
} else {
$test [ 'OR' ][] = array ( 'Event.sharing_group_id' => $piece );
}
}
if ( ! empty ( $test )) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = $test ;
}
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 ) {
if ( $piece [ 0 ] == '!' ) {
2020-12-23 12:50:19 +01:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'lower(Event.info) NOT LIKE' => '%' . strtolower ( substr ( $piece , 1 )) . '%' );
2018-07-19 11:48:22 +02:00
} else {
2020-12-23 12:50:19 +01:00
$test [ 'OR' ][] = array ( 'lower(Event.info) LIKE' => '%' . strtolower ( $piece ) . '%' );
2018-07-19 11:48:22 +02:00
}
}
$this -> paginate [ 'conditions' ][ 'AND' ][] = $test ;
break ;
case 'tag' :
case 'tags' :
if ( ! $v || ! Configure :: read ( 'MISP.tagging' ) || $v === 0 ) {
continue 2 ;
}
if ( ! is_array ( $v )) {
$pieces = explode ( '|' , $v );
} else {
$pieces = $v ;
}
$filterString = " " ;
$expectOR = false ;
$setOR = false ;
2020-09-12 11:54:49 +02:00
$tagRules = [];
2018-07-19 11:48:22 +02:00
foreach ( $pieces as $piece ) {
if ( $piece [ 0 ] == '!' ) {
if ( is_numeric ( substr ( $piece , 1 ))) {
$conditions = array ( 'OR' => array ( 'Tag.id' => substr ( $piece , 1 )));
} else {
$conditions = array ( 'OR' => array ( 'Tag.name' => substr ( $piece , 1 )));
}
$tagName = $this -> Event -> EventTag -> Tag -> find ( 'first' , array (
'conditions' => $conditions ,
'fields' => array ( 'id' , 'name' ),
'recursive' => - 1 ,
));
if ( empty ( $tagName )) {
if ( $filterString != " " ) {
$filterString .= " | " ;
}
$filterString .= '!' . $piece ;
continue ;
}
2020-12-23 12:50:19 +01:00
$block = $this -> Event -> EventTag -> find ( 'column' , array (
'conditions' => array ( 'EventTag.tag_id' => $tagName [ 'Tag' ][ 'id' ]),
'fields' => [ 'EventTag.event_id' ],
2018-07-19 11:48:22 +02:00
));
if ( ! empty ( $block )) {
2020-12-23 12:50:19 +01:00
$sqlSubQuery = 'Event.id NOT IN (' . implode ( " , " , $block ) . ')' ;
$tagRules [ 'AND' ][] = $sqlSubQuery ;
2018-07-19 11:48:22 +02:00
}
if ( $filterString != " " ) {
$filterString .= " | " ;
}
$filterString .= '!' . ( isset ( $tagName [ 'Tag' ][ 'name' ]) ? $tagName [ 'Tag' ][ 'name' ] : $piece );
} else {
$expectOR = true ;
if ( is_numeric ( $piece )) {
$conditions = array ( 'OR' => array ( 'Tag.id' => $piece ));
} else {
$conditions = array ( 'OR' => array ( 'Tag.name' => $piece ));
}
$tagName = $this -> Event -> EventTag -> Tag -> find ( 'first' , array (
'conditions' => $conditions ,
'fields' => array ( 'id' , 'name' ),
'recursive' => - 1 ,
));
if ( empty ( $tagName )) {
if ( $filterString != " " ) {
$filterString .= " | " ;
}
$filterString .= $piece ;
continue ;
}
2020-12-23 12:50:19 +01:00
$allow = $this -> Event -> EventTag -> find ( 'column' , array (
'conditions' => array ( 'EventTag.tag_id' => $tagName [ 'Tag' ][ 'id' ]),
'fields' => [ 'EventTag.event_id' ],
2018-07-19 11:48:22 +02:00
));
if ( ! empty ( $allow )) {
2020-12-23 12:50:19 +01:00
$setOR = true ;
$sqlSubQuery = 'Event.id IN (' . implode ( " , " , $allow ) . ')' ;
$tagRules [ 'OR' ][] = $sqlSubQuery ;
2018-07-19 11:48:22 +02:00
}
if ( $filterString != " " ) {
$filterString .= " | " ;
}
$filterString .= isset ( $tagName [ 'Tag' ][ 'name' ]) ? $tagName [ 'Tag' ][ 'name' ] : $piece ;
}
}
2020-09-12 11:54:49 +02:00
$this -> paginate [ 'conditions' ][ 'AND' ][] = $tagRules ;
2018-07-19 11:48:22 +02:00
// 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:
if ( $expectOR && ! $setOR ) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.id' => - 1 );
}
$v = $filterString ;
break ;
case 'email' :
if ( $v == " " || ( strtolower ( $this -> Auth -> user ( 'email' )) !== strtolower ( trim ( $v )) && ! $this -> _isSiteAdmin ())) {
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 ) {
if ( $piece [ 0 ] == '!' ) {
$users = $this -> Event -> User -> find ( 'list' , array (
'recursive' => - 1 ,
'fields' => array ( 'User.email' ),
'conditions' => array ( 'lower(User.email) LIKE' => '%' . strtolower ( substr ( $piece , 1 )) . '%' )
));
if ( ! empty ( $users )) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = array ( 'Event.user_id !=' => array_keys ( $users ));
}
} else {
$users = $this -> Event -> User -> find ( 'list' , array (
'recursive' => - 1 ,
'fields' => array ( 'User.email' ),
'conditions' => array ( 'lower(User.email) LIKE' => '%' . strtolower ( $piece ) . '%' )
));
if ( ! empty ( $users )) {
$test [ 'OR' ][] = array ( 'Event.user_id' => array_keys ( $users ));
}
}
}
if ( ! empty ( $test )) {
$this -> paginate [ 'conditions' ][ 'AND' ][] = $test ;
}
break ;
case 'distribution' :
case 'analysis' :
case 'threatlevel' :
if ( $v == " " ) {
continue 2 ;
}
$terms = array ();
$filterString = " " ;
$searchTermInternal = $searchTerm ;
if ( $searchTerm == 'threatlevel' ) {
$searchTermInternal = 'threat_level_id' ;
2021-03-30 09:38:41 +02:00
$terms = $this -> Event -> ThreatLevel -> listThreatLevels ();
2018-07-19 11:48:22 +02:00
} elseif ( $searchTerm == 'analysis' ) {
$terms = $this -> Event -> analysisLevels ;
} else {
$terms = $this -> Event -> distributionLevels ;
}
2020-11-20 10:36:20 +01:00
if ( is_array ( $v )) {
$pieces = $v ;
} else {
$pieces = explode ( '|' , $v );
}
2018-07-19 11:48:22 +02:00
$test = array ();
foreach ( $pieces as $piece ) {
if ( $filterString != " " ) {
$filterString .= '|' ;
}
if ( $piece [ 0 ] == '!' ) {
$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 ;
2019-07-08 11:39:41 +02:00
case 'minimal' :
2020-09-29 08:05:13 +02:00
$tableName = $this -> Event -> EventReport -> table ;
$eventReportQuery = sprintf ( 'EXISTS (SELECT id, deleted FROM %s WHERE %s.event_id = Event.id and %s.deleted = 0)' , $tableName , $tableName , $tableName );
$this -> paginate [ 'conditions' ][ 'AND' ][] = [
'OR' => [
2020-10-05 09:49:56 +02:00
[ 'Event.attribute_count >' => 0 ],
2020-09-29 08:05:13 +02:00
[ $eventReportQuery ]
]
];
2019-07-08 11:39:41 +02:00
break ;
2018-07-19 11:48:22 +02:00
default :
continue 2 ;
break ;
}
$passedArgsArray [ $searchTerm ] = $v ;
}
}
2019-08-02 14:38:28 +02:00
return $passedArgsArray ;
}
public function index ()
{
// list the events
$urlparams = " " ;
$overrideAbleParams = array ( 'all' , 'attribute' , 'published' , 'eventid' , 'datefrom' , 'dateuntil' , 'org' , 'eventinfo' , 'tag' , 'tags' , 'distribution' , 'sharinggroup' , 'analysis' , 'threatlevel' , 'email' , 'hasproposal' , 'timestamp' , 'publishtimestamp' , 'publish_timestamp' , 'minimal' );
$paginationParams = array ( 'limit' , 'page' , 'sort' , 'direction' , 'order' );
$passedArgs = $this -> passedArgs ;
if ( isset ( $this -> request -> data )) {
if ( isset ( $this -> request -> data [ 'request' ])) {
$this -> request -> data = $this -> request -> data [ 'request' ];
}
foreach ( $this -> request -> data as $k => $v ) {
if ( substr ( $k , 0 , 6 ) === 'search' && in_array ( strtolower ( substr ( $k , 6 )), $overrideAbleParams )) {
unset ( $this -> request -> data [ $k ]);
$this -> request -> data [ strtolower ( substr ( $k , 6 ))] = $v ;
} else if ( in_array ( strtolower ( $k ), $overrideAbleParams )) {
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
$passedArgsArray = $this -> __setIndexFilterConditions ( $passedArgs , $urlparams );
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 ()) {
$rules = array ();
$fieldNames = array_keys ( $this -> Event -> getColumnTypes ());
$directions = array ( 'ASC' , 'DESC' );
if ( isset ( $passedArgs [ 'sort' ]) && in_array ( $passedArgs [ 'sort' ], $fieldNames )) {
if ( isset ( $passedArgs [ 'direction' ]) && in_array ( strtoupper ( $passedArgs [ 'direction' ]), $directions )) {
$rules [ 'order' ] = array ( 'Event.' . $passedArgs [ 'sort' ] => $passedArgs [ 'direction' ]);
} else {
$rules [ 'order' ] = array ( 'Event.' . $passedArgs [ 'sort' ] => 'ASC' );
}
}
$rules [ 'contain' ] = $this -> paginate [ 'contain' ];
if ( isset ( $this -> paginate [ 'conditions' ])) {
$rules [ 'conditions' ] = $this -> paginate [ 'conditions' ];
}
2021-01-16 23:54:52 +01:00
$minimal = ! empty ( $passedArgs [ 'searchminimal' ]) || ! empty ( $passedArgs [ 'minimal' ]);
if ( $minimal ) {
2018-07-19 11:48:22 +02:00
$rules [ 'recursive' ] = - 1 ;
2019-11-22 21:53:51 +01:00
$rules [ 'fields' ] = array ( 'id' , 'timestamp' , 'sighting_timestamp' , 'published' , 'uuid' );
2019-09-06 10:59:48 +02:00
$rules [ 'contain' ] = array ( 'Orgc.uuid' );
2021-01-17 13:27:20 +01:00
} else {
$rules [ 'contain' ][] = 'EventTag' ;
2018-07-19 11:48:22 +02:00
}
2019-03-05 15:11:49 +01:00
$paginationRules = array ( 'page' , 'limit' , 'sort' , 'direction' , 'order' );
foreach ( $paginationRules as $paginationRule ) {
if ( isset ( $passedArgs [ $paginationRule ])) {
$rules [ $paginationRule ] = $passedArgs [ $paginationRule ];
}
}
2021-01-16 23:54:52 +01:00
2018-07-19 11:48:22 +02:00
if ( empty ( $rules [ 'limit' ])) {
$events = array ();
$i = 1 ;
$rules [ 'limit' ] = 20000 ;
2021-01-16 23:54:52 +01:00
while ( true ) {
2018-07-19 11:48:22 +02:00
$rules [ 'page' ] = $i ;
$temp = $this -> Event -> find ( 'all' , $rules );
2021-01-16 23:54:52 +01:00
$resultCount = count ( $temp );
if ( $resultCount !== 0 ) {
2018-07-19 11:48:22 +02:00
$events = array_merge ( $events , $temp );
2021-01-16 23:54:52 +01:00
}
if ( $resultCount < $rules [ 'limit' ]) {
break ;
2018-07-19 11:48:22 +02:00
}
$i += 1 ;
}
2021-01-17 13:27:20 +01:00
$absolute_total = count ( $events );
2018-07-19 11:48:22 +02:00
} else {
2021-01-16 23:54:52 +01:00
$counting_rules = $rules ;
unset ( $counting_rules [ 'limit' ]);
unset ( $counting_rules [ 'page' ]);
$absolute_total = $this -> Event -> find ( 'count' , $counting_rules );
2021-01-17 13:27:20 +01:00
$events = $absolute_total === 0 ? [] : $this -> Event -> find ( 'all' , $rules );
2018-07-19 11:48:22 +02:00
}
2021-01-16 23:54:52 +01:00
if ( ! $minimal ) {
2021-01-17 13:27:20 +01:00
$tagIds = [];
foreach ( array_column ( $events , 'EventTag' ) as $eventTags ) {
foreach ( array_column ( $eventTags , 'tag_id' ) as $tagId ) {
$tagIds [ $tagId ] = true ;
2018-07-19 11:48:22 +02:00
}
2021-01-17 13:27:20 +01:00
}
if ( ! empty ( $tagIds )) {
$tags = $this -> Event -> EventTag -> Tag -> find ( 'all' , [
'conditions' => [
'Tag.id' => array_keys ( $tagIds ),
'Tag.exportable' => 1 ,
],
2018-07-19 11:48:22 +02:00
'recursive' => - 1 ,
2021-01-17 13:27:20 +01:00
'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
2018-07-19 11:48:22 +02:00
} else {
2021-01-17 13:27:20 +01:00
$events [ $k ][ 'EventTag' ][ $k2 ][ 'Tag' ] = $tags [ $et [ 'tag_id' ]];
2018-07-19 11:48:22 +02:00
}
}
2021-05-21 10:17:18 +02:00
$events [ $k ][ 'EventTag' ] = array_values ( $events [ $k ][ 'EventTag' ]);
2018-07-19 11:48:22 +02:00
}
2021-02-24 16:52:44 +01:00
$events = $this -> GalaxyCluster -> attachClustersToEventIndex ( $this -> Auth -> user (), $events , false );
2018-07-19 11:48:22 +02:00
}
2018-12-12 19:24:12 +01:00
foreach ( $events as $key => $event ) {
2021-01-16 23:54:52 +01:00
if ( empty ( $event [ 'SharingGroup' ][ 'name' ])) {
unset ( $event [ 'SharingGroup' ]);
}
$temp = $event [ 'Event' ];
2018-12-12 19:24:12 +01:00
$temp [ 'Org' ] = $event [ 'Org' ];
$temp [ 'Orgc' ] = $event [ 'Orgc' ];
unset ( $temp [ 'user_id' ]);
$rearrangeObjects = array ( 'GalaxyCluster' , 'EventTag' , 'SharingGroup' );
foreach ( $rearrangeObjects as $ro ) {
if ( isset ( $event [ $ro ])) {
$temp [ $ro ] = $event [ $ro ];
}
}
$events [ $key ] = $temp ;
}
if ( $this -> response -> type () === 'application/xml' ) {
$events = array ( 'Event' => $events );
}
2018-07-19 11:48:22 +02:00
} else {
foreach ( $events as $key => $event ) {
2019-09-06 10:59:48 +02:00
$event [ 'Event' ][ 'orgc_uuid' ] = $event [ 'Orgc' ][ 'uuid' ];
2018-07-19 11:48:22 +02:00
$events [ $key ] = $event [ 'Event' ];
}
}
2021-01-17 13:27:20 +01:00
return $this -> RestResponse -> viewData ( $events , $this -> response -> type (), false , false , false , [ 'X-Result-Count' => $absolute_total ]);
2018-07-19 11:48:22 +02:00
}
2021-01-17 10:50:43 +01:00
$this -> paginate [ 'contain' ][ 'ThreatLevel' ] = [
'fields' => array ( 'ThreatLevel.name' )
];
$this -> paginate [ 'contain' ][] = 'EventTag' ;
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-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
2018-11-23 14:11:33 +01:00
if ( $this -> params [ 'ext' ] === 'csv' ) {
2021-03-20 11:40:41 +01:00
$events = $this -> __attachInfoToEvents ([ 'tags' ], $events );
2018-11-23 14:11:33 +01:00
App :: uses ( 'CsvExport' , 'Export' );
$export = new CsvExport ();
return $this -> RestResponse -> viewData ( $export -> eventIndex ( $events ), 'csv' );
}
2018-07-19 11:48:22 +02: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 );
2019-03-12 10:46:46 +01: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-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' ;
}
if ( Configure :: read ( 'MISP.showSightingsCountOnIndex' )) {
$possibleColumns [] = 'sightings' ;
}
if ( Configure :: read ( 'MISP.showProposalsCountOnIndex' )) {
$possibleColumns [] = 'proposals' ;
}
2021-05-07 14:09:34 +02:00
if ( Configure :: read ( 'MISP.showEventReportCountOnIndex' )) {
$possibleColumns [] = 'report_count' ;
}
2021-03-20 11:40:41 +01:00
if ( Configure :: read ( 'MISP.showDiscussionsCountOnIndex' )) {
$possibleColumns [] = 'discussion' ;
}
if ( $this -> _isSiteAdmin ()) {
$possibleColumns [] = 'creator_user' ;
}
$userEnabledColumns = $this -> User -> UserSetting -> getValueForUser ( $this -> Auth -> user ()[ 'id' ], 'event_index_hide_columns' );
if ( $userEnabledColumns === null ) {
$userEnabledColumns = [];
}
$enabledColumns = array_diff ( $possibleColumns , $userEnabledColumns );
return [ $possibleColumns , $enabledColumns ];
}
private function __attachInfoToEvents ( array $columns , array $events )
{
$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 );
}
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 );
}
if ( in_array ( 'discussion' , $columns , true )) {
$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 ()),
'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 ,
);
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' ),
];
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 );
$this -> layout = 'ajax' ;
}
2020-10-06 09:56:43 +02:00
/**
2018-07-19 11:48:22 +02:00
* Search for a value on an attribute level for a specific field .
2020-10-06 09:56:43 +02:00
*
* @ param array $attribute An attribute
* @ param array $fields List of keys in attribute to search in
* @ param string $searchValue Values to search ( '|' is the separator )
* @ return bool Returns true on match
2018-07-19 11:48:22 +02:00
*/
private function __valueInFieldAttribute ( $attribute , $fields , $searchValue )
{
2020-10-06 09:56:43 +02:00
$searchParts = explode ( '|' , mb_strtolower ( $searchValue ));
foreach ( $fields as $field ) {
if ( strpos ( $field , 'Tag' ) === 0 ) {
if ( empty ( $attribute [ 'AttributeTag' ])) {
continue ;
}
$fieldValues = Hash :: extract ( $attribute , 'AttributeTag.{n}.' . $field );
foreach ( $fieldValues as $fieldValue ) {
$fieldValue = mb_strtolower ( $fieldValue );
foreach ( $searchParts as $s ) {
if ( strpos ( $fieldValue , $s ) !== false ) {
return true ;
2018-07-19 11:48:22 +02:00
}
}
}
} else {
2020-10-06 09:56:43 +02:00
$fieldValue = isset ( $attribute [ $field ]) ? $attribute [ $field ] : null ;
if ( empty ( $fieldValue )) {
continue ;
}
$fieldValue = mb_strtolower ( $fieldValue );
foreach ( $searchParts as $s ) {
if ( strpos ( $fieldValue , $s ) !== false ) {
return true ;
2018-07-19 11:48:22 +02:00
}
}
}
}
return false ;
}
public function viewEventAttributes ( $id , $all = false )
{
2019-01-31 14:39:24 +01:00
$filterData = array (
'request' => $this -> request ,
2019-02-13 11:30:05 +01:00
'paramArray' => $this -> acceptedFilteringNamedParams ,
2019-01-31 14:39:24 +01:00
'named_params' => $this -> params [ 'named' ]
);
$exception = false ;
$filters = $this -> _harvestParameters ( $filterData , $exception );
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 ,
'includeEventCorrelations' => false ,
'noEventReports' => true , // event reports for view are loaded dynamically
'noSightings' => true ,
];
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 ];
2020-11-10 14:30:28 +01:00
} elseif ( $filters [ 'deleted' ] == 0 ) { // not-deleted only
$conditions [ 'deleted' ] = 1 ;
} else { // only deleted
$conditions [ 'deleted' ] = 0 ;
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-02-13 11:30:05 +01:00
if ( ! isset ( $filters [ 'includeServerCorrelations' ])) {
$conditions [ 'includeServerCorrelations' ] = 1 ;
} else {
$conditions [ 'includeServerCorrelations' ] = $filters [ 'includeServerCorrelations' ];
}
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
if ( $this -> _isSiteAdmin () && isset ( $this -> params [ 'named' ][ 'viewAs' ])) {
$user = $this -> User -> getAuthUser ( $this -> params [ 'named' ][ 'viewAs' ]);
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 ];
2019-04-16 14:14:51 +02:00
$attributeTagsName = $this -> Event -> Attribute -> AttributeTag -> extractAttributeTagsNameFromEvent ( $event , 'both' );
$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
$emptyEvent = ( empty ( $event [ 'Object' ]) && empty ( $event [ 'Attribute' ]));
$this -> set ( 'emptyEvent' , $emptyEvent );
// remove galaxies tags
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 ) {
2020-05-23 17:30:00 +02:00
$this -> Event -> Attribute -> removeGalaxyClusterTags ( $event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ]);
2019-11-04 14:55:43 +01:00
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
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 14:55:43 +01:00
}
2019-11-04 11:54:22 +01:00
$event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ][ 'tagConflicts' ] = $tagConflicts ;
2018-07-19 11:48:22 +02:00
}
}
}
foreach ( $event [ 'Attribute' ] as $k => $attribute ) {
2020-05-23 17:30:00 +02:00
$this -> Event -> Attribute -> removeGalaxyClusterTags ( $event [ 'Attribute' ][ $k ]);
2019-11-04 14:55:43 +01:00
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
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 14:55:43 +01:00
}
2019-11-04 11:54:22 +01:00
$event [ 'Attribute' ][ $k ][ 'tagConflicts' ] = $tagConflicts ;
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
}
2020-11-11 09:00:50 +01:00
$this -> loadModel ( 'Sighting' );
$sightingsData = $this -> Sighting -> eventsStatistic ([ $event ], $this -> Auth -> 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 );
$dataForView = array (
2020-05-23 17:16:30 +02:00
'Attribute' => array ( 'attrDescriptions' => 'fieldDescriptions' , 'distributionDescriptions' => 'distributionDescriptions' , 'distributionLevels' => 'distributionLevels' , 'shortDist' => 'shortDist' ),
'Event' => array ( 'eventDescriptions' => 'fieldDescriptions' , 'analysisDescriptions' => 'analysisDescriptions' , 'analysisLevels' => 'analysisLevels' )
2018-07-19 11:48:22 +02:00
);
foreach ( $dataForView as $m => $variables ) {
if ( $m === 'Event' ) {
$currentModel = $this -> Event ;
} elseif ( $m === 'Attribute' ) {
$currentModel = $this -> Event -> Attribute ;
}
2020-05-23 17:16:30 +02:00
foreach ( $variables as $alias => $variable ) {
$this -> set ( $alias , $currentModel -> { $variable });
2018-07-19 11:48:22 +02:00
}
}
if ( Configure :: read ( 'Plugin.Enrichment_services_enable' )) {
$this -> loadModel ( 'Module' );
$modules = $this -> Module -> getEnabledModules ( $this -> Auth -> user ());
if ( ! empty ( $modules ) && is_array ( $modules )) {
foreach ( $modules as $k => $v ) {
if ( isset ( $v [ 'restrict' ])) {
if ( ! $this -> _isSiteAdmin () && $v [ 'restrict' ] != $this -> Auth -> user ( 'org_id' )) {
unset ( $modules [ $k ]);
}
}
}
}
$this -> set ( 'modules' , $modules );
}
if ( Configure :: read ( 'Plugin.Cortex_services_enable' )) {
$this -> loadModel ( 'Module' );
$cortex_modules = $this -> Module -> getEnabledModules ( $this -> Auth -> user (), false , 'Cortex' );
$this -> set ( 'cortex_modules' , $cortex_modules );
}
2019-05-31 09:19:51 +02:00
$deleted = 0 ;
if ( isset ( $filters [ 'deleted' ])) {
2021-06-04 15:03:12 +02:00
$deleted = $filters [ 'deleted' ] > 0 ? 1 : 0 ;
2019-05-31 09:19:51 +02:00
}
2019-11-26 12:34:22 +01:00
$this -> set ( 'includeSightingdb' , ( ! empty ( $filters [ 'includeSightingdb' ]) && Configure :: read ( 'Plugin.Sightings_sighting_db_enable' )));
2019-05-31 09:19:51 +02:00
$this -> set ( 'deleted' , $deleted );
2018-07-19 11:48:22 +02:00
$this -> set ( 'typeGroups' , array_keys ( $this -> Event -> Attribute -> typeGroupings ));
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' ]);
2019-02-13 14:59:49 +01:00
$this -> set ( 'defaultFilteringRules' , $this -> defaultFilteringRules );
2020-07-27 22:00:31 +02:00
$orgTable = $this -> Event -> Orgc -> find ( 'list' , array (
'fields' => array ( 'Orgc.id' , 'Orgc.name' )
));
$this -> set ( 'orgTable' , $orgTable );
2018-07-19 11:48:22 +02:00
$this -> disableCache ();
$this -> layout = 'ajax' ;
$uriArray = explode ( '/' , $this -> params -> here );
foreach ( $uriArray as $k => $v ) {
if ( strpos ( $v , ':' )) {
$temp = explode ( ':' , $v );
if ( $temp [ 0 ] == 'focus' ) {
unset ( $uriArray [ $k ]);
}
}
$this -> params -> here = implode ( '/' , $uriArray );
}
2019-11-06 21:20:04 +01:00
if ( ! empty ( $filters [ 'includeSightingdb' ]) && Configure :: read ( 'Plugin.Sightings_sighting_db_enable' )) {
$this -> set ( 'sightingdbs' , $this -> Sightingdb -> getSightingdbList ( $this -> Auth -> user ()));
}
2018-07-19 11:48:22 +02:00
$this -> set ( 'currentUri' , $this -> params -> here );
2018-11-23 14:11:33 +01:00
$this -> layout = false ;
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 ,
2019-02-13 11:30:05 +01:00
'paramArray' => $this -> acceptedFilteringNamedParams ,
2019-01-31 14:39:24 +01:00
'named_params' => $this -> params [ 'named' ]
);
$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 );
$attributeCount = isset ( $event [ 'Attribute' ]) ? count ( $event [ 'Attribute' ]) : 0 ;
2019-02-26 16:33:37 +01:00
$objectCount = isset ( $event [ 'Object' ]) ? count ( $event [ 'Object' ]) : 0 ;
2019-04-04 15:00:05 +02:00
$oldest_timestamp = false ;
2018-07-19 11:48:22 +02:00
if ( ! empty ( $event [ 'Object' ])) {
foreach ( $event [ 'Object' ] as $k => $object ) {
if ( ! empty ( $object [ 'Attribute' ])) {
2019-04-04 15:00:05 +02:00
foreach ( $object [ 'Attribute' ] as $attribute ) {
2020-01-14 09:08:04 +01:00
if ( $oldest_timestamp == false || $oldest_timestamp > $attribute [ 'timestamp' ]) {
2019-04-04 15:00:05 +02:00
$oldest_timestamp = $attribute [ 'timestamp' ];
}
}
2018-07-19 11:48:22 +02:00
$attributeCount += count ( $object [ 'Attribute' ]);
}
}
}
$this -> set ( 'attribute_count' , $attributeCount );
2019-02-26 16:33:37 +01:00
$this -> set ( 'object_count' , $objectCount );
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 );
2021-03-10 18:27:19 +01:00
if ( $user [ 'Role' ][ 'perm_publish' ] && $event [ 'Event' ][ 'orgc_id' ] == $user [ 'org_id' ]) {
2018-07-19 11:48:22 +02:00
$proposalStatus = false ;
if ( isset ( $event [ 'ShadowAttribute' ]) && ! empty ( $event [ 'ShadowAttribute' ])) {
$proposalStatus = true ;
}
if ( ! $proposalStatus && ! empty ( $event [ 'Attribute' ])) {
foreach ( $event [ 'Attribute' ] as $temp ) {
if ( isset ( $temp [ 'ShadowAttribute' ]) && ! empty ( $temp [ 'ShadowAttribute' ])) {
$proposalStatus = true ;
}
}
}
$mess = $this -> Session -> read ( 'Message' );
if ( $proposalStatus && empty ( $mess )) {
$this -> Flash -> info ( 'This event has active proposals for you to accept or discard.' );
}
}
// 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 );
// set data for the view, the event is already set in view()
$dataForView = array (
'Attribute' => array ( 'attrDescriptions' => 'fieldDescriptions' , 'distributionDescriptions' => 'distributionDescriptions' , 'distributionLevels' => 'distributionLevels' , 'shortDist' => 'shortDist' ),
'Event' => array ( 'eventDescriptions' => 'fieldDescriptions' , 'analysisDescriptions' => 'analysisDescriptions' , 'analysisLevels' => 'analysisLevels' )
);
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 ) {
$relatedEventCorrelationCount [ $key ] = count ( $relatedEventCorrelationCount [ $key ]);
}
2018-07-19 11:48:22 +02:00
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 });
}
}
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 );
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 ) {
2020-01-14 09:08:04 +01:00
if ( $oldest_timestamp == false || $oldest_timestamp > $attribute [ 'timestamp' ]) {
2019-04-04 15:00:05 +02:00
$oldest_timestamp = $attribute [ 'timestamp' ];
}
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 ]);
2019-11-04 14:55:43 +01:00
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
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
$event [ 'Attribute' ][ $k ][ 'tagConflicts' ] = $tagConflicts ;
2018-07-19 11:48:22 +02:00
}
2019-04-16 14:14:51 +02:00
$attributeTagsName = $this -> Event -> Attribute -> AttributeTag -> extractAttributeTagsNameFromEvent ( $event , 'both' );
$this -> set ( 'attributeTags' , array_values ( $attributeTagsName [ 'tags' ]));
$this -> set ( 'attributeClusters' , array_values ( $attributeTagsName [ 'clusters' ]));
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' ])) {
foreach ( $object [ 'Attribute' ] as $k2 => $attribute ) {
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 ]);
2019-11-04 14:55:43 +01:00
$tagConflicts = $this -> Taxonomy -> checkIfTagInconsistencies ( $attribute [ 'AttributeTag' ]);
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
$event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ][ 'tagConflicts' ] = $tagConflicts ;
2018-07-19 11:48:22 +02:00
}
}
}
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 );
2020-07-05 16:22:01 +02:00
$today = strtotime ( date ( 'Y-m-d' , time ()));
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
}
if ( Configure :: read ( 'Plugin.Enrichment_services_enable' )) {
$this -> loadModel ( 'Module' );
2021-03-10 18:27:19 +01:00
$modules = $this -> Module -> getEnabledModules ( $user );
2018-07-19 11:48:22 +02:00
if ( is_array ( $modules )) {
foreach ( $modules as $k => $v ) {
if ( isset ( $v [ 'restrict' ])) {
2021-03-10 18:27:19 +01:00
if ( $this -> _isSiteAdmin () && $v [ 'restrict' ] != $user [ 'org_id' ]) {
2018-07-19 11:48:22 +02:00
unset ( $modules [ $k ]);
}
}
}
}
$this -> set ( 'modules' , $modules );
}
if ( Configure :: read ( 'Plugin.Cortex_services_enable' )) {
$this -> loadModel ( 'Module' );
2021-03-10 18:27:19 +01:00
$cortex_modules = $this -> Module -> getEnabledModules ( $user , false , 'Cortex' );
2018-07-19 11:48:22 +02:00
$this -> set ( 'cortex_modules' , $cortex_modules );
}
$this -> set ( 'typeGroups' , array_keys ( $this -> Event -> Attribute -> typeGroupings ));
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
}
}
$orgTable = $this -> Event -> Orgc -> find ( 'list' , array (
'fields' => array ( 'Orgc.id' , 'Orgc.name' )
));
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
}
$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 );
2019-04-04 15:00:05 +02:00
$this -> set ( 'oldest_timestamp' , $oldest_timestamp );
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 ( 'orgTable' , $orgTable );
$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-13 14:59:49 +01:00
$this -> set ( 'defaultFilteringRules' , $this -> defaultFilteringRules );
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' ]));
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' ));
}
2020-08-18 21:59:25 +02:00
if ( $this -> _isRest ()) {
2020-11-25 08:17:51 +01:00
$conditions [ 'includeAttachments' ] = isset ( $this -> params [ 'named' ][ 'includeAttachments' ]) ? $this -> params [ 'named' ][ '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 ;
2019-01-31 16:22:11 +01:00
if ( isset ( $this -> params [ 'named' ][ 'deleted' ])) {
2019-09-13 15:34:12 +02:00
$deleted = $this -> params [ 'named' ][ 'deleted' ];
}
if ( isset ( $this -> request -> data [ 'deleted' ])) {
$deleted = $this -> request -> data [ 'deleted' ];
}
if ( isset ( $deleted )) {
2019-06-04 13:54:47 +02:00
// workaround for old instances trying to pull events with both deleted / non deleted data
2019-09-13 15:34:12 +02:00
if (( $this -> userRole [ 'perm_sync' ] && $this -> _isRest () && ! $this -> userRole [ 'perm_site_admin' ]) && $deleted == 1 ) {
2019-06-04 13:54:47 +02:00
$conditions [ 'deleted' ] = array ( 0 , 1 );
} else {
2021-06-04 15:03:12 +02:00
if ( is_array ( $deleted )) {
$conditions [ 'deleted' ] = $deleted ;
} else if ( $deleted == 1 ) { // both
2020-11-10 14:30:28 +01:00
$conditions [ 'deleted' ] = [ 0 , 1 ];
} elseif ( $deleted == 0 ) { // not-deleted only
2020-11-09 17:11:11 +01:00
$conditions [ 'deleted' ] = 0 ;
2020-11-10 14:30:28 +01:00
} else { // only deleted
2020-11-09 17:11:11 +01:00
$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
}
2019-02-15 16:28:04 +01:00
if ( isset ( $this -> params [ 'named' ][ 'toIDS' ]) && $this -> params [ 'named' ][ 'toIDS' ] != 0 ) {
$conditions [ 'to_ids' ] = $this -> params [ 'named' ][ 'toIDS' ] == 2 ? 0 : 1 ;
}
2018-11-23 14:11:33 +01:00
if ( isset ( $this -> params [ 'named' ][ 'includeRelatedTags' ]) && $this -> params [ 'named' ][ '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
}
2019-09-12 11:40:23 +02:00
if ( ! empty ( $this -> params [ 'named' ][ 'includeDecayScore' ])) {
2019-08-12 16:34:26 +02:00
$conditions [ 'includeDecayScore' ] = 1 ;
}
2018-07-19 11:48:22 +02:00
if ( isset ( $this -> params [ 'named' ][ 'public' ]) && $this -> params [ 'named' ][ 'public' ]) {
$conditions [ 'distribution' ] = array ( 3 , 5 );
}
if ( ! empty ( $this -> params [ 'named' ][ 'overrideLimit' ]) && ! $this -> _isRest ()) {
$conditions [ 'overrideLimit' ] = 1 ;
}
if ( ! empty ( $this -> params [ 'named' ][ 'excludeGalaxy' ])) {
$conditions [ 'excludeGalaxy' ] = 1 ;
2020-03-12 10:26:09 +01:00
if ( ! empty ( $this -> params [ 'named' ][ 'includeCustomGalaxyCluster' ])) {
$conditions [ 'includeCustomGalaxyCluster' ] = 1 ;
}
2018-07-19 11:48:22 +02:00
}
2020-04-28 10:00:36 +02:00
if ( ! empty ( $this -> params [ 'named' ][ '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 ;
2020-07-16 10:56:32 +02:00
if ( isset ( $this -> params [ 'named' ][ 'excludeLocalTags' ])) {
$conditions [ 'excludeLocalTags' ] = $this -> params [ 'named' ][ 'excludeLocalTags' ];
}
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 ;
2019-06-18 10:51:16 +02:00
} else if ( ! empty ( $this -> params [ 'named' ][ 'includeGranularCorrelations' ])) {
$conditions [ 'includeGranularCorrelations' ] = 1 ;
2018-11-23 14:11:33 +01:00
}
2019-01-18 16:15:22 +01:00
if ( ! isset ( $this -> params [ 'named' ][ 'includeServerCorrelations' ])) {
$conditions [ 'includeServerCorrelations' ] = 1 ;
if ( $this -> _isRest ()) {
$conditions [ 'includeServerCorrelations' ] = 0 ;
}
} else {
$conditions [ 'includeServerCorrelations' ] = $this -> params [ 'named' ][ 'includeServerCorrelations' ];
}
2021-03-10 18:27:19 +01:00
// Site admin can view event as different user
if ( $this -> _isSiteAdmin () && isset ( $this -> params [ 'named' ][ 'viewAs' ])) {
$user = $this -> User -> getAuthUser ( $this -> params [ 'named' ][ 'viewAs' ]);
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
if ( ! empty ( $this -> params [ 'named' ][ 'includeGranularCorrelations' ]) && ! empty ( $event [ 'RelatedAttribute' ])) {
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' ];
2019-01-31 14:39:24 +01:00
if ( isset ( $this -> params [ 'named' ][ 'searchFor' ]) && $this -> params [ 'named' ][ 'searchFor' ] !== '' ) {
2019-02-01 11:35:01 +01:00
$this -> __applyQueryString ( $event , $this -> params [ 'named' ][ 'searchFor' ]);
2019-01-31 14:39:24 +01:00
}
2019-02-13 14:59:49 +01:00
if ( isset ( $this -> params [ 'named' ][ 'taggedAttributes' ]) && $this -> params [ 'named' ][ 'taggedAttributes' ] !== '' ) {
$this -> __applyQueryString ( $event , $this -> params [ 'named' ][ 'taggedAttributes' ], 'Tag.name' );
}
if ( isset ( $this -> params [ 'named' ][ 'galaxyAttachedAttributes' ]) && $this -> params [ 'named' ][ 'galaxyAttachedAttributes' ] !== '' ) {
$this -> __applyQueryString ( $event , $this -> params [ 'named' ][ 'galaxyAttachedAttributes' ], 'Tag.name' );
}
2019-01-31 14:39:24 +01:00
2018-07-19 11:48:22 +02:00
if ( $this -> _isRest ()) {
2021-01-17 20:54:14 +01:00
return $this -> __restResponse ( $event );
}
2020-10-04 13:16:33 +02:00
2021-06-04 14:46:08 +02:00
$this -> set ( 'deleted' , isset ( $deleted ) ? ( $deleted > 0 ? 1 : 0 ) : 0 );
2021-01-17 20:54:14 +01:00
$this -> set ( 'includeRelatedTags' , ( ! empty ( $this -> params [ 'named' ][ 'includeRelatedTags' ])) ? 1 : 0 );
$this -> set ( 'includeDecayScore' , ( ! empty ( $this -> params [ 'named' ][ 'includeDecayScore' ])) ? 1 : 0 );
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 ));
}
2020-10-06 09:56:43 +02:00
private function __applyQueryString ( & $event , $searchFor , $filterColumnsOverwrite = false )
{
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 ));
$validFilters = array ( 'id' , 'uuid' , 'value' , 'comment' , 'type' , 'category' , 'Tag.name' );
foreach ( $filterValue as $k => $v ) {
if ( ! in_array ( $v , $validFilters )) {
unset ( $filterValue [ $k ]);
}
}
}
// search in all attributes
foreach ( $event [ 'Attribute' ] as $k => $attribute ) {
if ( ! $this -> __valueInFieldAttribute ( $attribute , $filterValue , $searchFor )) {
unset ( $event [ 'Attribute' ][ $k ]);
}
}
$event [ 'Attribute' ] = array_values ( $event [ 'Attribute' ]);
// search in all attributes
foreach ( $event [ 'ShadowAttribute' ] as $k => $proposals ) {
if ( ! $this -> __valueInFieldAttribute ( $proposals , $filterValue , $searchFor )) {
unset ( $event [ 'ShadowAttribute' ][ $k ]);
}
}
$event [ 'ShadowAttribute' ] = array_values ( $event [ 'ShadowAttribute' ]);
// search for all attributes in object
foreach ( $event [ 'Object' ] as $k => $object ) {
2021-02-15 15:17:00 +01:00
if ( $this -> __valueInFieldAttribute ( $object , [ 'id' , 'uuid' , 'name' , 'comment' ], $searchFor )) {
continue ;
}
2019-01-31 14:39:24 +01:00
foreach ( $object [ 'Attribute' ] as $k2 => $attribute ) {
if ( ! $this -> __valueInFieldAttribute ( $attribute , $filterValue , $searchFor )) {
unset ( $event [ 'Object' ][ $k ][ 'Attribute' ][ $k2 ]);
}
}
2020-10-06 09:56:43 +02:00
if ( empty ( $event [ 'Object' ][ $k ][ 'Attribute' ])) {
2019-01-31 14:39:24 +01:00
// remove object if empty
unset ( $event [ 'Object' ][ $k ]);
} else {
$event [ 'Object' ][ $k ][ 'Attribute' ] = array_values ( $event [ 'Object' ][ $k ][ 'Attribute' ]);
}
}
$event [ 'Object' ] = array_values ( $event [ 'Object' ]);
}
2019-02-01 11:35:01 +01:00
// look in the parameters if we are doing advanced filtering or not
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 ) {
2019-02-13 14:59:49 +01:00
if ( isset ( $this -> defaultFilteringRules [ $k ]) && $this -> defaultFilteringRules [ $k ] != $v ) {
$activeRules [ $k ] = 1 ;
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 __removeChildren ( & $pivot , $id )
{
if ( $pivot [ 'id' ] == $id ) {
$pivot [ 'children' ] = array ();
} else {
foreach ( $pivot [ 'children' ] as $k => $v ) {
$this -> __removeChildren ( $v , $id );
}
}
}
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 ()
{
if ( ! $this -> userRole [ 'perm_add' ]) {
2020-07-20 10:10:47 +02:00
throw new MethodNotAllowedException ( __ ( 'You do not have permissions to create events.' ));
2018-07-19 11:48:22 +02:00
}
$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' );
}
if ( ! empty ( $this -> data )) {
if ( ! isset ( $this -> request -> data [ 'Event' ][ 'distribution' ])) {
$this -> request -> data [ 'Event' ][ 'distribution' ] = Configure :: read ( 'MISP.default_event_distribution' ) ? Configure :: read ( 'MISP.default_event_distribution' ) : 0 ;
}
if ( ! isset ( $this -> request -> data [ 'Event' ][ 'analysis' ])) {
$this -> request -> data [ 'Event' ][ 'analysis' ] = 0 ;
}
if ( ! isset ( $this -> request -> data [ 'Event' ][ 'threat_level_id' ])) {
$this -> request -> data [ 'Event' ][ 'threat_level_id' ] = Configure :: read ( 'MISP.default_event_threat_level' ) ? Configure :: read ( 'MISP.default_event_threat_level' ) : 4 ;
}
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 );
if ( $add === true && ! is_numeric ( $add )) {
if ( $this -> _isRest ()) {
if ( $add === 'blocked' ) {
2020-09-01 12:56:35 +02:00
throw new ForbiddenException ( __ ( 'Event blocked by local blocklist.' ));
2018-07-19 11:48:22 +02:00
}
// 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.' ));
}
// # 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
$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-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
}
2019-02-10 13:08:12 +01:00
if ( ! $this -> _isRest ()) {
$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
$this -> set ( 'published' , $this -> Event -> data [ 'Event' ][ 'published' ]);
}
public function add_misp_export ()
{
if ( ! $this -> userRole [ 'perm_modify' ]) {
throw new UnauthorizedException ( __ ( 'You do not have permission to do that.' ));
}
if ( $this -> request -> is ( 'post' )) {
$results = array ();
if ( ! empty ( $this -> data )) {
$ext = '' ;
if ( isset ( $this -> data [ 'Event' ][ 'submittedfile' ])) {
$ext = pathinfo ( $this -> data [ 'Event' ][ 'submittedfile' ][ 'name' ], PATHINFO_EXTENSION );
}
if ( isset ( $this -> data [ 'Event' ][ 'submittedfile' ]) && ( strtolower ( $ext ) != 'xml' && strtolower ( $ext ) != 'json' ) && $this -> data [ 'Event' ][ 'submittedfile' ][ 'size' ] > 0 &&
is_uploaded_file ( $this -> data [ 'Event' ][ 'submittedfile' ][ 'tmp_name' ])) {
$log = ClassRegistry :: init ( 'Log' );
// #TODO Think about whether we want to Localize Log entries.
$log -> createLogEntry ( $this -> Auth -> user (), 'file_upload' , 'Event' , 0 , 'MISP export file upload failed' , 'File details: ' . json_encode ( $this -> data [ 'Event' ][ 'submittedfile' ]));
$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).' ));
}
if ( isset ( $this -> data [ 'Event' ][ 'submittedfile' ])) {
2020-09-26 13:02:19 +02:00
$isXml = strtolower ( $ext ) === 'xml' ;
App :: uses ( 'FileAccessTool' , 'Tools' );
$data = ( new FileAccessTool ()) -> readFromFile ( $this -> data [ 'Event' ][ 'submittedfile' ][ 'tmp_name' ], $this -> data [ 'Event' ][ 'submittedfile' ][ 'size' ]);
$takeOwnership = Configure :: read ( 'MISP.take_ownership_xml_import' )
&& ( isset ( $this -> data [ 'Event' ][ 'takeownership' ]) && $this -> data [ 'Event' ][ 'takeownership' ] == 1 );
2020-09-26 13:06:39 +02:00
try {
$results = $this -> Event -> addMISPExportFile ( $this -> Auth -> user (), $data , $isXml , $takeOwnership , $this -> data [ 'Event' ][ 'publish' ]);
} catch ( Exception $e ) {
$filename = $this -> data [ 'Event' ][ 'submittedfile' ][ 'name' ];
$this -> log ( " Exception during processing MISP file import ' $filename ': { $e -> getMessage () } " );
$this -> Flash -> error ( __ ( 'Could not process MISP export file. Probably file content is invalid.' ));
$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' );
}
}
public function upload_stix ( $stix_version = '1' )
{
if ( ! $this -> userRole [ 'perm_modify' ]) {
throw new UnauthorizedException ( __ ( 'You do not have permission to do that.' ));
}
2020-01-22 15:39:06 +01:00
$scriptDir = APP . 'files' . DS . 'scripts' ;
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'post' )) {
if ( $this -> _isRest ()) {
$randomFileName = $this -> Event -> generateRandomFileName ();
2020-01-22 15:39:06 +01:00
$tempFile = new File ( $scriptDir . DS . 'tmp' . DS . $randomFileName , true , 0644 );
2018-07-19 11:48:22 +02:00
$tempFile -> write ( $this -> request -> input ());
$tempFile -> close ();
2019-09-28 02:35:22 +02:00
$result = $this -> Event -> upload_stix (
$this -> Auth -> user (),
2020-01-22 15:39:06 +01:00
$scriptDir ,
2019-09-28 02:35:22 +02:00
$randomFileName ,
$stix_version ,
2019-12-19 16:17:05 +01:00
'uploaded_stix_file.' . ( $stix_version == '1' ? 'xml' : 'json' ),
false
2019-09-28 02:35:22 +02:00
);
2018-07-19 11:48:22 +02:00
if ( is_array ( $result )) {
return $this -> RestResponse -> saveSuccessResponse ( 'Events' , 'upload_stix' , false , $this -> response -> type (), 'STIX document imported, event\'s created: ' . implode ( ', ' , $result ) . '.' );
} elseif ( is_numeric ( $result )) {
$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' ])) {
$randomFileName = $this -> Event -> generateRandomFileName ();
2020-01-22 15:39:06 +01:00
move_uploaded_file ( $this -> data [ 'Event' ][ 'stix' ][ 'tmp_name' ], $scriptDir . DS . 'tmp' . DS . $randomFileName );
2019-09-28 02:35:22 +02:00
$result = $this -> Event -> upload_stix (
$this -> Auth -> user (),
2020-01-22 15:39:06 +01:00
$scriptDir ,
2019-09-28 02:35:22 +02:00
$randomFileName ,
$stix_version ,
$original_file ,
$this -> data [ 'Event' ][ 'publish' ]
);
2018-07-19 11:48:22 +02:00
if ( is_array ( $result )) {
$this -> Flash -> success ( __ ( 'STIX document imported, event\'s created: ' . implode ( ', ' , $result ) . '.' ));
$this -> redirect ( array ( 'action' => 'index' ));
} elseif ( is_numeric ( $result )) {
$this -> Flash -> success ( __ ( 'STIX document imported.' ));
$this -> redirect ( array ( 'action' => 'view' , $result ));
} else {
$this -> Flash -> error ( __ ( 'Could not import STIX document: ' . $result ));
}
} 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
}
}
}
if ( $stix_version == 2 ) {
$stix_version = '2.x JSON' ;
} else {
$stix_version = '1.x XML' ;
}
$this -> set ( 'stix_version' , $stix_version );
}
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 ) {
$this -> Event -> Attribute -> captureAttribute ( $attribute , $target_id , $this -> Auth -> user (), false , $this -> Log );
2018-07-19 11:48:22 +02:00
}
2020-07-06 16:43:18 +02:00
foreach ( $results [ 'results' ][ 'Object' ] as $object ) {
$this -> Event -> Object -> captureObject ( $object , $target_id , $this -> Auth -> user (), $this -> Log );
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
}
}
public function edit ( $id = null )
{
if ( $this -> request -> is ( 'get' ) && $this -> _isRest ()) {
return $this -> RestResponse -> describe ( 'Events' , 'edit' , false , $this -> response -> type ());
}
2020-12-05 14:26:38 +01:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id , [ 'contain' => [ 'Orgc' ]]);
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
}
}
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 );
}
$result = $this -> Event -> _edit ( $this -> request -> data , $this -> Auth -> user (), $id );
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 ;
$date = new DateTime ();
$this -> request -> data [ 'Event' ][ 'timestamp' ] = $date -> getTimestamp ();
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 )
{
2019-08-11 21:22:38 +02:00
if ( Validation :: uuid ( $id )) {
$temp = $this -> Event -> find ( 'first' , array ( 'recursive' => - 1 , 'fields' => array ( 'Event.id' ), 'conditions' => array ( 'Event.uuid' => $id )));
if ( empty ( $temp )) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$id = $temp [ 'Event' ][ 'id' ];
}
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'post' ) || $this -> request -> is ( 'put' ) || $this -> request -> is ( 'delete' )) {
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 )) {
if ( is_numeric ( $idList )) {
$idList = array ( $idList );
} else {
$idList = json_decode ( $idList , true );
}
}
if ( ! is_array ( $idList ) || empty ( $idList )) {
throw new NotFoundException ( __ ( 'Invalid input.' ));
}
} else {
$idList = array ( $id );
}
$fails = array ();
$successes = array ();
foreach ( $idList as $eid ) {
if ( ! is_numeric ( $eid )) {
continue ;
}
$event = $this -> Event -> find ( 'first' , array (
'conditions' => array ( 'Event.id' => $eid ),
2020-07-20 10:10:47 +02:00
'fields' => array ( 'Event.orgc_id' , 'Event.id' , 'Event.user_id' ),
2018-07-19 11:48:22 +02:00
'recursive' => - 1
));
if ( empty ( $event )) {
$fails [] = $eid ;
} else {
2020-07-20 10:10:47 +02:00
if ( ! $this -> __canModifyEvent ( $event )) {
$fails [] = $eid ;
continue ;
2018-07-19 11:48:22 +02:00
}
$this -> Event -> insertLock ( $this -> Auth -> user (), $event [ 'Event' ][ 'id' ]);
if ( $this -> Event -> quickDelete ( $event )) {
$successes [] = $eid ;
} else {
$fails [] = $eid ;
}
}
}
$message = '' ;
if ( count ( $idList ) == 1 ) {
if ( ! empty ( $successes )) {
$message = 'Event deleted.' ;
} else {
$message = 'Event was not deleted.' ;
}
} else {
if ( ! empty ( $successes )) {
$message .= count ( $successes ) . ' event(s) deleted.' ;
}
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 {
if ( is_numeric ( $id )) {
$eventList = array ( $id );
} else {
$eventList = json_decode ( $id , true );
}
$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 )) {
// redirect to the view event page
2021-07-07 15:25:33 +02:00
$message = __ ( 'Event published without alerts' );
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 {
// update the DB to set the published flag
// for background jobs, this should be done already
$event [ 'Event' ][ 'published' ] = 1 ;
$event [ 'Event' ][ 'publish_timestamp' ] = time ();
2021-07-07 15:25:33 +02:00
$this -> Event -> save ( $event , true , [ 'id' , 'published' , 'publish_timestamp' , 'info' ]); // info field is required because of SysLogLogableBehavior
2018-07-19 11:48:22 +02:00
$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 {
$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 {
2021-07-07 15:25:33 +02:00
$this -> set ( 'id' , $event [ 'Event' ][ 'id' ]);
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
}
} 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 )) {
// redirect to the view event page
2021-07-07 15:25:33 +02:00
$message = __ ( 'Published but no email sent given GnuPG is not configured.' );
2018-07-19 11:48:22 +02:00
$errors [ 'GnuPG' ] = 'GnuPG not set up.' ;
} 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 {
2021-07-07 15:25:33 +02:00
$this -> set ( 'id' , $event [ 'Event' ][ 'id' ]);
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 ,
'fields' => [ 'id' , 'info' , 'publish_timestamp' , 'orgc_id' ],
]);
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Invalid event.' ));
}
if ( ! $this -> _isSiteAdmin () && $this -> Auth -> user ( 'org_id' ) !== $event [ 'Event' ][ 'orgc_id' ]) {
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' ]]);
}
}
}
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
if ( ! $this -> userRole [ 'perm_auth' ]) {
$this -> redirect ( array ( 'controller' => 'events' , 'action' => 'index' ));
}
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' );
$rpzSettings = $this -> Server -> retrieveCurrentSettings ( 'Plugin' , 'RPZ_' );
$this -> set ( 'rpzSettings' , $rpzSettings );
$this -> set ( 'hashTypes' , array_keys ( $this -> Event -> Attribute -> hashTypes ));
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.
if ( Configure :: read ( 'MISP.background_jobs' ) && ! Configure :: read ( 'MISP.disable_cached_exports' )) {
$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' );
foreach ( $this -> Event -> export_types as $k => $type ) {
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' ;
$this -> Event -> export_types [ $k ][ 'recommendation' ] = 0 ;
} else {
$lastModified = 'N/A' ;
$this -> Event -> export_types [ $k ][ 'recommendation' ] = 1 ;
}
} else {
$filesize = $file -> size ();
$filesize_unit_index = 0 ;
while ( $filesize > 1024 ) {
$filesize_unit_index ++ ;
$filesize = $filesize / 1024 ;
}
$this -> Event -> export_types [ $k ][ 'filesize' ] = round ( $filesize , 1 ) . $filesize_units [ $filesize_unit_index ];
$fileChange = $file -> lastChange ();
$lastModified = $this -> __timeDifference ( $now , $fileChange );
if ( empty ( $tempNewestEvent ) || $fileChange > $tempNewestEvent [ 'Event' ][ 'timestamp' ]) {
if ( empty ( $tempNewestEvent )) {
$lastModified = 'No valid events' ;
}
$this -> Event -> export_types [ $k ][ 'recommendation' ] = 0 ;
} else {
$this -> Event -> export_types [ $k ][ 'recommendation' ] = 1 ;
}
}
$this -> Event -> export_types [ $k ][ 'lastModified' ] = $lastModified ;
if ( ! empty ( $job )) {
$this -> Event -> export_types [ $k ][ 'job_id' ] = $job [ 'Job' ][ 'id' ];
$this -> Event -> export_types [ $k ][ 'progress' ] = $job [ 'Job' ][ 'progress' ];
} else {
$this -> Event -> export_types [ $k ][ 'job_id' ] = - 1 ;
$this -> Event -> export_types [ $k ][ 'progress' ] = 0 ;
}
}
}
2019-03-25 16:26:29 +01:00
$this -> loadModel ( 'Attribute' );
$this -> set ( 'sigTypes' , array_keys ( $this -> Attribute -> typeDefinitions ));
$this -> set ( 'export_types' , $this -> Event -> export_types );
2018-07-19 11:48:22 +02:00
}
public function downloadExport ( $type , $extra = null )
{
if ( Configure :: read ( 'MISP.disable_cached_exports' )) {
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 ;
}
$this -> response -> type ( $this -> Event -> export_types [ $type ][ 'extension' ]);
$path = 'tmp/cached_exports/' . $type . DS . 'misp.' . strtolower ( $this -> Event -> export_types [ $type ][ 'type' ]) . $extra . '.' . $org . $this -> Event -> export_types [ $type ][ 'extension' ];
$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 " ;
}
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.' ));
}
App :: uses ( 'FileAccessTool' , 'Tools' );
$fileAccessTool = new FileAccessTool ();
$iocData = $fileAccessTool -> readFromFile ( $this -> data [ 'Event' ][ 'submittedioc' ][ 'tmp_name' ], $this -> data [ 'Event' ][ 'submittedioc' ][ 'size' ]);
2019-02-10 13:08:12 +01:00
// write
$attachments_dir = Configure :: read ( 'MISP.attachments_dir' );
2018-07-19 11:48:22 +02:00
if ( empty ( $attachments_dir )) {
2019-02-10 13:08:12 +01:00
$attachments_dir = $this -> Event -> getDefaultAttachments_dir ();
}
$rootDir = $attachments_dir . DS . $id . DS ;
2018-07-19 11:48:22 +02:00
App :: uses ( 'Folder' , 'Utility' );
$dir = new Folder ( $rootDir . 'ioc' , true );
$destPath = $rootDir . 'ioc' ;
App :: uses ( 'File' , 'Utility' );
$iocFile = new File ( $destPath . DS . $this -> data [ 'Event' ][ 'submittedioc' ][ 'name' ]);
$result = $iocFile -> write ( $iocData );
if ( ! $result ) {
2020-02-27 02:43:04 +01:00
$this -> Flash -> error ( __ ( 'Problem with writing the IoC file. Please report to site admin.' ));
2018-07-19 11:48:22 +02:00
}
// open the xml
$xmlFilePath = $destPath . DS . $this -> data [ 'Event' ][ 'submittedioc' ][ 'name' ];
$xmlFileData = $fileAccessTool -> readFromFile ( $xmlFilePath , $this -> data [ 'Event' ][ 'submittedioc' ][ 'size' ]);
// 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
$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' ,
'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' ),
'Attribute' => array ( 'event_id' , 'category' , 'type' , 'value' , 'value1' , 'value2' , 'to_ids' , 'uuid' , 'distribution' , 'timestamp' , 'comment' )
);
// 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' ) {
$user = $this -> checkAuthUser ( $key );
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 (
'request' => false ,
'Event' => false ,
'tag_id' => 'tag' ,
'event_id' => 'event' ,
'id' => 'event'
);
$RearrangeTool = new RequestRearrangeTool ();
$this -> request -> data = $RearrangeTool -> rearrangeArray ( $this -> request -> data , $rearrangeRules );
if ( $id === false ) {
$id = $this -> request -> data [ 'event' ];
}
2019-03-20 11:21:40 +01:00
$this -> Event -> recursive = - 1 ;
$event = $this -> Event -> read ( array (), $id );
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
}
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 {
2020-08-15 15:48:39 +02:00
$conditions = array ( 'LOWER(Tag.name)' => strtolower ( trim ( $tag_id )));
if ( ! $this -> _isSiteAdmin ()) {
$conditions [ 'Tag.org_id' ] = array ( '0' , $this -> Auth -> user ( 'org_id' ));
$conditions [ 'Tag.user_id' ] = array ( '0' , $this -> Auth -> user ( 'id' ));
}
2019-03-20 11:21:40 +01:00
$tag = $this -> Event -> EventTag -> Tag -> find ( 'first' , array ( 'recursive' => - 1 , 'conditions' => $conditions ));
if ( empty ( $tag )) {
return new CakeResponse ( array ( 'body' => json_encode ( array ( 'saved' => false , 'errors' => 'Invalid Tag.' )), 'status' => 200 , 'type' => 'json' ));
}
$tag_id = $tag [ 'Tag' ][ 'id' ];
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 ) {
2020-08-15 15:48:39 +02:00
$conditions = [ 'Tag.id' => $tag_id ];
if ( ! $this -> _isSiteAdmin ()) {
$conditions [ 'Tag.org_id' ] = array ( '0' , $this -> Auth -> user ( 'org_id' ));
$conditions [ 'Tag.user_id' ] = array ( '0' , $this -> Auth -> user ( '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 ,
'fields' => array ( 'Tag.name' )
));
2020-08-15 15:48:39 +02:00
if ( ! $tag ) {
$fails [ $tag_id ] = __ ( 'Tag not found.' );
continue ;
}
2019-03-20 11:21:40 +01:00
$found = $this -> Event -> EventTag -> find ( 'first' , array (
'conditions' => array (
'event_id' => $id ,
'tag_id' => $tag_id
),
'recursive' => - 1 ,
));
if ( ! empty ( $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 ;
}
2019-11-04 11:54:22 +01:00
$tagsOnEvent = $this -> Event -> EventTag -> find ( 'all' , array (
'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
));
2019-11-04 15:46:53 +01:00
$exclusiveTestPassed = $this -> Taxonomy -> checkIfNewTagIsAllowedByTaxonomy ( $tag [ 'Tag' ][ 'name' ], Hash :: extract ( $tagsOnEvent , '{n}.Tag.name' ));
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 ;
}
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 ) {
$event [ 'Event' ][ 'published' ] = 0 ;
$date = new DateTime ();
$event [ 'Event' ][ 'timestamp' ] = $date -> getTimestamp ();
$this -> Event -> save ( $event );
}
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 (
'request' => false ,
'Event' => false ,
'tag_id' => 'tag' ,
'event_id' => 'event' ,
'id' => 'event'
);
$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' ])) {
$event [ 'Event' ][ 'published' ] = 0 ;
$date = new DateTime ();
$event [ 'Event' ][ 'timestamp' ] = $date -> getTimestamp ();
$this -> Event -> save ( $event );
}
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 )
{
2020-07-20 10:10:47 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id );
if ( empty ( $event )) {
throw new MethodNotAllowedException ( __ ( 'Invalid event.' ));
}
$this -> set ( 'event_id' , $event [ 'Event' ][ 'id' ]);
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'get' )) {
$this -> layout = 'ajax' ;
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
}
if ( $this -> request -> is ( 'post' )) {
App :: uses ( 'ComplexTypeTool' , 'Tools' );
$complexTypeTool = new ComplexTypeTool ();
$this -> loadModel ( 'Warninglist' );
$complexTypeTool -> setTLDs ( $this -> Warninglist -> fetchTLDLists ());
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' ];
}
$resultArray = $complexTypeTool -> checkComplexRouter ( $this -> request -> data [ 'Attribute' ][ 'value' ], 'freetext' );
foreach ( $resultArray as $key => $r ) {
$temp = array ();
foreach ( $r [ 'types' ] as $type ) {
$temp [ $type ] = $type ;
}
$resultArray [ $key ][ 'types' ] = $temp ;
}
if ( $this -> _isRest ()) {
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
$resultArray = array_values ( $resultArray );
$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 );
foreach ( $typeCategoryMapping as $k => $v ) {
$typeCategoryMapping [ $k ] = array_values ( $v );
}
$this -> set ( 'mapping' , $typeCategoryMapping );
$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' ));
2018-07-19 11:48:22 +02:00
$this -> loadModel ( 'Warninglist' );
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 ) {
if ( Configure :: read ( 'MISP.default_attribute_distribution' ) == 'event' ) {
$distribution = 5 ;
} else {
$distribution = Configure :: read ( 'MISP.default_attribute_distribution' );
}
} 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 )
{
2020-10-11 12:04:47 +02:00
if ( ! $this -> request -> is ( 'post' )) {
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.' ));
}
2020-10-11 12:04:47 +02:00
$this -> Event -> insertLock ( $this -> Auth -> user (), $id );
$attributes = json_decode ( $this -> request -> data [ 'Attribute' ][ 'JsonObject' ], true );
$default_comment = $this -> request -> data [ 'Attribute' ][ 'default_comment' ];
$proposals = ! $this -> __canModifyEvent ( $event ) || ( isset ( $this -> request -> data [ 'Attribute' ][ 'force' ]) && $this -> request -> data [ 'Attribute' ][ 'force' ]);
$flashMessage = $this -> Event -> processFreeTextDataRouter ( $this -> Auth -> user (), $attributes , $id , $default_comment , $proposals );
$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 ()
{
if ( $this -> request -> is ( 'post' )) {
$incomingIDs = array ();
$incomingEvents = array ();
foreach ( $this -> request -> data as $event ) {
$incomingIDs [] = $event [ 'Event' ][ 'uuid' ];
$incomingEvents [ $event [ 'Event' ][ 'uuid' ]] = $event [ 'Event' ][ 'timestamp' ];
}
$events = $this -> Event -> find ( 'all' , array (
'conditions' => array ( 'Event.uuid' => $incomingIDs ),
'recursive' => - 1 ,
'fields' => array ( 'Event.uuid' , 'Event.timestamp' , 'Event.locked' ),
));
2021-01-17 21:51:22 +01:00
foreach ( $events as $event ) {
if ( $event [ 'Event' ][ 'timestamp' ] >= $incomingEvents [ $event [ 'Event' ][ 'uuid' ]]) {
unset ( $incomingEvents [ $event [ 'Event' ][ 'uuid' ]]);
2018-07-19 11:48:22 +02:00
continue ;
}
2021-01-17 21:51:22 +01:00
if ( $event [ 'Event' ][ 'locked' ] == 0 ) {
unset ( $incomingEvents [ $event [ 'Event' ][ 'uuid' ]]);
2018-07-19 11:48:22 +02:00
}
}
2021-01-17 21:51:22 +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
// #TODO i18n
$exports = array (
'xml' => array (
2020-12-07 22:30:16 +01:00
'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
),
'json' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/events/restSearch/json/eventid:' . $id . '.json' ,
'text' => 'MISP JSON (metadata + all attributes)' ,
'requiresPublished' => false ,
'checkbox' => true ,
'checkbox_text' => 'Encode Attachments' ,
'checkbox_set' => $this -> baseurl . '/events/restSearch/json/withAttachments:1/eventid:' . $id . '.json' ,
'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' ,
'text' => 'OpenIOC (all indicators marked to IDS)' ,
'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 ,
'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 ,
'text' => 'CSV with additional context' ,
'requiresPublished' => false ,
'checkbox' => true ,
'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 ,
'text' => 'STIX 1 XML (metadata + all attributes)' ,
'requiresPublished' => false ,
'checkbox' => true ,
'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 ,
'text' => 'STIX 1 JSON (metadata + all attributes)' ,
'requiresPublished' => false ,
'checkbox' => true ,
'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 ,
'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 ,
'text' => 'RPZ Zone file' ,
'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 ,
'text' => 'Download Suricata rules' ,
'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 ,
'text' => 'Download Snort rules' ,
'requiresPublished' => false ,
'checkbox' => false ,
2018-07-19 11:48:22 +02:00
),
'bro' => array (
2020-12-07 22:30:16 +01:00
'url' => $this -> baseurl . '/attributes/bro/download/all/false/' . $id ,
// 'url' => '/attributes/restSearch/returnFormat:bro/published:1||0/eventid:' . $id,
'text' => 'Download Bro rules' ,
'requiresPublished' => false ,
'checkbox' => false
2018-07-19 11:48:22 +02:00
),
'text' => array (
2020-12-07 22:30:16 +01:00
'text' => 'Export all attribute values as a text file' ,
'url' => $this -> baseurl . '/attributes/restSearch/returnFormat:text/published:1||0/eventid:' . $id ,
'requiresPublished' => false ,
'checkbox' => true ,
'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 ,
2018-07-19 11:48:22 +02:00
'text' => 'CSV (event not published, IDS flag ignored)' ,
'requiresPublished' => false ,
'checkbox' => false
);
}
$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' )
{
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 (
'freetext' => array (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/events/freeTextImport/' . $id ,
2020-08-17 17:13:58 +02:00
'text' => __ ( 'Freetext Import' ),
2018-07-19 11:48:22 +02:00
'ajax' => true ,
'target' => 'popover_form'
),
'template' => array (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/templates/templateChoices/' . $id ,
2020-02-27 02:43:04 +01:00
'text' => __ ( 'Populate using a Template' ),
2018-07-19 11:48:22 +02:00
'ajax' => true ,
'target' => 'popover_form'
),
'OpenIOC' => array (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/events/addIOC/' . $id ,
2020-02-27 02:43:04 +01:00
'text' => __ ( 'OpenIOC Import' ),
2018-07-19 11:48:22 +02:00
'ajax' => false ,
),
'ThreatConnect' => array (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/attributes/add_threatconnect/' . $id ,
2020-02-27 02:43:04 +01:00
'text' => __ ( 'ThreatConnect Import' ),
2018-07-19 11:48:22 +02:00
'ajax' => false
2018-11-23 14:22:18 +01:00
),
'Forensic analysis' => array (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/events/upload_analysis_file/' . $id ,
'text' => __ ( '(Experimental) Forensic analysis - Mactime' ),
'ajax' => false ,
2020-08-17 17:13:58 +02:00
)
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 (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/events/importModule/' . $module [ 'name' ] . '/' . $id ,
2018-07-19 11:48:22 +02:00
'text' => Inflector :: humanize ( $module [ 'name' ]),
'ajax' => false
);
}
}
} else {
$imports = array (
'MISP' => array (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/events/add_misp_export' ,
2020-02-27 02:43:04 +01:00
'text' => __ ( 'MISP standard (recommended exchange format - lossless)' ),
2018-07-19 11:48:22 +02:00
'ajax' => false ,
'bold' => true
),
'STIX' => array (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/events/upload_stix' ,
2020-02-27 02:43:04 +01:00
'text' => __ ( 'STIX 1.1.1 format (lossy)' ),
2018-07-19 11:48:22 +02:00
'ajax' => false ,
),
'STIX2' => array (
2020-08-17 15:52:32 +02:00
'url' => $this -> baseurl . '/events/upload_stix/2' ,
2020-02-27 02:43:04 +01:00
'text' => __ ( 'STIX 2.0 format (lossy)' ),
2018-07-19 11:48:22 +02:00
'ajax' => false ,
)
);
}
$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 ) {
$this -> Log -> save ( array (
'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' );
$fileAccessTool = new FileAccessTool ();
foreach ( $data [ 'files' ] as $file ) {
2019-07-08 12:51:37 +02:00
$tmpdir = Configure :: read ( 'MISP.tmpdir' ) ? Configure :: read ( 'MISP.tmpdir' ) : APP . 'tmp' ;
2018-07-19 11:48:22 +02:00
$tmpfile = $fileAccessTool -> createTempFile ( $tmpdir , $prefix = 'MISP_upload' );
$fileAccessTool -> writeToFile ( $tmpfile , base64_decode ( $file [ 'data' ]));
$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 );
}
}
}
$fileAccessTool -> deleteFile ( $tmpfile -> path );
}
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 )
{
2020-12-23 12:49:59 +01:00
// Event data are fetched by 'updateGraph', here we need just metadata.
2018-10-02 07:34:02 +02:00
$event = $this -> Event -> fetchEvent ( $this -> Auth -> user (), array (
2018-11-23 14:11:33 +01:00
'eventid' => $id ,
2020-12-23 12:49:59 +01:00
'metadata' => true ,
2018-11-23 14:11:33 +01:00
));
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
}
$this -> set ( 'event' , $event [ 0 ]);
$this -> set ( 'scope' , 'event' );
$this -> set ( 'id' , $id );
}
/*
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' )
{
$validTools = array ( 'event' , 'galaxy' , 'tag' );
if ( ! in_array ( $type , $validTools )) {
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 ();
$grapher -> construct ( $this -> Event , $this -> Taxonomy , $this -> GalaxyCluster , $this -> Auth -> user (), $data );
$json = $grapher -> buildGraphJson ( $id , $type );
array_walk_recursive ( $json , function ( & $item , $key ) {
if ( ! mb_detect_encoding ( $item , 'utf-8' , true )) {
$item = utf8_encode ( $item );
}
});
$this -> response -> type ( 'json' );
return new CakeResponse ( array ( 'body' => json_encode ( $json ), 'status' => 200 , 'type' => 'json' ));
}
2020-10-14 09:44:33 +02:00
private function genDistributionGraph ( $id , $type = 'event' , $extended = 0 )
{
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
2018-07-19 11:48:22 +02:00
App :: uses ( 'DistributionGraphTool' , 'Tools' );
$grapher = new DistributionGraphTool ();
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
));
$grapher -> construct ( $this -> Event , $servers , $this -> Auth -> user (), $extended );
$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' )
{
$extended = isset ( $this -> params [ 'named' ][ 'extended' ]) ? 1 : 0 ;
$json = $this -> genDistributionGraph ( $id , $type , $extended );
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
}
2019-02-15 09:41:17 +01:00
public function viewGalaxyMatrix ( $scope_id , $galaxy_id , $scope = 'event' , $disable_picking = 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' ) {
$event = $this -> Event -> fetchEvent ( $this -> Auth -> user (), array ( 'eventid' => $eventId , 'metadata' => true ));
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Event not found or you are not authorised to view it.' ));
}
$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' );
}
// expects an attribute ID and the module to be used
public function queryEnrichment ( $attribute_id , $module = false , $type = 'Enrichment' )
{
if ( ! Configure :: read ( 'Plugin.' . $type . '_services_enable' )) {
throw new MethodNotAllowedException ( __ ( '%s services are not enabled.' , $type ));
}
$attribute = $this -> Event -> Attribute -> fetchAttributes ( $this -> Auth -> user (), array ( 'conditions' => array ( 'Attribute.id' => $attribute_id ), 'flatten' => 1 ));
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
$this -> loadModel ( 'Module' );
$enabledModules = $this -> Module -> getEnabledModules ( $this -> Auth -> user (), false , $type );
if ( ! is_array ( $enabledModules ) || empty ( $enabledModules )) {
throw new MethodNotAllowedException ( __ ( 'No valid %s options found for this attribute.' , $type ));
}
2018-07-19 11:48:22 +02:00
if ( $this -> request -> is ( 'ajax' )) {
$modules = array ();
foreach ( $enabledModules [ 'modules' ] as $module ) {
if ( in_array ( $attribute [ 0 ][ 'Attribute' ][ 'type' ], $module [ 'mispattributes' ][ 'input' ])) {
$modules [] = array ( 'name' => $module [ 'name' ], 'description' => $module [ 'meta' ][ 'description' ]);
}
}
foreach ( array ( 'attribute_id' , 'modules' ) as $viewVar ) {
$this -> set ( $viewVar , $$viewVar );
}
$this -> set ( 'type' , $type );
$this -> render ( 'ajax/enrichmentChoice' );
} else {
$options = array ();
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' ) {
$this -> __queryEnrichment ( $attribute , $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 ;
}
2020-10-22 19:42:47 +02:00
$result = $this -> Module -> queryModuleServer ( $data , false , $type );
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 );
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 ;
}
2020-10-22 19:42:47 +02:00
$result = $this -> Module -> queryModuleServer ( $data , false , $type );
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' );
$fileAccessTool = new FileAccessTool ();
$tmpdir = Configure :: read ( 'MISP.tmpdir' ) ? Configure :: read ( 'MISP.tmpdir' ) : '/tmp' ;
$tempFile = $fileAccessTool -> createTempFile ( $tmpdir , $prefix = 'MISP' );
$fileAccessTool -> writeToFile ( $tempFile , $result [ 'data' ]);
$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 );
$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.' ));
}
2020-10-15 19:01:01 +02:00
$resolved_data = $this -> Event -> jsonDecode ( $this -> request -> data [ 'Event' ][ 'JsonObject' ]);
$data = $this -> Event -> 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
}
2018-07-19 11:48:22 +02:00
public function importModule ( $module , $eventId )
{
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' );
$moduleName = $module ;
$module = $this -> Module -> getEnabledModule ( $module , 'Import' );
if ( ! is_array ( $module )) {
throw new MethodNotAllowedException ( $module );
}
if ( ! isset ( $module [ 'mispattributes' ][ 'inputSource' ])) {
$module [ 'mispattributes' ][ 'inputSource' ] = array ( 'paste' );
}
if ( $this -> request -> is ( 'post' )) {
$fail = false ;
$modulePayload = array (
'module' => $module [ 'name' ],
2020-07-20 12:57:45 +02:00
'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' ) {
if ( empty ( $this -> request -> data [ 'Event' ][ 'config' ][ 'header' ]) && $this -> request -> data [ 'Event' ][ 'config' ][ 'has_header' ] === '1' ) {
$this -> request -> data [ 'Event' ][ 'config' ][ 'header' ] = ' ' ;
}
2019-09-17 16:02:41 +02:00
if ( empty ( $this -> request -> data [ 'Event' ][ 'config' ][ 'special_delimiter' ])) {
$this -> request -> data [ 'Event' ][ 'config' ][ 'special_delimiter' ] = ' ' ;
}
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 {
$validation = call_user_func_array ( array ( $this -> Module , $this -> Module -> configTypes [ $config [ 'type' ]][ 'validation' ]), array ( $this -> request -> data [ 'Event' ][ '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' ])) {
$fail = preg_match ( $config [ 'regex' ], $this -> request -> data [ 'Event' ][ 'config' ][ $configName ]) ? false : ucfirst ( $configName ) . ': ' . 'Invalid setting' . ( $config [ 'errorMessage' ] ? ' - ' . $config [ 'errorMessage' ] : '' );
if ( ! empty ( $fail )) {
$modulePayload [ 'config' ][ $configName ] = $this -> request -> data [ 'Event' ][ 'config' ][ $configName ];
}
} else {
2018-07-19 11:48:22 +02:00
$modulePayload [ 'config' ][ $configName ] = $this -> request -> data [ 'Event' ][ 'config' ][ $configName ];
}
}
}
}
}
if ( ! $fail ) {
if ( ! empty ( $module [ 'mispattributes' ][ 'inputSource' ])) {
if ( ! isset ( $this -> request -> data [ 'Event' ][ 'source' ])) {
if ( in_array ( 'paste' , $module [ 'mispattributes' ][ 'inputSource' ])) {
$this -> request -> data [ 'Event' ][ 'source' ] = '0' ;
} else {
$this -> request -> data [ 'Event' ][ 'source' ] = '1' ;
}
}
if ( $this -> request -> data [ 'Event' ][ 'source' ] == '1' ) {
if ( isset ( $this -> request -> data [ 'Event' ][ 'data' ])) {
$modulePayload [ 'data' ] = base64_decode ( $this -> request -> data [ 'Event' ][ 'data' ]);
} elseif ( ! isset ( $this -> request -> data [ 'Event' ][ 'fileupload' ]) || empty ( $this -> request -> data [ 'Event' ][ 'fileupload' ])) {
$fail = 'Invalid file upload.' ;
} else {
$fileupload = $this -> request -> data [ 'Event' ][ 'fileupload' ];
$tmpfile = new File ( $fileupload [ 'tmp_name' ]);
if (( isset ( $fileupload [ 'error' ]) && $fileupload [ 'error' ] == 0 ) || ( ! empty ( $fileupload [ 'tmp_name' ]) && $fileupload [ 'tmp_name' ] != 'none' ) && is_uploaded_file ( $tmpfile -> path )) {
$filename = basename ( $fileupload [ 'name' ]);
App :: uses ( 'FileAccessTool' , 'Tools' );
$modulePayload [ 'data' ] = ( new FileAccessTool ()) -> readFromFile ( $fileupload [ 'tmp_name' ], $fileupload [ 'size' ]);
} else {
$fail = 'Invalid file upload.' ;
}
}
} else {
$modulePayload [ 'data' ] = $this -> request -> data [ 'Event' ][ 'paste' ];
}
} 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' ) {
2019-05-02 11:49:17 +02:00
$event = $this -> Event -> handleMispFormatFromModuleResult ( $result );
$event [ 'Event' ] = array ( 'id' => $eventId );
2019-08-19 16:44:49 +02:00
if ( $this -> _isRest ()) {
$this -> Event -> processModuleResultsDataRouter ( $this -> Auth -> user (), $event , $eventId , $importComment );
return $this -> RestResponse -> viewData ( $event , $this -> response -> type ());
}
2019-05-02 11:49:17 +02:00
$this -> set ( 'event' , $event );
$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 );
$render_name = 'resolved_attributes' ;
2018-07-19 11:48:22 +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 );
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
}
}
$this -> set ( 'configTypes' , $this -> Module -> configTypes );
$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 );
2020-07-20 10:10:47 +02:00
$this -> Event -> Attribute -> generateCorrelation ( false , 0 , $event [ 'Event' ][ 'id' ]);
2018-07-19 11:48:22 +02:00
} else {
$event [ 'Event' ][ 'disable_correlation' ] = 1 ;
$this -> Event -> save ( $event );
2020-07-20 10:10:47 +02:00
$this -> Event -> Attribute -> 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 )
{
2020-07-20 12:57:45 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> 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 )
{
if ( empty ( $id )) {
throw new MethodNotAllowedException ( __ ( 'Invalid ID.' ));
}
2020-07-19 16:22:16 +02:00
$event = $this -> Event -> fetchSimpleEvent ( $this -> Auth -> user (), $id , [
'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 ());
} else {
if ( $this -> request -> is ( 'ajax' )) {
$this -> layout = 'ajax' ;
}
$this -> set ( 'analysisLevels' , $this -> Event -> analysisLevels );
$this -> set ( 'validUuid' , Validation :: uuid ( $id ));
$this -> set ( 'id' , $id );
$this -> set ( 'event' , $event );
}
}
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' );
$this -> layout = 'ajax' ;
$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
{
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 ],
'fields' => [ 'Event.orgc_id' , 'Event.timestamp' ],
2018-07-19 11:48:22 +02:00
));
2021-03-19 18:00:21 +01:00
// Return empty response if event not found or user org is not owner
if ( empty ( $event ) || ( $event [ 'Event' ][ 'orgc_id' ] != $this -> Auth -> user ( 'org_id' ) && ! $this -> _isSiteAdmin ())) {
return new CakeResponse ([ 'status' => 204 ]);
}
$user = $this -> Auth -> user ();
$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 )) {
2021-04-30 16:04:33 +02:00
$message = __ ( '<b>Warning</b>: This event view is outdated. Please reload page to see latest changes.' );
2021-03-19 18:00:21 +01:00
$this -> set ( 'class' , 'alert' );
} else if ( $event [ 'Event' ][ 'timestamp' ] > $timestamp ) {
2021-04-30 16:04:33 +02:00
$message = __ ( '<b>Warning</b>: This event view is outdated, because is currently being edited by: %s. Please reload page to see 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.
if ( Validation :: uuid ( $id )) {
$this -> Event -> recursive = - 1 ;
$event = $this -> Event -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => array ( 'Event.uuid' => $id ),
'fields' => array ( 'Event.id' , 'Event.uuid' , 'Event.orgc_id' )
));
if ( $event == null ) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$id = $event [ 'Event' ][ 'id' ];
} elseif ( ! is_numeric ( $id )) {
throw new NotFoundException ( __ ( 'Invalid event' ));
} else {
$event = $this -> Event -> find ( 'first' , array (
'recursive' => - 1 ,
'conditions' => array ( 'Event.id' => $id ),
'fields' => array ( 'Event.id' , 'Event.uuid' , 'Event.orgc_id' )
));
}
if ( empty ( $event )) {
throw new NotFoundException ( __ ( 'Invalid event' ));
}
$response = array ( 'extensions' => array ());
if ( $event [ 'Event' ][ 'orgc_id' ] === $this -> Auth -> user ( 'org_id' )) {
$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 ,
'template_uuid' => '9297982e-be62-4772-a665-c91f5a8d639'
);
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' );
$ObjectResult = $this -> MispObject -> saveObject ( $object , $eventId , " " , " " );
$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' );
2018-11-23 14:52:43 +01:00
$result = $this -> MispObject -> ObjectReference -> captureReference ( $objectRef , $eventId , $this -> Auth -> user (), false );
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' );
2018-11-23 14:52:43 +01:00
$result = $this -> MispObject -> ObjectReference -> captureReference ( $objectRef , $eventId , $this -> Auth -> user (), false );
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 ;
$process_id = CakeResque :: enqueue (
'prio' ,
'EventShell' ,
array ( $function , $jobId , $id ),
true
);
$job -> saveField ( 'process_id' , $process_id );
$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 )
{
$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
/**
* @ param array $event
* @ return CakeResponseTmp
* @ throws Exception
*/
private function __restResponse ( array $event )
{
$tmpFile = new TmpFileTool ();
if ( $this -> request -> is ( 'json' )) {
App :: uses ( 'JSONConverterTool' , 'Tools' );
$converter = new JSONConverterTool ();
if ( $this -> RestResponse -> isAutomaticTool ()) {
foreach ( $converter -> streamConvert ( $event ) as $part ) {
$tmpFile -> write ( $part );
}
} else {
$tmpFile -> write ( $converter -> convert ( $event ));
}
$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 );
}
2015-04-10 15:23:53 +02:00
}