<commit_before><?php
/**
 * A11yc\Controller\Post
 *
 * @package    part of A11yc
 * @author     Jidaikobo Inc.
 * @license    The MIT License (MIT)
 * @copyright  Jidaikobo Inc.
 * @link       http://www.jidaikobo.com

ussage:
put this code to front controller.

require (__DIR__.'/libs/a11yc/classes/controller/post.php');
define('A11YC_POST_IP_MAX_A_DAY', 150);
define('A11YC_POST_COOKIE_A_10MIN', 10); // min.
define('A11YC_POST_SCRIPT_NAME', '/index.php');
\A11yc\Controller_Post::forge();

at .htaccess
php_value post_max_size "2M"

 */
namespace A11yc\Controller;

use A11yc\Model;

class Post
{
	/**
	 * set consts
	 *
	 * @return Void
	 */
	public static function setConsts()
	{
		// max post a day by ip
		defined('A11YC_POST_IP_MAX_A_DAY') or define('A11YC_POST_IP_MAX_A_DAY', 150);
		defined('A11YC_POST_COOKIE_A_10MIN') or define('A11YC_POST_COOKIE_A_10MIN', 10);

		// Google Analytics
		defined('A11YC_POST_GOOGLE_ANALYTICS_CODE') or define('A11YC_POST_GOOGLE_ANALYTICS_CODE', '');

		// script name
		defined('A11YC_POST_SCRIPT_NAME') or define('A11YC_POST_SCRIPT_NAME', '/post.php');

		// SCRIPT URL
		$url = Util::removeQueryStrings(Util::uri());
		$url.= strpos($url, A11YC_POST_SCRIPT_NAME) === false ? A11YC_POST_SCRIPT_NAME : '';
		defined('A11YC_POST_SCRIPT_URL') or define('A11YC_POST_SCRIPT_URL', $url);
	}

	/**
	 * forge
	 *
	 * @return Void
	 */
	public static function forge()
	{
		// is guest validation
		defined('A11YC_IS_GUEST_VALIDATION') or define('A11YC_IS_GUEST_VALIDATION', true);

		// a11yc
		require (dirname(dirname(__DIR__)).'/main.php');

		// set const
		self::setConsts();

		// session
 	Session::forge('A11YCONLINEVALIDATE');

		// auth users
		if (defined('A11YC_GUEST_USERS'))
		{
			Users::forge(unserialize(A11YC_GUEST_USERS));
		}
		else
		{
			Users::forge(array());
		}

		// auth
		if (A11yc\Auth::auth())
		{
			// login user
			$login_user = Users::fetchCurrentUser();
			View::assign('login_user', $login_user);
		}

		// view
		View::addTplPath(A11YC_PATH.'/views/post');

		// set base url before call controllers
		View::assign('base_url', A11YC_POST_SCRIPT_URL);

		// routing
		static::routing();
		$action = Route::getAction();
		static::$action();

		// render
		View::assign('mode', 'post');

		View::display(array(
				'post/header.php',
				'messages.php',
				'body.php',
				'post/footer.php',
			));
	}

	/**
	 * Action_Login
	 *
	 * @return Void
	 */
	public static function actionLogin()
	{
		Auth::actionLogin();
		define('A11YC_LANG_POST_TITLE', A11YC_LANG_AUTH_TITLE);
	}

	/**
	 * Action_Logout
	 *
	 * @return Void
	 */
	public static function actionLogout()
	{
		Auth::actionLogout(A11YC_POST_SCRIPT_URL);
	}

	/**
	 * Action_Docs
	 *
	 * @return Void
	 */
	public static function actionDocs()
	{
		View::assign('a11yc_doc_url', A11YC_POST_SCRIPT_URL.'?a=doc&amp;criterion=');
		Docs::index(); // $body set
		define('A11YC_LANG_POST_TITLE', A11YC_LANG_DOCS_TITLE);
	}

	/**
	 * Action_Doc
	 *
	 * @return Void
	 */
	public static function actionDoc()
	{
		$criterion = Input::get('criterion');
		if ($criterion)
		{
			View::assign('a11yc_doc_url', A11YC_POST_SCRIPT_URL.'?a=doc&amp;criterion=');
			Docs::each($criterion); // $body set
			$doc = View::fetch('doc');
			define('A11YC_LANG_POST_TITLE', $doc['name']);
		}
		else
		{
			Util::error('service not available.');
		}
	}

