/**
  * Form Handler to save a content quick create.
  *
  * @param Form $form
  *
  * @return string|bool
  */
 public static function QuickDraftSave(Form $form)
 {
     if (!$form->getElementValue('title')) {
         \Core\set_message('All pages must have titles.', 'error');
         return false;
     }
     /** @var $model ContentModel */
     $model = new ContentModel();
     /** @var $page PageModel Page object for this model, already linked up! */
     $page = $model->getLink('Page');
     // The content nickname is derived from the page title.
     $model->set('nickname', $form->getElementValue('title'));
     $model->save();
     $ins = new InsertableModel();
     $ins->set('site', $page->get('site'));
     $ins->set('baseurl', '/content/view/' . $model->get('id'));
     $ins->set('name', 'body');
     $ins->set('value', '<p>' . nl2br($form->getElementValue('content')) . '</p>');
     $ins->save();
     $page->set('title', $form->getElementValue('title'));
     $page->set('published_status', 'draft');
     $page->set('editurl', '/content/edit/' . $model->get('id'));
     $page->set('deleteurl', '/content/delete/' . $model->get('id'));
     $page->set('component', 'content');
     $page->save();
     return true;
 }
 public static function SpamKeywordsSave(Form $form)
 {
     ConfigHandler::Set('/security/spam_threshold', $form->getElementValue('threshold'));
     foreach ($form->getElements() as $el) {
         /** @var FormElement $el */
         $n = $el->get('name');
         if (strpos($n, 'score[') === 0) {
             $n = substr($n, 6, -1);
             $s = $el->get('value');
             if ($s == '') {
                 $s = 1;
             }
             $model = SpamHamKeywordModel::Construct($n);
             $model->set('score', $s);
             $model->save();
         }
     }
     if ($form->getElementValue('new_keyword')) {
         $n = $form->getElementValue('new_keyword');
         $s = $form->getElementValue('new_score');
         if ($s == '') {
             $s = 1;
         }
         $model = SpamHamKeywordModel::Construct($n);
         $model->set('score', $s);
         $model->save();
     }
     return true;
 }
 public static function _GenerateLicenses(Form $form)
 {
     $qty = $form->getElementValue('qty');
     if (!is_numeric($qty)) {
         Core::SetMessage('Please set a valid quantity', 'error');
         return false;
     }
     if ($qty < 1) {
         Core::SetMessage('Please set a quantity greater than 0', 'error');
         return false;
     }
     if ($qty > 999) {
         Core::SetMessage('Quantity limited to 999', 'warning');
         $qty = 999;
     }
     $expires = new \Core\Date\DateTime();
     $expires->modify($form->getElementValue('duration'));
     $expires = $expires->format('Y-m-d');
     for ($i = 0; $i < $qty; $i++) {
         $license = new PackageRepositoryLicenseModel();
         $license->set('password', \Core\random_hex(rand(35, 49)));
         $license->set('expires', $expires);
         $license->save();
     }
     Core::SetMessage('Generated ' . $qty . ' license(s)!', 'success');
     return '/packagerepositorylicense/admin';
 }
	/**
	 * Form Handler for logging in.
	 *
	 * @static
	 *
	 * @param \Form $form
	 *
	 * @return bool|null|string
	 */
	public static function LoginHandler(\Form $form){
		/** @var \FormElement $e */
		$e = $form->getElement('email');
		/** @var \FormElement $p */
		$p = $form->getElement('pass');


		/** @var \UserModel $u */
		$u = \UserModel::Find(array('email' => $e->get('value')), 1);

		if(!$u){
			// Log this as a login attempt!
			$logmsg = 'Failed Login. Email not registered' . "\n" . 'Email: ' . $e->get('value') . "\n";
			\SystemLogModel::LogSecurityEvent('/user/login', $logmsg);
			$e->setError('t:MESSAGE_ERROR_USER_LOGIN_EMAIL_NOT_FOUND');
			return false;
		}

		if($u->get('active') == 0){
			// The model provides a quick cut-off for active/inactive users.
			// This is the control managed with in the admin.
			$logmsg = 'Failed Login. User tried to login before account activation' . "\n" . 'User: '******'email') . "\n";
			\SystemLogModel::LogSecurityEvent('/user/login', $logmsg, null, $u->get('id'));
			$e->setError('t:MESSAGE_ERROR_USER_LOGIN_ACCOUNT_NOT_ACTIVE');
			return false;
		}
		elseif($u->get('active') == -1){
			// The model provides a quick cut-off for active/inactive users.
			// This is the control managed with in the admin.
			$logmsg = 'Failed Login. User tried to login after account deactivation.' . "\n" . 'User: '******'email') . "\n";
			\SystemLogModel::LogSecurityEvent('/user/login', $logmsg, null, $u->get('id'));
			$e->setError('t:MESSAGE_ERROR_USER_LOGIN_ACCOUNT_DEACTIVATED');
			return false;
		}

		try{
			/** @var \Core\User\AuthDrivers\datastore $auth */
			$auth = $u->getAuthDriver('datastore');
		}
		catch(Exception $e){
			$e->setError('t:MESSAGE_ERROR_USER_LOGIN_PASSWORD_AUTH_DISABLED');
			return false;
		}


		// This is a special case if the password isn't set yet.
		// It can happen with imported users or if a password is invalidated.
		if($u->get('password') == ''){
			// Use the Nonce system to generate a one-time key with this user's data.
			$nonce = \NonceModel::Generate(
				'20 minutes',
				['type' => 'password-reset', 'user' => $u->get('id')]
			);

			$link = '/datastoreauth/forgotpassword?e=' . urlencode($u->get('email')) . '&n=' . $nonce;

			$email = new \Email();
			$email->setSubject('Initial Password Request');
			$email->to($u->get('email'));
			$email->assign('link', \Core\resolve_link($link));
			$email->assign('ip', REMOTE_IP);
			$email->templatename = 'emails/user/initialpassword.tpl';
			try{
				$email->send();
				\SystemLogModel::LogSecurityEvent('/user/initialpassword/send', 'Initial password request sent successfully', null, $u->get('id'));

				\Core\set_message('t:MESSAGE_INFO_USER_LOGIN_MUST_SET_NEW_PASSWORD_INSTRUCTIONS_HAVE_BEEN_EMAILED');
				return true;
			}
			catch(\Exception $e){
				\Core\ErrorManagement\exception_handler($e);
				\Core\set_message('t:MESSAGE_ERROR_USER_LOGIN_MUST_SET_NEW_PASSWORD_UNABLE_TO_SEND_EMAIL');
				return false;
			}
		}


		if(!$auth->checkPassword($p->get('value'))){

			// Log this as a login attempt!
			$logmsg = 'Failed Login. Invalid password' . "\n" . 'Email: ' . $e->get('value') . "\n";
			\SystemLogModel::LogSecurityEvent('/user/login/failed_password', $logmsg, null, $u->get('id'));

			// Also, I want to look up and see how many login attempts there have been in the past couple minutes.
			// If there are too many, I need to start slowing the attempts.
			$time = new \CoreDateTime();
			$time->modify('-5 minutes');

			$securityfactory = new \ModelFactory('SystemLogModel');
			$securityfactory->where('code = /user/login/failed_password');
			$securityfactory->where('datetime > ' . $time->getFormatted(\Time::FORMAT_EPOCH, \Time::TIMEZONE_GMT));
			$securityfactory->where('ip_addr = ' . REMOTE_IP);

			$attempts = $securityfactory->count();
			if($attempts > 4){
				// Start slowing down the response.  This should help deter brute force attempts.
				// (x+((x-7)/4)^3)-4
				sleep( ($attempts+(($attempts-7)/4)^3)-4 );
				// This makes a nice little curve with the following delays:
				// 5th  attempt: 0.85
				// 6th  attempt: 2.05
				// 7th  attempt: 3.02
				// 8th  attempt: 4.05
				// 9th  attempt: 5.15
				// 10th attempt: 6.52
				// 11th attempt: 8.10
				// 12th attempt: 10.05
			}

			$e->setError('t:MESSAGE_ERROR_USER_LOGIN_INCORRECT_PASSWORD');
			$p->set('value', '');
			return false;
		}


		if($form->getElementValue('redirect')){
			// The page was set via client-side javascript on the login page.
			// This is the most reliable option.
			$url = $form->getElementValue('redirect');
		}
		elseif(REL_REQUEST_PATH == '/user/login'){
			// If the user came from the registration page, get the page before that.
			$url = $form->referrer;
		}
		else{
			// else the registration link is now on the same page as the 403 handler.
			$url = REL_REQUEST_PATH;
		}

		// Well, record this too!
		\SystemLogModel::LogSecurityEvent('/user/login', 'Login successful (via password)', null, $u->get('id'));

		// yay...
		$u->set('last_login', \CoreDateTime::Now('U', \Time::TIMEZONE_GMT));
		$u->save();
		\Core\Session::SetUser($u);

		// Allow an external script to override the redirecting URL.
		$overrideurl = \HookHandler::DispatchHook('/user/postlogin/getredirecturl');
		if($overrideurl){
			$url = $overrideurl;
		}

		return $url;
	}
	public static function _i18nSaveHandler(Form $form) {
		
		// NEW IDEA!
		// Instead of setting the override for keys, (possibly useful, just somewhere else)...
		// Set the enabled languages for this site.
		// This allows site administrators to NOT have every language under the sun appear if they're running SuSE.
		$selected = $form->getElement('languages[]')->get('value');
		
		// Implode them into a single string.
		$enabled = implode('|', $selected);
		// Strip out any invalid character.
		$enabled = preg_replace('/[^a-zA-Z_|]/', '', $enabled);
		
		// And save!
		ConfigHandler::Set('/core/language/languages_enabled', $enabled);
		return true;
		
		// Create a custom ini for just these options.
		// This will allow the site admin to change a string without worrying about it getting overridden from an update.

		$lang = $form->getElementValue('lang');
		$ini = "[$lang]\n; Custom locale strings set by the site manager!\n\n";

		foreach($form->getElements() as $el){
			/** @var FormElement $el */

			$name = $el->get('name');
			$val  = $el->get('value');

			if(strpos($name, 'MESSAGE') === 0 || strpos($name, 'FORMAT') === 0 || strpos($name, 'STRING') === 0){
				$ini .= $name . ' = "' . str_replace('"', '\\"', $val) . '";' . "\n";
			}
		}

		// Save this ini out to a custom i18n file.
		$fileout = \Core\Filestore\Factory::File(ROOT_PDIR . 'themes/custom/i18n/' . $lang . '.ini');
		$fileout->putContents($ini);

		\Core\set_message('t:MESSAGE_SUCCESS_UPDATED_TRANSLATION_STRINGS');
		return true;
	}
	/**
	 * This is the form handler for a password protected page.
	 *
	 * @return bool
	 */
	public static function PasswordProtectHandler(Form $form){
		/** @var PageModel $page */
		$page = $form->getElementValue('page');
		$val  = $form->getElementValue('passinput');
		if( $val !== $page->get('password_protected') ){
			\Core\set_message('t:MESSAGE_ERROR_INCORRECT_PASSWORD');
			return false;
		}
		else {
			\Core\Session::Set('page-password-protected/' . $page->get('baseurl'), $val);
			return true;
		}


	}