<commit_before><?php
App::uses('AppController', 'Controller');
App::uses('Folder', 'Utility');
App::uses('File', 'Utility');

class ShadowAttributesController extends AppController {

	public $components = array('Acl', 'Security', 'RequestHandler', 'Email');

	public $paginate = array(
			'limit' => 60,
			'maxLimit' => 9999,
		);

	public $helpers = array('Js' => array('Jquery'));

	public function beforeFilter() {
		parent::beforeFilter();
		$this->set('title_for_layout', 'Proposals');
		$this->Security->validatePost = true;

		// convert uuid to id if present in the url, and overwrite id field
		if (isset($this->params->query['uuid'])) {
			$params = array(
					'conditions' => array('ShadowAttribute.uuid' => $this->params->query['uuid']),
					'recursive' => 0,
					'fields' => 'ShadowAttribute.id'
					);
			$result = $this->ShadowAttribute->find('first', $params);
			if (isset($result['ShadowAttribute']) && isset($result['ShadowAttribute']['id'])) {
				$id = $result['ShadowAttribute']['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()) {
			$this->paginate = Set::merge($this->paginate,array(
			'conditions' =>
					array('OR' =>
							array(
								'Event.org =' => $this->Auth->user('org_id'),
								'AND' => array(
									'ShadowAttribute.org =' => $this->Auth->user('org_id'),
									'Event.distribution >' => 0,
									Configure::read('MISP.unpublishedprivate') ? array('Event.published =' => 1) : array(),
								),
							)
			)));
		}
	}

	private function __accept($id) {
		$this->loadModel('Attribute');
		$this->Attribute->Behaviors->detach('SysLogLogable.SysLogLogable');
		$shadow = $this->ShadowAttribute->find(
			'first',
			array(
				'recursive' => -1,
				'conditions' => array(
					'ShadowAttribute.id' => $id,
					'deleted' => 0
				),
			)
		);
		if (empty($shadow)) return array('false' => true, 'errors' => 'Proposal not found or you are not authorised to accept it.');
		$shadow = $shadow['ShadowAttribute'];
		if ($this->ShadowAttribute->typeIsAttachment($shadow['type'])) {
			$encodedFile = $this->ShadowAttribute->base64EncodeAttachment($shadow);
			$shadow['data'] = $encodedFile;
		}
		// If the old_id is set to anything but 0 then we're dealing with a proposed edit to an existing attribute
		if ($shadow['old_id'] != 0) {
			// Find the live attribute by the shadow attribute's uuid, so we can begin editing it
			$this->Attribute->contain = 'Event';
			$activeAttribute = $this->Attribute->findByUuid($shadow['uuid']);

			// Send those away that shouldn't be able to see this
			if (!$this->_isSiteAdmin()) {
				if ($activeAttribute['Event']['orgc_id'] != $this->Auth->user('org_id') || (!$this->userRole['perm_modify'])) {
					if ($this->_isRest()) {
						return array('false' => true, 'errors' => 'Proposal not found or you are not authorised to accept it.');
					} else {
						$this->Session->setFlash('You don\'t have permission to do that');
						$this->redirect(array('controller' => 'events', 'action' => 'view', $shadow['event_id']));
					}
				}
			}
			$date = new DateTime();
			if (isset($shadow['proposal_to_delete']) && $shadow['proposal_to_delete']) {
				$this->Attribute->delete($activeAttribute['Attribute']['id']);
			} else {
				// Update the live attribute with the shadow data
				$fieldsToUpdate = array('value1', 'value2', 'value', 'type', 'category', 'comment', 'to_ids');
				foreach ($fieldsToUpdate as $f) $activeAttribute['Attribute'][$f] = $shadow[$f];
				$activeAttribute['Attribute']['timestamp'] = $date->getTimestamp();
				$this->Attribute->save($activeAttribute['Attribute']);
			}
			$this->ShadowAttribute->setDeleted($id);
			$this->loadModel('Event');
			$this->Event->Behaviors->detach('SysLogLogable.SysLogLogable');
			$this->Event->recursive = -1;
			// Unpublish the event, accepting a proposal is modifying the event after all. Also, reset the lock.
			$event = $this->Event->read(null, $activeAttribute['Attribute']['event_id']);
			$this->Event->unpublishEvent($activeAttribute['Attribute']['event_id'], true);
			$this->Log = ClassRegistry::init('Log');
			$this->Log->create();
			$this->Log->save(array(
				'org_id' => $this->Auth->user('org_id'),
				'model' => 'ShadowAttribute',
				'model_id' => $id,
				'email' => $this->Auth->user('email'),
				'action' => 'accept',
				'title' => 'Proposal (' . $shadow['id'] . ') of ' . $shadow['org_id'] . ' to Attribute (' . $shadow['old_id'] . ') of Event (' . $shadow['event_id'] . ') accepted - ' . $shadow['category'] . '/' . $shadow['type'] . ' ' . $shadow['value'],
			));
			return array('saved' => true, 'success' => 'Proposed change accepted.');
		} else {
			// If the old_id is set to 0, then we're dealing with a brand new proposed attribute
			// The idea is to load the event that the new attribute will be attached to, create an attribute to it and set the distribution equal to that of the event
			$toDeleteId = $shadow['id'];
			$this->loadModel('Event');
			$this->Event->Behaviors->detach('SysLogLogable.SysLogLogable');
			$this->Event->recursive = -1;
			$event = $this->Event->read(null, $shadow['event_id']);

			if (!$this->_isSiteAdmin()) {
				if (($event['Event']['orgc_id'] != $this->Auth->user('org_id')) || (!$this->userRole['perm_modify'])) {
					$this->Session->setFlash('You don\'t have permission to do that');
					$this->redirect(array('controller' => 'events', 'action' => 'index'));
				}
			}
			$shadowForLog = $shadow;
			// Stuff that we won't use in its current form for the attribute
			unset($shadow['email'], $shadow['org_id'], $shadow['id'], $shadow['old_id']);
			$attribute = $shadow;

			// set the distribution equal to that of the event
			$attribute['distribution'] = 5;
			$this->Attribute->create();
			$this->Attribute->save($attribute);
			$this->ShadowAttribute->setDeleted($toDeleteId);

			if ($this->Auth->user('org_id') == $event['Event']['orgc_id']) {
				$this->Event->unpublishEvent($activeAttribute['Attribute']['event_id'], true);
				$event['Event']['proposal_email_lock'] = 0;
			} else {
				$this->Event->unpublishEvent($activeAttribute['Attribute']['event_id']);
			}
			$this->Log = ClassRegistry::init('Log');
			$this->Log->create();
			$this->Log->save(array(
				'org_id' => $this->Auth->user('org_id'),
				'model' => 'ShadowAttribute',
				'model_id' => $id,
				'email' => $this->Auth->user('email'),
				'action' => 'accept',
				'title' => 'Proposal (' . $shadowForLog['id'] . ') of ' . $shadowForLog['org_id'] . ' to Event(' . $shadowForLog['event_id'] . ') accepted',
				'change' => null,
			));
			return array('saved' => true, 'success' => 'Proposal accepted.');
		}
	}

	// Accept a proposed edit and update the attribute
	public function accept($id = null) {
		if (!$this->request->is('post')) {
			throw new MethodNotAllowedException();
		}
		$response = $this->__accept($id);
		if ($this->_isRest()) {
			if (isset($response['success'])) {
				$response['check_publish'] = true;<commit_msg>fix: Fixed an issue where events wouldn't get properly unpublished when accepting a proposal, fixes #2943<commit_after><?php
App::uses('AppController', 'Controller');
App::uses('Folder', 'Utility');
App::uses('File', 'Utility');

class ShadowAttributesController extends AppController {

	public $components = array('Acl', 'Security', 'RequestHandler', 'Email');

	public $paginate = array(
			'limit' => 60,
			'maxLimit' => 9999,
		);

	public $helpers = array('Js' => array('Jquery'));

	public function beforeFilter() {
		parent::beforeFilter();
		$this->set('title_for_layout', 'Proposals');
		$this->Security->validatePost = true;

		// convert uuid to id if present in the url, and overwrite id field
		if (isset($this->params->query['uuid'])) {
			$params = array(
					'conditions' => array('ShadowAttribute.uuid' => $this->params->query['uuid']),
					'recursive' => 0,
					'fields' => 'ShadowAttribute.id'
					);
			$result = $this->ShadowAttribute->find('first', $params);
			if (isset($result['ShadowAttribute']) && isset($result['ShadowAttribute']['id'])) {
				$id = $result['ShadowAttribute']['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()) {
			$this->paginate = Set::merge($this->paginate,array(
			'conditions' =>
					array('OR' =>
							array(
								'Event.org =' => $this->Auth->user('org_id'),
								'AND' => array(
									'ShadowAttribute.org =' => $this->Auth->user('org_id'),
									'Event.distribution >' => 0,
									Configure::read('MISP.unpublishedprivate') ? array('Event.published =' => 1) : array(),
								),
							)
			)));
		}
	}

	private function __accept($id) {
		$this->loadModel('Attribute');
		$this->Attribute->Behaviors->detach('SysLogLogable.SysLogLogable');
		$shadow = $this->ShadowAttribute->find(
			'first',
			array(
				'recursive' => -1,
				'conditions' => array(
					'ShadowAttribute.id' => $id,
					'deleted' => 0
				),
			)
		);
		if (empty($shadow)) return array('false' => true, 'errors' => 'Proposal not found or you are not authorised to accept it.');
		$shadow = $shadow['ShadowAttribute'];
		if ($this->ShadowAttribute->typeIsAttachment($shadow['type'])) {
			$encodedFile = $this->ShadowAttribute->base64EncodeAttachment($shadow);
			$shadow['data'] = $encodedFile;
		}
		// If the old_id is set to anything but 0 then we're dealing with a proposed edit to an existing attribute
		if ($shadow['old_id'] != 0) {
			// Find the live attribute by the shadow attribute's uuid, so we can begin editing it
			$this->Attribute->contain = 'Event';
			$activeAttribute = $this->Attribute->findByUuid($shadow['uuid']);

			// Send those away that shouldn't be able to see this
			if (!$this->_isSiteAdmin()) {
				if ($activeAttribute['Event']['orgc_id'] != $this->Auth->user('org_id') || (!$this->userRole['perm_modify'])) {
					if ($this->_isRest()) {
						return array('false' => true, 'errors' => 'Proposal not found or you are not authorised to accept it.');
					} else {
						$this->Session->setFlash('You don\'t have permission to do that');
						$this->redirect(array('controller' => 'events', 'action' => 'view', $shadow['event_id']));
					}
				}
			}
			$date = new DateTime();
			if (isset($shadow['proposal_to_delete']) && $shadow['proposal_to_delete']) {
				$this->Attribute->delete($activeAttribute['Attribute']['id']);
			} else {
				// Update the live attribute with the shadow data
				$fieldsToUpdate = array('value1', 'value2', 'value', 'type', 'category', 'comment', 'to_ids');
				foreach ($fieldsToUpdate as $f) $activeAttribute['Attribute'][$f] = $shadow[$f];
				$activeAttribute['Attribute']['timestamp'] = $date->getTimestamp();
				$this->Attribute->save($activeAttribute['Attribute']);
			}
			$this->ShadowAttribute->setDeleted($id);
			$this->loadModel('Event');
			$this->Event->Behaviors->detach('SysLogLogable.SysLogLogable');
			$this->Event->recursive = -1;
			// Unpublish the event, accepting a proposal is modifying the event after all. Also, reset the lock.
			$event = $this->Event->read(null, $activeAttribute['Attribute']['event_id']);
			$this->Event->unpublishEvent($activeAttribute['Attribute']['event_id'], true);
			$this->Log = ClassRegistry::init('Log');
			$this->Log->create();
			$this->Log->save(array(
				'org_id' => $this->Auth->user('org_id'),
				'model' => 'ShadowAttribute',
				'model_id' => $id,
				'email' => $this->Auth->user('email'),
				'action' => 'accept',
				'title' => 'Proposal (' . $shadow['id'] . ') of ' . $shadow['org_id'] . ' to Attribute (' . $shadow['old_id'] . ') of Event (' . $shadow['event_id'] . ') accepted - ' . $shadow['category'] . '/' . $shadow['type'] . ' ' . $shadow['value'],
			));
			return array('saved' => true, 'success' => 'Proposed change accepted.');
		} else {
			// If the old_id is set to 0, then we're dealing with a brand new proposed attribute
			// The idea is to load the event that the new attribute will be attached to, create an attribute to it and set the distribution equal to that of the event
			$toDeleteId = $shadow['id'];
			$this->loadModel('Event');
			$this->Event->Behaviors->detach('SysLogLogable.SysLogLogable');
			$this->Event->recursive = -1;
			$event = $this->Event->read(null, $shadow['event_id']);

			if (!$this->_isSiteAdmin()) {
				if (($event['Event']['orgc_id'] != $this->Auth->user('org_id')) || (!$this->userRole['perm_modify'])) {
					$this->Session->setFlash('You don\'t have permission to do that');
					$this->redirect(array('controller' => 'events', 'action' => 'index'));
				}
			}
			$shadowForLog = $shadow;
			// Stuff that we won't use in its current form for the attribute
			unset($shadow['email'], $shadow['org_id'], $shadow['id'], $shadow['old_id']);
			$attribute = $shadow;

			// set the distribution equal to that of the event
			$attribute['distribution'] = 5;
			$this->Attribute->create();
			$this->Attribute->save($attribute);
			$this->ShadowAttribute->setDeleted($toDeleteId);

			if ($this->Auth->user('org_id') == $event['Event']['orgc_id']) {
				$this->Event->unpublishEvent($shadow['event_id'], true);
				$event['Event']['proposal_email_lock'] = 0;
			} else {
				$this->Event->unpublishEvent($shadow['event_id']);
			}
			$this->Log = ClassRegistry::init('Log');
			$this->Log->create();
			$this->Log->save(array(
				'org_id' => $this->Auth->user('org_id'),
				'model' => 'ShadowAttribute',
				'model_id' => $id,
				'email' => $this->Auth->user('email'),
				'action' => 'accept',
				'title' => 'Proposal (' . $shadowForLog['id'] . ') of ' . $shadowForLog['org_id'] . ' to Event(' . $shadowForLog['event_id'] . ') accepted',
				'change' => null,
			));
			return array('saved' => true, 'success' => 'Proposal accepted.');
		}
	}

	// Accept a proposed edit and update the attribute
	public function accept($id = null) {
		if (!$this->request->is('post')) {
			throw new MethodNotAllowedException();
		}
		$response = $this->__accept($id);
		if ($this->_isRest()) {
			if (isset($response['success'])) {
				$response['check_publish'] = true;
{'fraction_non_alphanumeric': 0.20387811634349032, 'fraction_numerical': 0.0033240997229916896, 'mean_word_length': 4.042248603351955, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 309, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '815600', 'n_tokens_mistral': 5273, 'n_tokens_neox': 4489, 'n_words': 1046}