	/**
	 * Action_Readme
	 *
	 * @return Void
	 */
	public static function actionReadme()
	{
		View::assign('body', View::fetchTpl('post/readme.php'), false);
		View::assign('title', A11YC_LANG_POST_README);
		define('A11YC_LANG_POST_TITLE', A11YC_LANG_POST_README);
	}

	/**
	 * is in white list
	 *
	 * @return Bool
	 */
	public static function isInWhiteList()
	{
		$ip = Input::server('REMOTE_ADDR', '');

		// performed IPs
		$is_in_white_list = false;
		if (defined('A11YC_APPROVED_GUEST_IPS'))
		{
			$is_in_white_list = in_array($ip, unserialize(A11YC_APPROVED_GUEST_IPS));
		}

		return $is_in_white_list;
	}

	/**
	 * auth
	 *
	 * @return Void
	 */
	public static function auth()
	{
		if (A11yc\Auth::auth()) return true;

		// ip check for guest users
		if ( ! self::isInWhiteList())
		{
			// die if at limit
			static::ipCheckForGuestUsers(Input::server('REMOTE_ADDR', ''));
		}
		return true;
	}

	/**
	 * count up for guest users
	 *
	 * @return Void
	 */
	private static function countUpForGuestUsers()
	{
		if ( ! A11yc\Auth::auth() && ! self::isInWhiteList())
		{
			// ip
			$sql = 'INSERT INTO ip (ip, datetime) VALUES (?, ?);';
			$ip = Input::server('REMOTE_ADDR', '');
			Db::execute($sql, array($ip, date('Y-m-d H:i:s')), A11YC_POST_DB);

			// cookie (session)
			Session::add('a11yc_post', 'count', time());
		}
	}

	/**
	 * ip check for guest users
	 *
	 * @param  String $ip
	 * @return Void
	 */
	private static function ipCheckForGuestUsers($ip)
	{
		// database
		define('A11YC_POST_DB', 'post_log');
		define('A11YC_POST_DATA_FILE', '/'.A11YC_POST_DB.'.sqlite');
		Db::forge(
			A11YC_POST_DB,
			array(
				'dbtype' => 'sqlite',
				'path' => A11YC_DATA_PATH.A11YC_POST_DATA_FILE,
			));
		static::initTable();

		// ip check
		$past_24h = time() - 86400;
		$sql = 'SELECT COUNT(`ip`) as cnt FROM ip WHERE `ip` = ? AND `datetime` > ?;;';
		$ip_count = Db::fetch($sql, array($ip, $past_24h), A11YC_POST_DB);

		// cookie check
		$cookie_count = Session::show('a11yc_post', 'count') ?: array();
		$cookie_count = array_filter($cookie_count, function ($v){return ($v > time() - 600);});

		// ban
		if (
			$ip_count['cnt'] >= A11YC_POST_IP_MAX_A_DAY ||
			count($cookie_count) >= A11YC_POST_COOKIE_A_10MIN
		)
		{
			Util::error('too much accesses.');
		}
	}

	/**
	 * Action_Validation
	 *
	 * @return Void
	 */
	public static function actionValidation()
	{
		// vals
		$url              = Input::post('url', Input::get('url', ''));
		$user_agent       = Input::post('user_agent', '');
		$default_ua       = Input::userAgent();
		$doc_root         = Input::post('doc_root');
		$target_html      = '';
		$render           = '';
		$do_validate      = true;
		$do_css_check     = Input::post('do_css_check', false);

		// host check
		$doc_root = strpos($url, $doc_root) !== false ? $doc_root : Crawl::getHostFromUrl($url);

		// User Agent
		$uas = Values::uas();
		$ua = Arr::get($uas, $user_agent) ? $user_agent : $default_ua;
		$current_ua = Arr::get($uas, "{$user_agent}.str");
		$current_ua = $current_ua ?: $default_ua;

		// fallback
		View::assign('errs', array());

		// auth - if limit die here
		self::auth();

		// validation
		if (Input::post('source'))
		{
			$target_html = Input::post('source');
		}
		elseif ($url)
		{
			$target_html = Model\Html::fetchHtml($url, $ua); // not use Database
			$do_validate = self::failedOrDoOtherAction($url, $doc_root, $do_validate);
		}

		// Do Validate
		if ($target_html && $do_validate)
		{
			self::validate($url, $target_html, $ua, $do_css_check);
		}

		// error
		if (Input::isPostExists() || Input::get('url'))
		{
			if ( ! $target_html && $url)
			{
				Session::add('messages', 'errors', A11YC_LANG_CHECKLIST_PAGE_NOT_FOUND_ERR);

				if (strpos($url, 'http') === false)
				{
					Session::add('messages', 'errors', A11YC_LANG_CHECKLIST_PAGE_NOT_FOUND_ERR_NO_SCHEME);
				}
			}

			View::assign('page_title', Model\Html::fetchPageTitleFromHtml($target_html));

			// validate or image list
			$tpl = $do_validate ? 'checklist/validate.php' : 'checklist/images.php' ;
			View::assign('result', View::fetchTpl($tpl), false);
		}

		// title
		define('A11YC_LANG_POST_TITLE', A11YC_LANG_POST_SERVICE_NAME);

		// assign
		View::assign('do_css_check'       , $do_css_check);
		View::assign('title'              , ''); // need for header
		View::assign('current_user_agent' , $current_ua);
		View::assign('doc_root'           , $doc_root);
		View::assign('user_agent'         , $user_agent);
		View::assign('script_url'         , A11YC_POST_SCRIPT_URL);
		View::assign('url'                , $url);
		View::assign('target_html'        , $target_html);
		View::assign('render'             , $render, false);
		View::assign('body'               , View::fetchTpl('post/index.php'), false);
	}

	/**
	 * failedOrDoOtherAction<commit_msg>refactoring: actionValidation 2<commit_after><?php
/**
 * A11yc\Controller\Post
 *
 * @package    part of A11yc
 * @author     Jidaikobo Inc.
 * @license    The MIT License (MIT)
 * @copyright  Jidaikobo Inc.
 * @link       http://www.jidaikobo.com

ussage:
put this code to front controller.

require (__DIR__.'/libs/a11yc/classes/controller/post.php');
define('A11YC_POST_IP_MAX_A_DAY', 150);
define('A11YC_POST_COOKIE_A_10MIN', 10); // min.
define('A11YC_POST_SCRIPT_NAME', '/index.php');
\A11yc\Controller_Post::forge();

at .htaccess
php_value post_max_size "2M"

 */
namespace A11yc\Controller;

use A11yc\Model;

class Post
{
	/**
	 * set consts
	 *
	 * @return Void
	 */
	public static function setConsts()
	{
		// max post a day by ip
		defined('A11YC_POST_IP_MAX_A_DAY') or define('A11YC_POST_IP_MAX_A_DAY', 150);
		defined('A11YC_POST_COOKIE_A_10MIN') or define('A11YC_POST_COOKIE_A_10MIN', 10);

		// Google Analytics
		defined('A11YC_POST_GOOGLE_ANALYTICS_CODE') or define('A11YC_POST_GOOGLE_ANALYTICS_CODE', '');

		// script name
		defined('A11YC_POST_SCRIPT_NAME') or define('A11YC_POST_SCRIPT_NAME', '/post.php');

		// SCRIPT URL
		$url = Util::removeQueryStrings(Util::uri());
		$url.= strpos($url, A11YC_POST_SCRIPT_NAME) === false ? A11YC_POST_SCRIPT_NAME : '';
		defined('A11YC_POST_SCRIPT_URL') or define('A11YC_POST_SCRIPT_URL', $url);
	}

	/**
	 * forge
	 *
	 * @return Void
	 */
	public static function forge()
	{
		// is guest validation
		defined('A11YC_IS_GUEST_VALIDATION') or define('A11YC_IS_GUEST_VALIDATION', true);

		// a11yc
		require (dirname(dirname(__DIR__)).'/main.php');

		// set const
		self::setConsts();

		// session
 	Session::forge('A11YCONLINEVALIDATE');

		// auth users
		if (defined('A11YC_GUEST_USERS'))
		{
			Users::forge(unserialize(A11YC_GUEST_USERS));
		}
		else
		{
			Users::forge(array());
		}

		// auth
		if (A11yc\Auth::auth())
		{
			// login user
			$login_user = Users::fetchCurrentUser();
			View::assign('login_user', $login_user);
		}

		// view
		View::addTplPath(A11YC_PATH.'/views/post');

		// set base url before call controllers
		View::assign('base_url', A11YC_POST_SCRIPT_URL);

		// routing
		static::routing();
		$action = Route::getAction();
		static::$action();

		// render
		View::assign('mode', 'post');

		View::display(array(
				'post/header.php',
				'messages.php',
				'body.php',
				'post/footer.php',
			));
	}

	/**
	 * Action_Login
	 *
	 * @return Void
	 */
	public static function actionLogin()
	{
		Auth::actionLogin();
		define('A11YC_LANG_POST_TITLE', A11YC_LANG_AUTH_TITLE);
	}

	/**
	 * Action_Logout
	 *
	 * @return Void
	 */
	public static function actionLogout()
	{
		Auth::actionLogout(A11YC_POST_SCRIPT_URL);
	}

	/**
	 * Action_Docs
	 *
	 * @return Void
	 */
	public static function actionDocs()
	{
		View::assign('a11yc_doc_url', A11YC_POST_SCRIPT_URL.'?a=doc&amp;criterion=');
		Docs::index(); // $body set
		define('A11YC_LANG_POST_TITLE', A11YC_LANG_DOCS_TITLE);
	}

	/**
	 * Action_Doc
	 *
	 * @return Void
	 */
	public static function actionDoc()
	{
		$criterion = Input::get('criterion');
		if ($criterion)
		{
			View::assign('a11yc_doc_url', A11YC_POST_SCRIPT_URL.'?a=doc&amp;criterion=');
			Docs::each($criterion); // $body set
			$doc = View::fetch('doc');
			define('A11YC_LANG_POST_TITLE', $doc['name']);
		}
		else
		{
			Util::error('service not available.');
		}
	}

	/**
	 * Action_Readme
	 *
	 * @return Void
	 */
	public static function actionReadme()
	{
		View::assign('body', View::fetchTpl('post/readme.php'), false);
		View::assign('title', A11YC_LANG_POST_README);
		define('A11YC_LANG_POST_TITLE', A11YC_LANG_POST_README);
	}

	/**
	 * is in white list
	 *
	 * @return Bool
	 */
	public static function isInWhiteList()
	{
		$ip = Input::server('REMOTE_ADDR', '');

		// performed IPs
		$is_in_white_list = false;
		if (defined('A11YC_APPROVED_GUEST_IPS'))
		{
			$is_in_white_list = in_array($ip, unserialize(A11YC_APPROVED_GUEST_IPS));
		}

		return $is_in_white_list;
	}

	/**
	 * auth
	 *
	 * @return Void
	 */
	public static function auth()
	{
		if (A11yc\Auth::auth()) return true;

		// ip check for guest users
		if ( ! self::isInWhiteList())
		{
			// die if at limit
			static::ipCheckForGuestUsers(Input::server('REMOTE_ADDR', ''));
		}
		return true;
	}

	/**
	 * count up for guest users
	 *
	 * @return Void
	 */
	private static function countUpForGuestUsers()
	{
		if ( ! A11yc\Auth::auth() && ! self::isInWhiteList())
		{
			// ip
			$sql = 'INSERT INTO ip (ip, datetime) VALUES (?, ?);';
			$ip = Input::server('REMOTE_ADDR', '');
			Db::execute($sql, array($ip, date('Y-m-d H:i:s')), A11YC_POST_DB);

			// cookie (session)
			Session::add('a11yc_post', 'count', time());
		}
	}

	/**
	 * ip check for guest users
	 *
	 * @param  String $ip
	 * @return Void
	 */
	private static function ipCheckForGuestUsers($ip)
	{
		// database
		define('A11YC_POST_DB', 'post_log');
		define('A11YC_POST_DATA_FILE', '/'.A11YC_POST_DB.'.sqlite');
		Db::forge(
			A11YC_POST_DB,
			array(
				'dbtype' => 'sqlite',
				'path' => A11YC_DATA_PATH.A11YC_POST_DATA_FILE,
			));
		static::initTable();

		// ip check
		$past_24h = time() - 86400;
		$sql = 'SELECT COUNT(`ip`) as cnt FROM ip WHERE `ip` = ? AND `datetime` > ?;;';
		$ip_count = Db::fetch($sql, array($ip, $past_24h), A11YC_POST_DB);

		// cookie check
		$cookie_count = Session::show('a11yc_post', 'count') ?: array();
		$cookie_count = array_filter($cookie_count, function ($v){return ($v > time() - 600);});

		// ban
		if (
			$ip_count['cnt'] >= A11YC_POST_IP_MAX_A_DAY ||
			count($cookie_count) >= A11YC_POST_COOKIE_A_10MIN
		)
		{
			Util::error('too much accesses.');
		}
	}

	/**
	 * Action_Validation
	 *
	 * @return Void
	 */
	public static function actionValidation()
	{
		// vals
		$url              = Input::post('url', Input::get('url', ''));
		$user_agent       = Input::post('user_agent', '');
		$default_ua       = Input::userAgent();
		$doc_root         = Input::post('doc_root');
		$target_html      = '';
		$do_validate      = true;
		$do_css_check     = Input::post('do_css_check', false);

		// host check
		$doc_root = strpos($url, $doc_root) !== false ? $doc_root : Crawl::getHostFromUrl($url);

		// User Agent
		$uas = Values::uas();
		$ua = Arr::get($uas, $user_agent) ? $user_agent : $default_ua;
		$current_ua = Arr::get($uas, "{$user_agent}.str");
		$current_ua = $current_ua ?: $default_ua;

		// fallback
		View::assign('errs', array());

		// auth - if limit die here
		self::auth();

		// validation
		if (Input::post('source'))
		{
			$target_html = Input::post('source');
		}
		elseif ($url)
		{
			$target_html = Model\Html::fetchHtml($url, $ua); // not use Database
			$do_validate = self::failedOrDoOtherAction($url, $doc_root, $do_validate);
		}

		// Do Validate
		if ($target_html && $do_validate)
		{
			self::validate($url, $target_html, $ua, $do_css_check);
		}

		// error
		if (Input::isPostExists() || Input::get('url'))
		{
			if ( ! $target_html && $url)
			{
				Session::add('messages', 'errors', A11YC_LANG_CHECKLIST_PAGE_NOT_FOUND_ERR);

				if (strpos($url, 'http') === false)
				{
					Session::add('messages', 'errors', A11YC_LANG_CHECKLIST_PAGE_NOT_FOUND_ERR_NO_SCHEME);
				}
			}

			View::assign('page_title', Model\Html::fetchPageTitleFromHtml($target_html));

			// validate or image list
			$tpl = $do_validate ? 'checklist/validate.php' : 'checklist/images.php' ;
			View::assign('result', View::fetchTpl($tpl), false);
		}

		// title
		define('A11YC_LANG_POST_TITLE', A11YC_LANG_POST_SERVICE_NAME);

		// assign
		View::assign('do_css_check'       , $do_css_check);
		View::assign('title'              , ''); // need for header
		View::assign('current_user_agent' , $current_ua);
		View::assign('doc_root'           , $doc_root);
		View::assign('user_agent'         , $user_agent);
		View::assign('script_url'         , A11YC_POST_SCRIPT_URL);
		View::assign('url'                , $url);
		View::assign('target_html'        , $target_html);
		View::assign('body'               , View::fetchTpl('post/index.php'), false);
	}

	/**
	 * failedOrDoOtherAction
{'fraction_non_alphanumeric': 0.17379039676212668, 'fraction_numerical': 0.019562151223400992, 'mean_word_length': 3.672779369627507, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '5511004', 'n_tokens_mistral': 7152, 'n_tokens_neox': 6204, 'n_words': 1031}