From 62cdc8b3394528fb8614e88d07c69026e0ad3849 Mon Sep 17 00:00:00 2001 From: franzz Date: Wed, 7 Aug 2013 14:39:34 +0200 Subject: [PATCH] Initial commit --- .htaccess | 3 + aescrawl.ttf | Bin 0 -> 31056 bytes background.php | 19 + config.php | 1362 ++++++++++++++++++++++++++++++++ functions.js | 54 ++ images/bubble.png | Bin 0 -> 22072 bytes images/bubble_inverted.png | Bin 0 -> 22464 bytes images/button_left.png | Bin 0 -> 1422 bytes images/button_left_hover.png | Bin 0 -> 1265 bytes images/button_middle.png | Bin 0 -> 247 bytes images/button_middle_hover.png | Bin 0 -> 244 bytes images/button_right.png | Bin 0 -> 1685 bytes images/button_right_hover.png | Bin 0 -> 1627 bytes images/error.png | Bin 0 -> 1212 bytes images/favicon.ico | Bin 0 -> 15086 bytes images/favicon2.ico | Bin 0 -> 15086 bytes images/logo.png | Bin 0 -> 56228 bytes images/minicloud.png | Bin 0 -> 5210 bytes images/minicloud_active.png | Bin 0 -> 4325 bytes images/minicloud_disabled.png | Bin 0 -> 3377 bytes images/minicloud_hover.png | Bin 0 -> 5014 bytes images/pad_bottom.gif | Bin 0 -> 1210 bytes images/pad_line.gif | Bin 0 -> 636 bytes images/pad_top.gif | Bin 0 -> 1393 bytes images/writing_cloud.png | Bin 0 -> 116603 bytes index.php | 109 +++ mask/calendar.html | 27 + mask/errors.html | 7 + mask/index.html | 37 + mask/logon.html | 20 + mask/menu.html | 4 + mask/read_thought.html | 14 + mask/settings.html | 19 + mask/write_thought.html | 77 ++ style.css | 365 +++++++++ test.php | 36 + welcome | 2 + 37 files changed, 2155 insertions(+) create mode 100644 .htaccess create mode 100755 aescrawl.ttf create mode 100755 background.php create mode 100755 config.php create mode 100755 functions.js create mode 100755 images/bubble.png create mode 100755 images/bubble_inverted.png create mode 100755 images/button_left.png create mode 100755 images/button_left_hover.png create mode 100755 images/button_middle.png create mode 100755 images/button_middle_hover.png create mode 100755 images/button_right.png create mode 100755 images/button_right_hover.png create mode 100755 images/error.png create mode 100755 images/favicon.ico create mode 100755 images/favicon2.ico create mode 100755 images/logo.png create mode 100755 images/minicloud.png create mode 100755 images/minicloud_active.png create mode 100755 images/minicloud_disabled.png create mode 100755 images/minicloud_hover.png create mode 100755 images/pad_bottom.gif create mode 100755 images/pad_line.gif create mode 100755 images/pad_top.gif create mode 100755 images/writing_cloud.png create mode 100755 index.php create mode 100755 mask/calendar.html create mode 100755 mask/errors.html create mode 100755 mask/index.html create mode 100755 mask/logon.html create mode 100755 mask/menu.html create mode 100755 mask/read_thought.html create mode 100755 mask/settings.html create mode 100755 mask/write_thought.html create mode 100755 style.css create mode 100755 test.php create mode 100755 welcome diff --git a/.htaccess b/.htaccess new file mode 100644 index 0000000..f3a6dd0 --- /dev/null +++ b/.htaccess @@ -0,0 +1,3 @@ +## Jul - deny access to the top-level git repository +RewriteEngine On +RewriteRule \.git - [F,L] diff --git a/aescrawl.ttf b/aescrawl.ttf new file mode 100755 index 0000000000000000000000000000000000000000..fe13851ee7d5b163cf4bd7aa09b8f9e0c6d89d22 GIT binary patch literal 31056 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 Vd=$yzT%mx^SKk8NQzOj2e*v1m7svnr literal 0 HcmV?d00001 diff --git a/background.php b/background.php new file mode 100755 index 0000000..5906aec --- /dev/null +++ b/background.php @@ -0,0 +1,19 @@ +asMessageStack = array(); + $this->asMessageStack[self::ERROR_TAB] = array(); + $this->asMessageStack[self::WARNING_TAB] = array(); + $this->iExtractMode = self::MODE_ARRAY; + } + + protected function addError($sError) + { + $this->addMessage(self::ERROR_TAB, $sError); + } + + protected function addWarning($sWarning) + { + $this->addMessage(self::WARNING_TAB, $sError); + } + + private function addMessage($sType, $sMessage) + { + $this->asMessageStack[$sType][] = $sMessage; + } + + protected function getCleanErrorStack() + { + return $this->getCleanMessageStack(self::ERROR_TAB); + } + + protected function getCleanWarningStack() + { + return $this->getCleanMessageStack(self::WARNING_TAB); + } + + private function getCleanMessageStack($sType) + { + switch($this->iExtractMode) + { + case self::MODE_TEXT: + $oMessageStack = implode("\n", $this->asMessageStack[$sType]); + break; + case self::MODE_ARRAY: + $oMessageStack = $this->asMessageStack[$sType]; + break; + case self::MODE_FILE: + $oMessageStack = implode("

", $this->asMessageStack[$sType]); + break; + } + $this->asMessageStack[$sType] = array(); + return $oMessageStack; + } + + function __destruct() + { + $sErrorStack = $this->getCleanErrorStack(); + + switch($this->iExtractMode) + { + case self::MODE_TEXT: + echo $sErrorStack; + break; + case self::MODE_ARRAY: + if(count($sErrorStack)>0) + { + pre($sErrorStack, 'Error Stack'); + } + break; + case self::MODE_FILE: + if($sErrorStack!='') + { + @file_put_contents('log.html', '

'.date('r')."

".$sErrorStack.'

', FILE_APPEND); + } + break; + } + } +} + +class MySqlManager extends PhpObject +{ + const DB_SERVER = 'localhost'; + const DB_LOGIN = 'root'; + const DB_PASS = '0nadmin'; + const DB_NAME = 'mythoughts'; + + const ID_TAG = 'id_'; + const USERS_TABLE = 'users'; + const THOUGHTS_TABLE = 'thoughts'; + const SETTINGS_TABLE = 'settings'; + + private $oConnection; + + public function __construct() + { + parent::__construct(); + $this->oConnection = mysql_connect(self::DB_SERVER, self::DB_LOGIN, self::DB_PASS); + if(!$this->oConnection) + { + $this->addError('bug connection'); + } + else + { + if(!mysql_select_db(self::DB_NAME, $this->oConnection)) + { + $this->install(); + } + } + } + + public function __destruct() + { + mysql_close($this->oConnection); + } + + private function install() + { + $this->setQuery("DROP DATABASE IF EXISTS ".self::DB_NAME); + $this->setQuery("CREATE /* ".basename(__FILE__)." ".__LINE__." */ DATABASE ".self::DB_NAME); + mysql_select_db(self::DB_NAME, $this->oConnection); + @array_walk(array_map(array($this, 'getInstallQuery'), $this->getTables()), array($this, 'setQuery')); + } + + private function getInstallQuery($sTableName) + { + $asTableColumns = $this->getTableColumns($sTableName); + $sQuery = "\n".implodeAll($asTableColumns, "` ", "\n", "`", ",")."\n".implode(", \n", $this->getTableConstraints($sTableName)); + return "CREATE /* ".basename(__FILE__)." ".__LINE__." */ TABLE `{$sTableName}` ({$sQuery})"; + } + + private function setQuery($sQuery, $sTypeQuery=__FUNCTION__) + { + return $this->getQuery($sQuery, $sTypeQuery); + } + + private function getQuery($sQuery, $sTypeQuery=__FUNCTION__) + { + $oResult = mysql_query($sQuery, $this->oConnection); + if(!$oResult) + { + $this->addError("\nErreur SQL : \n".$sQuery."\n".mysql_error()); + } + return $oResult; + } + + public function getArrayQuery($sQuery, $bStringOnly=false, $sTypeQuery=__FUNCTION__) + { + $asResult = array(); + $oResult = $this->getQuery($sQuery, true, $sTypeQuery); + if($oResult!==false) + { + while($asCurrentRow = mysql_fetch_array($oResult)) + { + if($bStringOnly) + { + $asCurrentRow = $this->arrayKeyFilter($asCurrentRow, 'is_string'); + } + + //One column case : collapse a level + if(count($asCurrentRow)==1) + { + $asResult[] = array_shift($asCurrentRow); + } + else + { + $asResult[] = $asCurrentRow; + } + } + } + return $asResult; + } + + private function arrayKeyFilter($asArray, $sCallBack) + { + $asValidKeys = array_flip(array_filter(array_keys($asArray), $sCallBack)); + return array_intersect_key($asArray, $asValidKeys); + } + + public static function getTables() + { + return array(self::USERS_TABLE, self::THOUGHTS_TABLE, self::SETTINGS_TABLE); + } + + public static function getId($sTableName) + { + return self::ID_TAG.substr($sTableName, 0, -1); + } + + public static function getText($sTableName) + { + return substr($sTableName, 0, -1); + } + + private static function isId($sColumnName, $sTableName='') + { + $asTables = ($sTableName=='')?self::getTables():array($sTableName); + $asTableIds = array_map(array('self', 'getId'), $asTables); + return in_array($sColumnName, $asTableIds); + } + + public static function getTablecolumns($sTableName) + { + $asTableColumns = array(self::getId($sTableName)); + + switch($sTableName) + { + case self::USERS_TABLE: + $asTableColumns[] = 'user'; + $asTableColumns[] = 'pass'; + break; + case self::THOUGHTS_TABLE: + $asTableColumns[] = self::getId(self::USERS_TABLE); + $asTableColumns[] = 'thought'; + break; + case self::SETTINGS_TABLE: + $asTableColumns[] = self::getId(self::USERS_TABLE); + $asTableColumns[] = 'setting'; + $asTableColumns[] = 'value'; + break; + default: + $this->addError('Function '.__FUNCTION__.', table '.$sTableName.' not found'); + } + $asTableColumns[] = 'led'; + $asTableName = array_fill(0, count($asTableColumns), $sTableName); + return array_combine($asTableColumns, array_map(array('self', 'getColumnType'), $asTableColumns, $asTableName)); + } + + private static function getColumnType($sColumnName, $sTableName) + { + $sColumnType = ''; + switch($sColumnName) + { + case 'user': + $sColumnType = "varchar(20) NOT NULL"; + break; + case 'pass': + $sColumnType = "varchar(128) NOT NULL"; + break; + case 'thought': + $sColumnType = "longtext NOT NULL"; + break; + case 'setting': + $sColumnType = "varchar(20) NOT NULL"; + break; + case 'value': + $sColumnType = 'varchar(20) NOT NULL'; + break; + case 'led': + $sColumnType = "TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP"; + break; + case self::isId($sColumnName, $sTableName): + $sColumnType = "int(10) UNSIGNED auto_increment"; + break; + case self::isId($sColumnName): + $sColumnType = "int(10) UNSIGNED NOT NULL"; + break; + } + return $sColumnType; + } + + private static function getTableConstraints($sTableName) + { + //primary key + $asTableConstraints = array('PRIMARY' => "PRIMARY KEY (`".self::getId($sTableName)."`)"); + + //other constraints + switch($sTableName) + { + case 'user' : + break; + case 'thought' : + break; + } + return $asTableConstraints; + } + + private function addQuotes($oData) + { + return array_map_encapsulate($oData, "'"); + } + + private function getLastId() + { + return mysql_insert_id(); + } + + public function insertRow($sTableName, $asData) + { + $this->cleanSql($sTableName); + $this->cleanSql($asData); + + $asQueryValues = $this->addQuotes($asData); + $sQuery = "INSERT /* ".basename(__FILE__)." ".__LINE__." */ + INTO ".$sTableName." (`".implode("`, `", array_keys($asQueryValues))."`) + VALUES (".implode(", ", $asQueryValues).")"; + + return $this->setQuery($sQuery)?$this->getLastId():false; + } + + public function updateRow($sTableName, $asConstraints, $asData) + { + if(!is_array($asConstraints)) + { + $asConstraints = array($this->getId($sTableName)=>$asConstraints); + } + $iTableId = + + $this->cleanSql($sTableName); + $this->cleanSql($iTableId); + $this->cleanSql($asData); + $this->cleanSql($asConstraints); + $asQueryValues = $this->addQuotes($asData); + $asConstraintsValues = $this->addQuotes($asConstraints); + + $sQuery = "UPDATE /* ".basename(__FILE__)." ".__LINE__." */ $sTableName + SET ".implodeAll($asQueryValues, " = ", ", ")." + WHERE ".implodeAll($asConstraintsValues, " = ", " AND ")." LIMIT 1"; + return $this->setQuery($sQuery)?$this->selectValue($sTableName, $this->getId($sTableName), $asConstraints):false; + } + + public function insertUpdateRow($sTableName, $asConstraints, $asData) + { + $iTableId = $this->selectValue($sTableName, $this->getId($sTableName), $asConstraints); + if(!$iTableId) + { + $asData = array_merge($asConstraints, $asData); + return $this->insertRow($sTableName, $asData); + } + else + { + return $this->updateRow($sTableName, $asConstraints, $asData); + } + } + + public function selectRow($sTableName, $asConstraints=array(), $sColumnName='*', $bStringOnly=false) + { + $asResult = $this->selectRows(array('select'=>$sColumnName, 'from'=>$sTableName, 'constraint'=>$asConstraints)); + $iCountNb = count($asResult); + switch($iCountNb) + { + case 0 : + return false; + case $iCountNb > 1 : + $this->addError('Trop de résultats pour un selectRow() : '.$iCountNb); + break; + } + return array_shift($asResult); + } + function selectValue($sTableName, $sColumnName, $asConstraints) + { + if(is_numeric($asConstraints)) + { + $asConstraints = array(self::getId($sTableName)=>$asConstraints); + } + return $this->selectRow($sTableName, $asConstraints, $sColumnName); + } + + public function selectRows($asInfo, $bStringOnly=true) + { + $sAttributes = array('select'=>"SELECT", 'from'=>"FROM", 'constraint'=>"WHERE", 'groupBy'=>"GROUP BY", 'orderBy'=>"ORDER BY"); + $asRowSeparators = array('select'=>", ", 'from'=>"", 'constraint'=>" AND ", 'groupBy'=>", ", 'orderBy'=>", "); + $asOperators = array('constraint'=>" = ", 'orderBy'=>" "); + + $sQuery = "/* ".basename(__FILE__)." ".__LINE__." */"; + foreach($sAttributes as $sStatement => $sKeyWord) + { + $asSelection = array_key_exists($sStatement, $asInfo)?$asInfo[$sStatement]:array(); + if(!is_array($asSelection)) + { + $asSelection = array($asSelection); + } + + //if provided values + if(!empty($asSelection)) + { + $this->cleanSql($asSelection); + + if($sStatement=='constraint') + { + $asSelection = $this->addQuotes($asSelection); + } + + $sQuery .= " ".$sKeyWord." "; + + //in case of double value input + if(array_key_exists($sStatement, $asOperators)) + { + $sQuery .= implodeAll($asSelection, $asOperators[$sStatement], $asRowSeparators[$sStatement]); + } + else + { + $sQuery .= implode($asRowSeparators[$sStatement], $asSelection); + } + } + //default value for select + elseif($sStatement=='select') + { + $sQuery .= " ".$sKeyWord." * "; + } + } + + return $this->getArrayQuery($sQuery, $bStringOnly); + } + + private function cleanSql(&$oData) + { + cleanData($oData, 'mysql_real_escape_string'); + } +} + +class Session extends PhpObject +{ + private $iUserId; + private $sLogin; + private $sToken; + private $sPostToken; + + private $oMySql; + + const SESSION_ID_USER = 'id_user'; + const SESSION_USER = 'user'; + const SESSION_TOKEN = 'token'; + const SESSION_POST_TOKEN = 'post_token'; + + public function __construct($oMySql) + { + parent::__construct(); + $this->iUserId = $this->sLogin = $this->sToken = $this->sPostToken = false; + $this->oMySql = $oMySql; + $this->syncSession(); + } + + public function getUserId() + { + return $this->iUserId; + } + + private function syncSession() + { + if(isset($_SESSION[self::SESSION_ID_USER])) + { + $this->iUserId = $_SESSION[self::SESSION_ID_USER]; + } + if(isset($_SESSION[self::SESSION_USER])) + { + $this->sLogin = $_SESSION[self::SESSION_USER]; + } + if(isset($_SESSION[self::SESSION_TOKEN])) + { + $this->sToken = $_SESSION[self::SESSION_TOKEN]; + } + if(isset($_SESSION[self::SESSION_POST_TOKEN])) + { + $this->sPostToken = $_SESSION[self::SESSION_POST_TOKEN]; + } + } + + private function setSession($iUserId, $sLogin) + { + $_SESSION[self::SESSION_ID_USER] = $iUserId; + $_SESSION[self::SESSION_USER] = $sLogin; + + //Token + $sToken = $this->createToken(); + $_SESSION[self::SESSION_TOKEN] = $sToken; + $this->setTokenCookie($sToken); + + $this->syncSession(); + } + + public function register($asData) + { + $sLogin = strtolower($asData['user']); + $sPass = $asData['pass']; + + if($sLogin=='' || $sPass=='') + { + $this->addError('Empty mandatory fields (Nickname or password)'); + } + elseif(htmlspecialchars($sLogin, ENT_QUOTES)!=$sLogin) + { + $this->addError('Nickname: HTML characters are forbidden'); + } + elseif($this->oMySql->selectRow(MySqlManager::USERS_TABLE, array('user'=>$sLogin))) + { + $this->addError('Nickname: This is already a user called by that name, choose a different one'); + } + else + { + $asData['pass'] = self::encryptPassword($sPass); + $iUserId = $this->oMySql->insertRow(MySqlManager::USERS_TABLE, $asData); + return $this->logMeIn($sLogin, $sPass); + } + return false; + } + + public function logMeIn($sLogin, $sPass) + { + $bResult = false; + $asUser = $this->oMySql->selectRow(MySqlManager::USERS_TABLE, array('user'=>$sLogin)); + if(!$asUser) + { + $this->addError('Utilisateur inconnu'); + } + elseif(!$this->checkPassword($sPass, $asUser['pass'])) + { + $this->addError('mot de pass incorrect'); + } + else + { + $this->setSession($asUser[MySqlManager::getId(MySqlManager::USERS_TABLE)], $sLogin); + $bResult = true; + } + return $bResult; + } + + public function isLogguedIn() + { + $bLogguedIn = false; + if($this->iUserId && $this->sLogin && $this->sToken) + { + //check if token is set and valid + if($this->checkToken()) + { + //Check if user got a actual account in the database + $bLogguedIn = $this->checkAccount($this->sLogin, $this->iUserId); + } + else + { + $this->addError('Authentication problem, please sign in again'); + } + } + return $bLogguedIn; + } + + private function checkAccount($sUserName, $iUserId=0) + { + $asConstraints = array('user'=>$sUserName); + if($iUserId>0) + { + $asConstraints[MySqlManager::getId(MySqlManager::USERS_TABLE)] = $iUserId; + } + return $this->oMySql->selectValue(MySqlManager::USERS_TABLE, 'COUNT(1)', $asConstraints); + } + + public function logMeOut() + { + $_SESSION = array(); + $this->setTokenCookie('', -1); + return session_destroy(); + } + + private static function encryptPassword($sPass) + { + $sRandomText = 'F_RA-1H"2{bvj)5f?0sd3r#fP,K]U|w}hGiN@(sZ.sDe!7*x/:Mq+&'; + for($iIndex=0; $iIndex < strlen($sPass); $iIndex++) + { + $sPass[$iIndex] = $sRandomText[$iIndex%strlen($sRandomText)] ^ $sPass[$iIndex]; + } + return md5($sPass); + } + + private static function createToken() + { + return self::encryptPassword( $_SERVER['HTTP_USER_AGENT']. + $_SERVER['REMOTE_ADDR']. + $_SERVER['REQUEST_TIME']. + strstr(microtime(), ' ', true). + $_SERVER['SERVER_SIGNATURE']. + $_SERVER['SERVER_ADMIN']); + } + + //Session Token + + private static function setTokenCookie($sToken, $iTime=1) + { + setcookie(self::SESSION_TOKEN, $sToken, time()+60*60*24*$iTime); + $_COOKIE[self::SESSION_TOKEN] = $sToken; + } + + private function checkToken() + { + return ($this->sToken && array_key_exists(self::SESSION_TOKEN, $_COOKIE) && $_COOKIE[self::SESSION_TOKEN] == $this->sToken); + } + + //Post Token + + private function refreshPostToken() + { + $this->sPostToken = self::createToken(); + $_SESSION[self::SESSION_POST_TOKEN] = $this->sPostToken; + } + + public function getNewPostToken() + { + $this->refreshPostToken(); + return $this->sPostToken; + } + + public function checkPostToken($sPostToken) + { + return ($this->sPostToken && $sPostToken!='' && $sPostToken == $this->sPostToken); + } + + private static function checkPassword($sClearPass, $sEncodedPass) + { + return self::encryptPassword($sClearPass) == $sEncodedPass; + } +} + +class Mask extends PhpObject +{ + public $sMaskName; + public $sFilePath; + private $sMask; + private $asTags; + private $asPartsSource; + private $aoInstances; + + const MASK_FOLDER = 'mask/'; + const START_TAG = 'START'; + const END_TAG = 'END'; + const TAG_MARK = '#'; + + public function __construct($sFileName='') + { + //init + parent::__construct(); + $this->sMaskName = ''; + $this->sFilePath = ''; + $this->sMask = ''; + $this->asTags = array(); + $this->asPartsSource = array(); + $this->aoInstances = array(); + $this->sFilePath = ''; + + //load file + if($sFileName!='') + { + $this->initFile($sFileName); + } + } + + public function initFile($sFileName) + { + $sFilePath = self::MASK_FOLDER.$sFileName.'.html'; + if(file_exists($sFilePath)) + { + $this->sFilePath = $sFilePath; + $sSource = file_get_contents($this->sFilePath); + $this->initMask($sFileName, $sSource); + } + else + { + $this->addError('Fichier introuvable à l\'adresse : '.$sFilePath); + } + } + + public function initFileFromString($sSource, $sPartName='', $iInstanceNb=0) + { + $this->initMask($sPartName.' (from row) '.$iInstanceNb, $sSource); + } + + private function initMask($sMaskName, $sSource) + { + $this->sMaskName = $sMaskName; + $this->sMask = $sSource; + $this->setParts(); + } + + private function setParts() + { + while(preg_match('/\<\!-- \[PART\] (?P\S+) \[START\] --\>/', $this->sMask, $asMatch)) + { + $sPartName = $asMatch['part']; + + $this->asPartsSource[$sPartName] = $this->getCleanPart($sPartName); + $this->aoInstances[$sPartName] = array(); + } + } + + private function getCleanPart($sPartName) + { + $iStartPos = $this->getPartStartPos($sPartName); + $iEndPos = $this->getPartEndPos($sPartName); + $sPart = substr($this->sMask, $iStartPos, $iEndPos-$iStartPos); + $sExtendedPart = $this->getPartPattern($sPartName, self::START_TAG).$sPart. $this->getPartPattern($sPartName, self::END_TAG); + $this->sMask = str_replace($sExtendedPart, $this->getPartTagPattern($sPartName), $this->sMask); + return $sPart; + } + + private function getPartStartPos($sPartName) + { + $sPartStartPattern = $this->getPartPattern($sPartName, self::START_TAG); + return strpos($this->sMask, $sPartStartPattern) + strlen($sPartStartPattern); + } + + private function getPartEndPos($sPartName) + { + $sPartEndPattern = $this->getPartPattern($sPartName, self::END_TAG); + return strpos($this->sMask, $sPartEndPattern); + } + + private function getPartPattern($sPartName, $sAction) + { + return ''; + } + + private function getPartTagPattern($sPartName, $bMark=true) + { + $sPartTag = 'PART '.$sPartName; + return $bMark?$this->addTagMark($sPartTag):$sPartTag; + } + + public function addInstance($sPartName, $asTags) + { + $this->newInstance($sPartName); + foreach($asTags as $sTagName=>$sTagValue) + { + $this->setInstanceTag($sPartName, $sTagName, $sTagValue); + } + } + + public function newInstance($sPartName) + { + //Finding the part + $oMask = &$this->findPart($this, $sPartName); + + //Retrieving source html + $sPartSource = $oMask->asPartsSource[$sPartName]; + + //Creating new instance + $oInstance = new Mask(); + $oInstance->initFileFromString($sPartSource, $sPartName); + $oMask->aoInstances[$sPartName][] = $oInstance; + } + + public function setInstanceTag($sPartName, $sTagName, $sTagValue) + { + $oMask = &$this->findPart($this, $sPartName); + $oMask->getCurrentInstance($sPartName)->setTag($sTagName, $sTagValue); + } + + private function &findPart($oMask, $sPartName) + { + if(array_key_exists($sPartName, $oMask->aoInstances)) + { + return $oMask; + } + else //not tested + { + foreach($oMask->aoInstances as $sLevelPartName=>$aoInstances) + { + if(!empty($aoInstances)) + { + //take last instances + return $this->findPart($oMask->getCurrentInstance($sLevelPartName), $sPartName); + } + } + } + $this->addError('No part found : '.$sPartName); + } + + private function getCurrentInstance($sPartName) + { + if(!empty($this->aoInstances[$sPartName])) + { + return end($this->aoInstances[$sPartName]); + } + else + { + return false; + } + } + + public function setTag($sTagName, $sTagValue) + { + $this->asTags[$sTagName] = $sTagValue; + } + + public function getMask() + { + $sCompletedMask = $this->sMask; + + //build parts + foreach($this->aoInstances as $sPart=>$aoParts) + { + $sTagValue = ''; + foreach($aoParts as $oInstance) + { + $sTagValue .= $oInstance->getMask(); + } + $this->setTag($this->getPartTagPattern($sPart, false), $sTagValue); + } + + //replace tags + if(!empty($this->asTags)) + { + $asTags = $this->addTagMark(array_keys($this->asTags)); + $sCompletedMask = str_replace($asTags, $this->asTags, $sCompletedMask); + } + return $sCompletedMask; + } + + private function addTagMark($oData) + { + return array_map_encapsulate($oData, self::TAG_MARK); + } +} + +class MyThoughts extends PhpObject +{ + //Constants + const URL_DATE_FORMAT = 'Ymd'; + const LAYOUT_DATE_FORMAT = 'F \t\h\e jS, Y'; + const MYSQL_DATE_FORMAT = 'Y-m-d'; + const LAYOUT_TIME_FORMAT = 'G:i'; + const WELCOME_MSG_FILE = 'welcome'; + + //settings + const SETTING_LAYOUT = 'layout'; + const LAYOUT_ONE_PAGE = '1'; + const LAYOUT_TWO_PAGES = '2'; + const SETTING_FONT = 'font'; + const FONT_THOUGHTS = 'thoughts'; + const FONT_ARIAL = 'Arial'; + const FONT_VERDANA = 'Verdana'; + const SETTING_SIZE = 'Size'; + const SIZE_16 = '16'; + const SIZE_18 = '18'; + const SIZE_20 = '20'; + + //Objects + private $oMySql; + private $oSession; + private $oCalendar; + private $asSettings; + + //Masks + private $oMainMask; + private $oPageMask; + private $oMenuMask; + + function __construct() + { + parent::__construct(); + $this->oMySql = new MySqlManager(); + $this->oSession = new Session($this->oMySql); + $this->oCalendar = new Calendar($this->oMySql, $this->oSession); + $this->oMainMask = new Mask('index'); + $this->oPageMask = new Mask(); + $this->oMenuMask = new Mask(); + $this->asSettings = array(); + } + + public function register($sLogin, $sPass) + { + $asData = array('user'=>$sLogin, 'pass'=>$sPass); + $bRegistered = $this->oSession->register($asData); + if($bRegistered) + { + $this->addThought(file_get_contents(self::WELCOME_MSG_FILE)); + } + return $bRegistered; + } + + public function logMeIn($sLogin, $sPass) + { + return $this->oSession->logMeIn($sLogin, $sPass); + } + + public function logMeOut() + { + $this->oSession->logMeOut(); + self::relocate(); + } + + public function isLogguedIn() + { + return $this->oSession->isLogguedIn(); + } + + public function checkPostToken($sPostToken) + { + return $this->oSession->checkPostToken($sPostToken); + } + + public function setPage($sPage) + { + $this->oPageMask->initFile($sPage); + } + + public function setPageTitle($sTitle) + { + $this->oMainMask->setTag('title', $sTitle); + } + + public function setCalendarDate($iYear=0, $iMonth=0) + { + $this->oCalendar->setDate($iYear, $iMonth); + } + + private static function relocate($sPage='', $asVar=array()) + { + $asVar['p'] = $sPage; + header('Location:index.php?'.implodeAll($asVar, '=', '&')); + die(); + } + + public function addThought($sThought) + { + $asThought = array('thought'=>$this->encodeThought($sThought)); + $asThought[MySqlManager::getId(MySqlManager::USERS_TABLE)] = $this->oSession->getUserId(); + return $this->oMySql->insertRow(MySqlManager::THOUGHTS_TABLE, $asThought); + } + + public function updateThought($iThoughtId, $sThought) + { + $asValues = array('thought'=>$this->encodeThought($sThought)); + $asConstraints = array( MySqlManager::getId(MySqlManager::THOUGHTS_TABLE)=>$iThoughtId, + MySqlManager::getId(MySqlManager::USERS_TABLE)=>$this->oSession->getUserId()); + $this->oMySql->updateRow(MySqlManager::THOUGHTS_TABLE, $asConstraints, $asValues); + } + + private function encodeThought($sthought) + { + return base64_encode(serialize(explode("\n", $this->shuffleText($sthought)))); + } + + private function decodeThought($sEncodedThought) + { + return $this->shuffleText(implode("\n", unserialize(base64_decode($sEncodedThought)))); + } + + private function shuffleText($sText) + { + $sRandomText = "let's_mess%a&bit;with~it,!just§for¨the^sake*of-it"; + for($iIndex=0; $iIndex < strlen($sText); $iIndex++) + { + $sText[$iIndex] = $sRandomText[$iIndex%strlen($sRandomText)] ^ $sText[$iIndex]; + } + return $sText; + } + + public function activateMenu() + { + $this->oMenuMask->initFile('menu'); + } + + //settings + + public static function getSettingsList() + { + //TODO Save on database (param table) + return array(self::SETTING_FONT, self::SETTING_SIZE, self::SETTING_LAYOUT); + } + + private static function getDefaultSetting($sSettingName) + { + switch($sSettingName) + { + case self::SETTING_FONT: + return self::FONT_THOUGHTS; + case self::SETTING_LAYOUT: + return self::LAYOUT_ONE_PAGE; + } + return false; + } + + private function getSetting($sSettingName) + { + if(!array_key_exists($sSettingName, $this->asSettings)) + { + $asConstraint = array(MySqlManager::getText(MySqlManager::SETTINGS_TABLE)=>$sSettingName, MySqlManager::getId(MySqlManager::USERS_TABLE)=>$this->oSession->getUserId()); + $oValue = $this->oMySql->selectValue(MySqlManager::SETTINGS_TABLE, 'value', $asConstraint); + $this->asSettings[$sSettingName] = (!$oValue)?self::getDefaultSetting($sSettingName):$oValue; + } + return $this->asSettings[$sSettingName]; + } + + private function setSetting($sValue, $sSettingName) + { + $this->oMySql->insertUpdateRow(MySqlManager::SETTINGS_TABLE, array('setting'=>$sSettingName, MySqlManager::getId(MySqlManager::USERS_TABLE)=>$this->oSession->getUserId()), array('value'=>$sValue)); + } + + public function setSettings($asSettings) + { + array_walk($asSettings, array($this, 'setSetting')); + } + + /* Pages */ + + public function logonPage($sPreviousLogin) + { + $this->setPageTitle('Login'); + $this->setPage('logon'); + $sPreviousLogin = ($sPreviousLogin=='')?'':$sPreviousLogin; + $this->oPageMask->setTag('login', $sPreviousLogin); + } + + public function writingPage($iThoughtId=0) + { + $sThought = ''; + $iThoughtTime = ''; + if($iThoughtId!=0) + { + //load a thought + $asConstraints = array( MySqlManager::getId(MySqlManager::THOUGHTS_TABLE)=>$iThoughtId, + MySqlManager::getId(MySqlManager::USERS_TABLE)=>$this->oSession->getUserId()); + $asThought = $this->oMySql->selectRow(MySqlManager::THOUGHTS_TABLE, $asConstraints); + $sThought = $this->decodeThought($asThought['thought']); + $iThoughtTime = 'Saved at '.date(self::LAYOUT_TIME_FORMAT, strtotime($asThought['led'])); + } + + $this->setPage('write_thought'); + $this->oPageMask->setTag('font', $this->getSetting(self::SETTING_FONT)); + $this->oPageMask->setTag('size', $this->getSetting(self::SETTING_SIZE)); + $this->oPageMask->setTag('thought', $sThought); + $this->oPageMask->setTag('thought_id', $iThoughtId); + $this->oPageMask->setTag('last_saved', $iThoughtTime); + $this->setPageTitle('Talk to me'); + } + + public function readingPage($iTimeStamp=0) + { + if($iTimeStamp==0) + { + $iTimeStamp = strtotime('now'); + } + $sMySqlDate = date(self::MYSQL_DATE_FORMAT, $iTimeStamp); + $sLayoutDate = date(self::LAYOUT_DATE_FORMAT, $iTimeStamp); + + $asConstraints = array('DATE(led)'=>$sMySqlDate, MySqlManager::getId(MySqlManager::USERS_TABLE)=>$this->oSession->getUserId()); + $asThougths = $this->oMySql->selectRows(array('from'=>MySqlManager::THOUGHTS_TABLE, 'constraint'=>$asConstraints)); + + $this->setPage('read_thought'); + $this->setPageTitle('Thoughts on '.$sLayoutDate); + $this->oPageMask->setTag('date', $sLayoutDate); + + foreach($asThougths as $asThought) + { + $asThoughtParagraphs = explode("\n", $this->decodeThought($asThought['thought'])); + $this->oPageMask->newInstance('THOUGHT'); + $this->oPageMask->setInstanceTag('THOUGHT', 'time', date(self::LAYOUT_TIME_FORMAT, strtotime($asThought['led']))); + foreach($asThoughtParagraphs as $sParagraph) + { + $asParagraphTags = array('thought_paragraph'=>$sParagraph); + $this->oPageMask->addInstance('THOUGHT_PARA', $asParagraphTags); + } + } + + //calendar update + $this->setCalendarDate(date('Y', $iTimeStamp), date('m', $iTimeStamp)); + + return (count($asThougths)>0); + } + + public function settingsPage() + { + $this->setPage('settings'); + $this->setPageTitle('Settings'); + $asSettingsOptions = array( self::SETTING_LAYOUT => array( + 'One extensible page' => self::LAYOUT_ONE_PAGE, + 'Two Pages, Diary like' => self::LAYOUT_TWO_PAGES), + self::SETTING_FONT => array( + 'AES Crawl' => self::FONT_THOUGHTS, + 'Arial' => self::FONT_ARIAL, + 'Verdana' => self::FONT_VERDANA), + self::SETTING_SIZE => array( + '16pt' => self::SIZE_16, + '18pt' => self::SIZE_18, + '20pt' => self::SIZE_20)); + + foreach(self::getSettingsList() as $sSettingName) + { + $this->oPageMask->newInstance('SETTING'); + $this->oPageMask->setInstanceTag('SETTING', 'setting_name', $sSettingName); + $sUserSetting = $this->getSetting($sSettingName); + foreach($asSettingsOptions[$sSettingName] as $sOptionName=>$sOptionValue) + { + if($sOptionValue == self::getDefaultSetting($sSettingName)) + { + $sOptionName .= ' (Default)'; + } + $sSelectedOption = ($sUserSetting==$sOptionValue)?'selected':''; + $asSettingOptions = array( 'setting_option_value'=>$sOptionValue, + 'setting_option_selected'=>$sSelectedOption, + 'setting_option_name'=>$sOptionName); + $this->oPageMask->addInstance('SETTING_OPTION', $asSettingOptions); + } + } + } + + /* Final processes */ + + private function collectErrors() + { + $asErrors = array_merge($this->getCleanErrorStack(), + $this->oMySql->getCleanErrorStack(), + $this->oSession->getCleanErrorStack(), + $this->oCalendar->getCleanErrorStack(), + $this->oMainMask->getCleanErrorStack(), + $this->oPageMask->getCleanErrorStack(), + $this->oMenuMask->getCleanErrorStack()); + + //$asErrors = array_map('getCleanErrorStack', array($this, $this->oMySql, $this->oSession, $this->oCalendar, $this->oMainMask, $this->oPageMask, $this->oMenuMask)); + //pre($asErrors, 'static error stock', true); + + $oErrorMask = new Mask(); + if(!empty($asErrors)) + { + $oErrorMask->initFile('errors'); + foreach($asErrors as $sError) + { + $oErrorMask->addInstance('ERROR', array('error'=>$sError)); + } + } + return $oErrorMask->getMask(); + } + + public function getPage() + { + $this->oMenuMask->setTag('calendar', $this->oCalendar->getCalendar()); + $this->oMainMask->setTag('menu', $this->oMenuMask->getMask()); + $this->oMainMask->setTag('content', $this->oPageMask->getMask()); + $this->oMainMask->setTag('errors', $this->collectErrors()); + $this->oMainMask->setTag('post_token', $this->oSession->getNewPostToken()); + return $this->oMainMask->getMask(); + } +} + +class Calendar extends PhpObject +{ + const CAL_YEAR = 'cy'; + const CAL_MONTH = 'cm'; + + private $oMySql; + private $oSession; + private $oMask; + + private $iUserId; + private $iYear; + private $iMonth; + + function __construct($oMySql, $oSession) + { + parent::__construct(); + $this->oMySql = $oMySql; + $this->oSession = $oSession; + $this->oMask = new Mask('calendar'); + $this->iYear = 0; + $this->iMonth = 0; + } + + public function setDate($iYear=0, $iMonth=0) + { + if($iYear==0) + { + $iYear = date('Y'); + } + if($iMonth==0) + { + $iMonth = date('m'); + } + $this->iYear = $iYear; + $this->iMonth = $iMonth; + } + + private function getThoughts() + { + //TODO essayer avec selectRows + $sQuery = "SELECT DATE_FORMAT(led, '%d') AS day + FROM ".MySqlManager::THOUGHTS_TABLE." + WHERE ".MySqlManager::getId(MySqlManager::USERS_TABLE)." = ".$this->oSession->getUserId()." + AND YEAR(led) = ".$this->iYear." + AND MONTH(led) = ".$this->iMonth." + GROUP BY day + ORDER BY day"; + + return $this->oMySql->getArrayQuery($sQuery, true); + } + + private function getUpdatedLink($asParams) + { + $sCurrentVariables = $_SERVER['QUERY_STRING']; + $asCurrentVariables = explode('&', $sCurrentVariables); + foreach($asCurrentVariables as $sParam) + { + $sKey = strstr($sParam, '=', true); + $sValue = substr(strstr($sParam, '='), 1); + $asVariables[$sKey] = $sValue; + } + return '?'.implodeAll(array_merge($asVariables, $asParams), '=', '&'); + } + + private function getLink($iOffset) + { + $iTimeStamp = mktime(0, 0, 0, $this->iMonth + $iOffset, 1, $this->iYear); + return $this->getUpdatedLink(array(self::CAL_MONTH=>date('n', $iTimeStamp), self::CAL_YEAR=>date('Y', $iTimeStamp))); + } + + private function setMaskItems() + { + //week starting on the sunday : offset = 0, monday : offset = 1 + $iOffset = 1; + + //days in the month + $iMonthLastDay = date('d', mktime(0, 0, 0, $this->iMonth+1, 0, $this->iYear)); + $asDays = range(1, $iMonthLastDay); + + $iDayNb = 1 - date($iOffset?'N':'w', mktime(0, 0, 0, $this->iMonth, 1, $this->iYear)) + $iOffset; + $iCalendarLastDay = $iMonthLastDay + (7 - date($iOffset?'N':'w', mktime(0, 0, 0, $this->iMonth+1, 0, $this->iYear))) + $iOffset; + + //days with thoughts + $asThoughts = $this->getThoughts(); + + while($iDayNb < $iCalendarLastDay) + { + $iCurrentDayTimeStamp = mktime(0, 0, 0, $this->iMonth, $iDayNb, $this->iYear); + $sItemDate = date('d', $iCurrentDayTimeStamp); + + //new week + if(date('w', $iCurrentDayTimeStamp) == $iOffset) + { + $this->oMask->newInstance('WEEK'); + } + + //day within month + if(date('n', $iCurrentDayTimeStamp)==$this->iMonth) + { + $bThoughts = in_array($iDayNb, $asThoughts); + + $sItemClass = $bThoughts?'full':'empty'; + $sItemLink = $bThoughts?$this->getUpdatedLink(array('d'=>date(MyThoughts::URL_DATE_FORMAT, $iCurrentDayTimeStamp), 'p'=>'r')):'#'; + $sItemLinkTitle = $bThoughts?'See my thoughts on '.date(MyThoughts::LAYOUT_DATE_FORMAT, $iCurrentDayTimeStamp):''; + } + else + { + $sItemClass = 'disabled'; + $sItemLink = '#'; + $sItemLinkTitle = ''; + } + + $this->oMask->addInstance('DAY', array('item_day'=>$sItemDate, 'item_class'=>$sItemClass, 'item_link'=>$sItemLink, 'item_link_title'=>$sItemLinkTitle)); + $iDayNb++; + } + + //column titles + $asDayNames = array('1'=>'Mon', '2'=>'Tue', '3'=>'Wed', '4'=>'Thu', '5'=>'Fri', '6'=>'Sat', $iOffset?'7':'0'=>'Sun'); + ksort($asDayNames); + foreach($asDayNames as $sDayName) + { + $this->oMask->addInstance('TITLE', array('day_name'=>$sDayName)); + } + + } + + public function getCalendar() + { + $sResult = ''; + if($this->iYear!=0 && $this->iMonth!=0) + { + $this->oMask->setTag('link_prev', $this->getLink(-1)); + $this->oMask->setTag('current_month', date('F', mktime(0, 0, 0, $this->iMonth, 1, $this->iYear))); + $this->oMask->setTag('link_next', $this->getLink(1)); + $this->setMaskItems(); + $sResult = $this->oMask->getMask(); + } + return $sResult; + } +} + +function arrayKeyFilter($asArray, $sCallBack) +{ + $asValidKeys = array_flip(array_filter(array_keys($asArray), $sCallBack)); + return array_intersect_key($asArray, $asValidKeys); +} + +function array_map_encapsulate($oData, $sChar) +{ + if(is_array($oData)) + { + $asChar = array_fill(1, count($oData), $sChar); + return array_combine(array_keys($oData), array_map('array_map_encapsulate', $oData, $asChar)); + } + else + { + return $sChar.$oData.$sChar; + } +} + +function implodeAll($asText, $sKeyValueSeparator='', $sRowSeparator='', $sKeyPre='', $sValuePost=false) +{ + if($sValuePost===false) + { + $sValuePost = $sKeyPre; + } + $asCombinedText = array(); + foreach($asText as $sKey=>$sValue) + { + $asCombinedText[] = $sKeyPre.$sKey.$sKeyValueSeparator.$sValue.$sValuePost; + } + return implode($sRowSeparator, $asCombinedText); +} + +function cleanPost(&$asData) +{ + //get rid of magic quotes + if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) + { + cleanData($asData, 'stripslashes'); + } +} +function cleanData(&$oData, $sCleaningFunc) +{ + if(!is_array($oData)) + { + $oData = call_user_func($sCleaningFunc, $oData); + } + elseif(!empty($oData)) + { + $asKeys = array_map($sCleaningFunc, array_keys($oData)); + $asValues = array_map($sCleaningFunc, $oData); + $oData = array_combine($asKeys, $asValues); + } +} + +//debug +function pre($sText, $sTitle='Test', $bDie=false, $bLog=false) +{ + if($bLog) + { + file_put_contents('log', ($sTitle!=''?$sTitle." :\n":'').print_r($sText, true)."\n\n"); + } + echo '
'.$sTitle.'
'.print_r($sText, true).'
'; + if($bDie) + { + die('[die() called by the test function '.__FUNCTION__.'()]'); + } +} +?> \ No newline at end of file diff --git a/functions.js b/functions.js new file mode 100755 index 0000000..dbb4490 --- /dev/null +++ b/functions.js @@ -0,0 +1,54 @@ +function emptyBox(element, text) +{ + //var textarea = $('#thoughts_form textarea[name="thoughts"]'); + if(element.value == text) + { + element.value = ''; + } + else if(element.value == '') + { + element.value = text; + } +} + +function setHeight(element) +{ + var padtext = element.value; + var height = Math.max(300, 130 + Math.round((padtext.length / 85 + padtext.split("\n").length) * 20)); + //alert(height); + element.style.height = height+'px'; +} + +function goTo(url) +{ + window.location.href = url; +} + +function addInput(form, name, type, value) +{ + var registerInput = document.createElement('input'); + registerInput.setAttribute('type', type); + registerInput.setAttribute('name', name); + registerInput.setAttribute('value', value); + document.forms[form].appendChild(registerInput); +} + +/* +texts = new Object(); +texts['thoughts'] = 'Talk to me.'; +texts['login'] = 'Nickname'; +texts['pass'] = 'Password'; + +window.onload = function () +{ + for (i in texts) + { + var id = document.getElementById(i); + if(id) + { + id.addEventListener('focus', function() {emptyBox(this, texts[this.name]);}, false); + id.addEventListener('blur', function() {emptyBox(this, texts[this.name]);}, false); + } + } +}; +*/ \ No newline at end of file diff --git a/images/bubble.png b/images/bubble.png new file mode 100755 index 0000000000000000000000000000000000000000..9e4dce901a77b45ccc7e4d90243dcaa423cbe9bb GIT binary patch literal 22072 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 z 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 Du(tyf literal 0 HcmV?d00001 diff --git a/images/bubble_inverted.png b/images/bubble_inverted.png new file mode 100755 index 0000000000000000000000000000000000000000..18375189607ba0019a1fbc0e5fcd7b25b5a6212a GIT binary patch literal 22464 zcmY(rcQ~8>7eAb!LhV(xDz?^YYu9cmsz&Q$)vnsRN`%-|t15PFt)lj(h}~A~)-DoM zP%}i0i1FP0{;ucuT#xGt@rV1q-{<{4=e)*|I3ojXx~rU5K_C#Fu8!tY5D2^nykDlG z1is5ZS@!^bQ25=~{f`RxLQuVk1%aR-T}_Su0&{or;JMr;P5ogeQ$yRN$4>QlYF#So z*Njl{$U-uy@T*tr%as39S6A0!WZfe&vLdw@5#ie;W?D;VB_;K*2ltulMN%INH{dPJ zI@G)tH|D3B0?eeO{X!4Q3=PdN!MkOQOibj7h)z?` zJXj{Mq2}XTx@U4Mm)|K~*vnh!ALSeug0+QHPy(McYF;NnML@8R5g>RUubc+9H9|%M z%Z|QAgU+-KD8pyugu!AzicYX;ag>S<`dDNzBs;>t2D@DabPju5P1Oew96a|jFrnVHuT61vb+z<`;}yd_()q#fL+9B0 zp{W!bTA&(`c`|F5@@jZ%-HAf}o9fdSax_U${49lrYAO!geH?86<|YU7Sd?F`@jepv zwTu&;||vXWoUX6HZ}E; zuoveP-?;rjSC5oTFi-Pw#d46Bx*&N zir|$PXd)_*Uc0_SH+9Ep+d>!F;x1HCXk{hQ(eS4!*P_A6faZkUSWtH`^~Kv%!7|N^ z)h8)}>3S(LRw+39I3*9>0r%`?4)LVpdlnh6H}^mA#Q(OWAxA?F;#=>8CMkiSCj&9~ z{CmOEd|?FQnJ@7%5;l|4@VripF8&bog}hs0`EqCe#w(;D+awj?NP@u=9ZcbKtj~nY zs;3eA0;UfC+uLA>8_x5a{fjz7Jz%rQ`Y1}!i2wLFUC1?!+?m_sXidE_91&IGswAUt zNoN-fgatD@+qi-4QaPF03G38r$NlD|zr-ZUpLtujZnzE{{jx*{^Pb-mOMgSdHuUja zYzC}A(=A+jEn24K{7p93CjGQbmFRmmWgQa}-6v`PmRnJN3#f0u&ZC7~DQCYG7{>(5 z=#%c--k*>ONWNK@pl?rjPY1deLxEdad>;-RSEJvcnnj1_iZ>>rxCr;mhc1J+@KNmf zVWVeurqgHPi(#4yhR5i@^S4_;D$z)W==*daR;?#jt?%IqsWen?m@PCuFC0a3wmp85 zrcJzR9b~z&nrVYpy!hhae8TG3Jhsjysr$6}qiD>dl>dY|Y|@@J7DVdU0A*Q7cN0`= zFf}=nT~cMt>L?Lz%|t^%#Kl4j(uAvCT=mheV(>ycv(v4xIfBNg%xv;Qz7?xw6=W8` zJfKTzw{o?_k&o1*sR`tK#S#@jQ7vDXnSlid*eugkm?3Or5hr^VJ$7~(W9v#^*AGU3 zwvaLr;=67z$hSy4y;W;qG9_CtE(NKjPq~mIYf(oUzM~@Sr^`IC#O%66*^s{iX{eTd zzI$~Rls2+uHYy=0c~5BRn0NJ;eJx&F5A{o^*?IcY{7#-#L?ulbH zi~ErQ7Olt#QEqoL{{|xv2%YRxLaLzM0cjxJw)iQCfmXf~@dqC{AVh|~A!hZ{+f4Ga zn}QFpeuYf99m^wnLLB*7_h_w9O9`bU&hOEies$8yF;*dP{44e1(8!32-jlSSWq(tl z_-=6xtmB!E^KB{8i8*-s{AFQqPe`P(=8lNh&Kg1 z5>@d$?je)SZj>JRKs16YJQ|cA{<_5~tF}4E$T#w=I|>1uSB#gZ@S6PlcT|%qxGO#f z6oQ=vm)l(l)t!X#p`k~5HAqLrex=KgA%f^FeMVeW0wWI7#$>2B8sDbMEdToc2Q{&H z0&DmUe6a9unfu5jX9u!)2Eq;SLL4O}?qKlYxA5SzFLjDEwusHMpG6O?N<|;FnyXG- zaCAvqWv3k|p-=E|{@rhB?maf0LOj;h^JsBG$mzVsaw6CP1Lm2GW zS)Suwh@cr&37(aZw}!b}Sp2fcC&qw5#24K_QsrWqfH1Ie86g*$uSSP{5FP9qP7vZu zX2NxtZ1NQ-bi4lr!Jf-XLknzGGrCwr=Fp*MyvMx0n=J;R(CbuheWpLfTySIypt)Lr z#{^&zvGK8igSq$$^zvG`9@u=bLJ%$TIf5F_0P6f^=cz1WdT{?}hI|*CZhOa+*WVe8 zCc5lzv5(w)@m)VfkSI_*L1W~+Mn(7zw4}UPD8598ADQINJNKVSha4hI*(;2S5O?bU z3Ov|x2wO8w;!_GW@hsk#ng6&g3RDlqRau>44^xHTUHU3t00}TJ@PGH(zapQ~=T5kR z_V<;&7-+%gr!>UZBXWM>mU4ZIpEwD1paEXF{JwbzCEf}YEv9O5Hb0Omaskcy|6PVw z5nTiFxeJy3>N*P7t4;u5lt*_HB2JM^eL|dT`fFmgllgaU!uQo8dCMLDMsH%DaO~bF z8IqxJZzp=p_MYqbYhIUZr%Mjur2?n_uyiB;x#3-f3T`JN7<=~~oZ)$$_6<6WP8dn@rw1A7r1$3UPz9xD0bR2x=j znrk%M2zCe)Hx;4xagl>giJ#jGr7#d92So#&$t0`?QSv_?bKzFr-ZG{ko~W+S#vrc$R$x+Z==teo4zp9oe%S{@;0Z^l*NEN_vXNl< zR#DH1+*PNowz{qXbav!m+|w^qNhlgn+T(l$`{CdOo0DLBdkvH4o!_qcK;R-T*LnSC z=3AV@ZX6d5c@*NRAlyVZHZ{dcJKO#bPv@<9Z7p?ot8K|BeIZAAvTiYknQK-pxXSkq zQW%aSTStONZ#0|kZUn5F~yoNojO+P;l|5i&e|?t>J7&va*J15!8F{oDtVowAt(-?LNq6>)vE>J`P_se;3g|OfIEpIGEFr=uo)Y%EjXwGFkY%l07 z9*OvkZ24W}A0mP@997x7Apb?lT^5159>Pv0%3=D%)WYJ4jXlFHuEmcz^0SYSNhl$7 zKc^5nXI>Dk9Y2dN9V^YHak&@X9*>KDMgez#)4+#BRh^pZ4sJYL`d)kYm43bA&2R6M zxCqS8AvJ8g%IAf5QUrCK)D(2Tfa=&ZY|Mb-*ZsNG!(fjB{u4m{s$mPN%x}a(`qRl4r zIyUS1G02wZDWmd{sPm*C^#`i-fy}rn4|+PZ9 zAVAOP$ayAVAUK}i$C9xdj2qEdy++UyDAkPxDT4wSlp*R~4#o{0ff)@VNlU;D3@bD3 zT^@9Xv1nlDpc>ePwZd?O-DcX&VgL$5-hK>>YNn%O!BuTKapG9IAYS_hK3cQfYM-Br z&pogqo7Yz3PtBm132QAIs%`8C3e?CsP=K?5mz&W8tdiaI_F_$XX679lj?D4tKp_om zgw&ho=^X>nUQHaeD#=1j1m&w{jNsO;BlV6pcbNbD=j6TvyQP9+pwVJmuhZBNwUP37 z-?uh-tBv+y?gH zv+=p_$>Yr}E%<}8@p6Z@XPa$2W_N8j9+BHq-ZLGdgYHy)vmLguUU~Y{T_xo0@Lv4% zxY?GA;eY$@vz{O+p_VLUEU#qKqq$ z{ib>{O61~+p!W+&KYsXuT?{{bg8!Zx7bn-EeO1Ex%KJwTGq}IVy%vDyP|ZFYNcxwr z!r1{NFvo+=7sGta{FZ{CaRS4oYze9ohgOH)HcU>3s}|g)sdTrR34Z~1i**}xhy_|5 z=^-+y*${}jf&x@Z$YIkoufW2h=jWlUQrN=GeEZz`fh>3y`E@slobD-_E7T+l1RrQ~ zEiGT{9PAc>IqCI}GDk>|BfG4QunP+d+r$X|@to}T7=%uG9>$4)!!DpZf z%*nG-a)>=A%RUgfiJnA2L2R_ORL)9&%r6#GBLDjr9po}MNg1U~T zatn)NP_)Q2P@k|P6vW3dK)Z5=s$+S=P07tm%QxBo55i{)=X7ZQhh;aS5WNManCA5J zOUn?i;uZR-2bLBm!+k~c*>^Y6fJGUThhEMI>JqerGv5dQ1BDZ06!3k|@@3o-nmZn8 zI8fOBIo%Q@P91$84?wv);cn~yk|;qCLbw4!L~k_L@5g*oC#`MO+&a5xF(esiXk5U- zU6-F{pJDG$Hs1sAuV*CUMRW`D@1WpwMMWgUIIb*5x3HRCL^LmqSZ}#S+!7mxiC&k zWF^UehT`8U8(ghRaebHO*}{xt0SbUeae}Z))R|>@d8gzMfd={3E%^sB>8rR^Lq$pM$KoCb#gB4obauTEexSPAsl{Hun2tNmB#xoy zXX?CP8r=_#D{-qCtUn`rjL%cD*)X7hvkT?6@C)2MZVnsh6*0`c=X#bHp>CHUEoRg9 zds0wCwQh}?urCkD9&K4r??szzzRRoOU1TS>o4*CV(*oFbP+W6@ix0#mWU~hzGnyOf z5D+l^a!NC@4|u8|ML zf3EJN(7+albf`q4YU?dbrYs#TI@#5e+J$2ja6F;-x-y+A{YO-=baFItEv}z7_&h6S z_l8=)q?Dt@;7c!8QFUxLc_b=PHWCrGK^uwKh9^M_kN{C@5Y)ZL(XGfQ`=7+nc&5|p z3bO__8TNd#Dtx3O&u?)@o(F!~(iv(C)H|<518&~?%%Dd|m{cU<6RIJb0^S@6T!vBv zr$({I0?MJaG^A99T*dL6mPt9XM;v^%)KJ)@L|(32hK2n7<(y9#3tu$b{BkoAk;{)} z!CAA#O6nu!CDf5E((8)vzmt8@F`1&&O?iAb{1-x-0^V;*w;VFBKf@i;qv))WS_yB=Rhm*P~D^|%wDUCW$`^+v(Wh)VHTuq$6zAL(_ zfo;Q;CdjFrbf#W~&lKshT!~n@zx>fF%z=W4z8Z!(AL#e@ z8t_1GLF)F=N+3!+KWH`VatI&hbFv*}7}v)#)MBv7h;y)PveZJt#yK^x@DVUAks^d^ z94W6nC3xlIDv18do(yPYnp)5A0S)1!5Os3e=YL?5c4+YGJ9E-ccZO@Y^^Auzh72-^ zSDF4@D##rb59OWD=0XRPh^-f)%5Ox0>jLo#HCgEDumqh+MnSMy9Iu`Z%ta}L{N2DN z2#h9x)2v~u-xkOFxIi-c6E*S4=Sjoe4~K6R2?(|!>qOcZh9kO;Y~Kcl$-3HY!d{9)u?acih@7ja0ck~u&-3%%+M$ey=emikKIClw1oac=( zz2FE_`FUZHeLSlMTj$NGr#>y&KuDi@Rq^4g!kX6~jI6bj<&tK)bWgmvDSiqgyQUaD#mYX{ONp$j0HYQKaL{6M$12=bUZ=f&+pXRs*fABx=Fj$&w0>3&6wf? z2xMlVme$f;{-5%Yz>Tyx2a)gh92g$6Bsoko;zl@c#3JQY;{e@QO?%+aR}G}RXFim7 z)#~k)nln8JPDtl+3WJfpd7TQ8t}eKUFQ}rtjgy7mB3mCrtVe=TE|al?6-q1~D8LUp3kE5Xr8`h$H1C912bU4-92epv6K9UNRM8?6xf%&p*(^ z1;PPt1Tiu~7MOAS?cKWo6f@JqyKIDNd_Oq_{D5+Yb~By@mv^d-Y$;O>=aT~WubRD0 zeRk}f@Spye3NiH3BV8Ds09t2Be-Wj%+?tnXeK9*t#~n{12cBmNSVQXFKlD&^j=YPr z(LaPcsTPUSKYSdGdi}s*x){Ecw}U>F(a0yaq9p&q>%nL#7hZ{(l6CX;_D186EglCw zuXUh+Ln?qAO9!~z>@_L^1w6zz67euD zI!c2QUQkWVk?dkc3GKKT)eh$9Ub*tlUPGXUdsYNJPvRy;0X$p_DT3xQ2jqZn@-2W> zQFT7)eOcI1?3D1}lKTv6t&Tl!{XtJ?^UH@%EVqpE;U}7^H?Ap@26IT&t=o~Vs#?kV zmfN-ukn)+qXr&>!f0wh&;<7^?|LEd_z%$qRVCw~w8l5dtjr8H4j>nW!V6}^qP;V~@ z8+1EqdqLd>L2q@1k?aSgQ2vZ_F08O~y)|=j?mP<6b|20>PxI9V-7a_katkPe2wiek z0#a^H9DFSj(@RK*T>I{6T0%kaeYjtu573G^VYI+G z(l9cK0v-jZ9;f&1XHe0o61Pnf?*+-^;Nz$Oya6xkg`N+s0a!7^ZvVm0)w50*$b&V= zCU5|ZoWe}3%v<^uZl$rTGo*?u{mBdO9kg&3%WHXlZJ>WuhfM#w``FRr-397)&Ua8= z=Xoy!Q-cZ+eK!srTk&Q>T9MBE*Eh>P+3B^8$j4i9$b*AIIbJc)eH$a!|5X4xah^@FLD#&gCe#;W8y*FgK{{ANj3!)w}$(Zs6BhItZQ4ZI#Gkd;#mOA={PMyYF$_MXnW_x444j18_ML~RD zB^kmZ;GX6w9!?~I;U)Qv-(IXER4I2iV5nLDtQ{k~xPV@GkAo$Oe^O%v`Y{GyC zkx;aQ7Cc)_r6ejK40v#uume)i{1iD@{xJzxBM9z0DWpcqCfm)wpi`yj^ECf4S8vAYT7N#DS}q2F+jFF zV{`s63+Mvci9jQv`)dDE^np!pLXBk5dL>Qhk&YSc*aie)jOz>rf1a@paUDNvsM+w8 zit^l`fO=C}(k*{DvrEb>>wQk)=lX3ZQ=FJf_(Y491(644i%30JY&E#sJv(T*dJyFYZjUS!N({uS(Wh(MjjH8 zsG{%Ggc1Pc0cMT&eCt+s-toD^z=Ra4z^~Nn|D6SB=A@mI1-bR?1|O@*Q9=O;pz5&0 z8*)J>gjV8E8Ev0<5c~M$IL$PsXYn|?<)9t}osyS}sc(oJZyZ=5BwRfpf2aKNGaohF zteP1YBZuqQ&jMgl`IO~~$paQb6J+z*<;%rB-t&`s+jDo!8-3ddEet=3SlDzMHS@lE zetvB1@OVYz6Swt(5}Ne5<+d;Mn4fH)k)I|1RiuANW3+8Mh?Rs;wR(AxRV1ab)i@wf zaf@&&p>^r7oOv$EVbFTb0ZWZzd3@>S)~gzF%hq)}LNc+?UZbKRX2#W%?!bT(?mGUc ze!Mrkg=_xPzN%)IY<>D%8fqg)@5UWfB^~~(+_dI56@r*G!B0(x&_l1sWKW}3x|#WJ z7C2o)dL)^wU+ny{oFEJ*(9B#M_Gp{=2Lwz-_^0x!<3eEq*QMJS-@wk_P1ThdljbMi zTD_a^>PZ`)reFGauBsV6TD0d?D-{vOwAqxIuXYYthe{v5)I!JV94qK3;4}>XT6qGH z5-#+rwgbO$ZdQCeNEn=tERYsXLLF|&dnxXPC8@O>6^x-8nLPf3KL{)%Px!*s-8MYm zGy5~BzbZg!q2Im0vPPR+M!Nfo_MohI#t-rsfvW7g!K87p)IT$$esDKI0_^`d-!z zPsorkCtzRlEFPI(LnbYf&o^jWnXc5h{i5E$7Oo6pcOaNlnC+NFy5PxH_opqqv{vZ% zedH#QG#Bmy*$?M=at9*0L+<7Dwq>$PKK2a|5KF(@UI@r;plRJ;fAWr zGUV9gfa`NJpg5js$#xlcQj2Da)7^-t@yUo79>iici&P`fDpSc&^@jOSG)?Hj~ZRfb3e0tnF~ zWQ*nhsgy)84LreC*WXt3)d#~T*amO@Cu%X*a8>!_>_xjCAb3Bo|LkXx-40^i`0rka z9qz-y9$@msZ~+DB4E*7sfrRZm&IND@W||M(-|Vs1te#QK3o;U1a!}xk@Bs8xtdl=0 zssV&c`YbMG`xl2{$h^irYJgUfX2My&=SM4v=^|nC@gb?eD1bi|;mI>Hozkd8o%MH` z@=WueNv3b8aEXxu5WeediC6e7hi^O!K;1O3(KjPe4Jp9iRn5w05s_n`T5&uk zU`iI88AyR+d;ji4hV{RGUZDYkhfu5hGY(W=t|zjGp3k$dqIDS5|J*YX(ItbmU%aW8Q zzoi{c=|cZ@p7oA?F0&(l1jFb!Y6wDP@sx4%ue3f`KNVnOd4srL5Yr%s(tVR!si|=1 zo%!66D#yE-I3HTmN6j|{U(1&13p-#xg+zXQCDOMq%tX&vFjl9l!X47@s`G}$`O&;9 z$Oe?~H8^FtwB%sok95;(1hcB1)Lm@cDjR0*A{c8Yok$mamcMw}R{!x8Do@wJ`M1<_ z??`?)X{0O`*WvC^t4XNtWB@RZSXMHExeM|SPu-v?yxyJT;b)bMBHgQdxbQ#ZqY6(( z8P1kN?_R?A!p8?zw37;y?f+WA=oG)WebB*L7g0YXOy>)74g{x;XIRu@!-nwE0{rj_ zQPrS?)^^r`QlXS%aiN+Xd@4V@;SE?P^Emqc7>RXt<vlL|&lin%<0!zzb@m$qfsIF*pm$HrE`|F zaIK|i#a|Xez)K@IN!mJqw{1D=Ywde~G1oV!Dp$afm1B-XOm0Td!Ycs%odu`z8uhxU zrP|8sqeg{%6snk#4!5Ib%tTPF-SxZpV=gzVvWLpYV#Q6SWGs$6s2tx6E+=*O_=kt+ z>Apr)ZM@RJE>S%HmCJ*(K6x*R*3RNZBa>|OkS$Mz)v-#8K%@RvbK-Qrj|B7~Y@uw< zm;wgL-u{EAvgZN%6%z8n&fPND&|U)zjqPPgk78Jest%eSw~IoB2yW36D4#gIr6L4) zW>*6k%|*bN4}fnSF(^68AHO$4bp8k72417CN07RqH)y3UB$SS1c;)=uqC13`|CuVK z|6k-8UZE?pv!y*Y5w4ft4Rikr%(tjfK&4b43P%F;ujcf*u>g2MkM0WEec_AaP`=zF zB!eX%+ET2Kui#H8tq=P6=twpmU*smVd_z81sg@5P6@4RYIdLj$DxE3^xny#GLkY1Esj-apRLn#OxsBYm~1B zOKSuwq616`?{oO>fR4HEc6g^WuWO(&KaX5T2)85k_~{im@5detO(Buvz;vq=sT+j+Kwv2(Ad{Fc&eI2y@E7;0PNIJP(pHBjkq|OeD3+IEqf{S*G`ht zW^qG@Oue)Dorv>T*QW{Ag&I?nSa~ez5APZ!-Q26c)?e4#KNPfmv%#Kt1T^DllFEq= zFO;+NB*VFD`v=boYOp`nQHwTq%3to z{4gq22b)#=+L39XA0J^N$lEn_QlWG-o~6;xHbS$zXnQ%>BGtBevldj3&(@QwcfE@p z6U5^AJC9IV(W7(D9JDyT+Sqm$b+K?KkOXLs@xmzVv|?Tkak4S^j6s>7?w;b8asAs+ z`zj+r@2)t0A_e{Jt#j_T$*9&$VTt!Vu>qv#+rfs0hAUMt)j;`K39G3A)%RM2qjhiv zZ%X>*eh368m~5JXl6-{g7ElyL55HemxhsJSFX5RB`}6mV$%IXj{+V#HRXjiOlgy)J zl!I8lORW~*jrZ@|aLX=HJsqy-I-3_5tET)xFL(5)Q(T!DR z*wq$nP2dfeV!dkrGx)N)K*^m`BR5T$370w!h<$ZzhMLHJC0_A!Qo8)Y5vO^QHzXVz zVk`bcpDyT!HNN>-$pfs%i`KVP=%NfPR#o}(G`NWfS9~uU@+cXnudNn``#?p|b(O&& z4SUu#kV#|ZIpx_UWm2e%(IT~uqv=x6<Y6djIR zk%*^&sjJldJ3@eZ{^%;9BP1jQrn+}h)Pgxc&x4N0T|iti7&>Sp3=?ed&>u)w1R{Nc z23{oj$`_qe9=v*cT~a5{8nZd%jS5>zNVLphP<6Q<>T9pj-NY_99?qtrdK0KXJeK?2 z$*(=R*wn15o5Kt|nJN8iCno3Rijp#VI;JbajMbj5y$* ztz&GWeZ%+wG9%*in{WHWzUry3(SqAg@q=LnDAb7u;V z+&dDl)gD9isCUDNNu!+mefT`NW~kZ>ZwpLt90?%0gNM?b1Z-1s8FH~T*n6i*e(`W~ z+|gYwGNPSwyR&819}7{huxU4!KIW(US>t#(9Dy=1q4(vzp6dr<<>$l|FCRzSG2+Lt zl-=vbtgE@whSdtk^NZINLkK7LMZ8jU1OYIn;th-&4aT$VR4M*A`kUKyalT=Gk!B`~@K{bya?-l!nY#n(pyhCxH}- z?+|s>7jvJ^^hT8&zUub#Jkez-Lh1|vE&1T#O1p`7`&4=gEqn++Vb3x}a+ZucaBhkvPB`^8tqB-GTVEdDFKl^>Pn@h-h8TIr?~U$dSHLz;ZupoF%{!PgF`@SKDJjJH>Yn&p(^O#HF1Dj#9BaGx_Qw=(BCX0yjf zg}22RS+J$H^NCnonjiSLw$E8#>;pPibCC64=w2~ubT(A9AFo_i&YhpR<2?{t=fz6h zAc@{~K9r0=%I9Lpa>S1*cWiS6tez4}Cy8!vDoOgTh=$JuMR+YAe@|4$@}`p;MMi|< zCu?|3UT&j)3HdqeOWjaJMdpi%B;N)2+Zfk~4?3*QcPqjSYhHi2k%?UxpTqu)MB~gx z?7F>ZrAC%Ll{a^HvZq&(^HZS)*U#p>E|iPdC%c|;Vj?Z z4RfhHH#aZ{xTfN5z)xphEFACbLI&Mu5kpA$C^oA4oL@WULv3v26{ACr_B zKE*7wqn@$dIZ{=zlrV6Do0514Ww)1n zxc*!t$$I)8@K0`u#AcS+?rpxp7~A zK~?ppxNH}GGJQQJ(=9 zU*`*n2O$%V2gxIO&O`jPX7Vc+RqcmkbB}FmhbGP~%U(Yc6)Sl^nz0sPdw$-%b-ix&bcrLF z0&&ZU*jc!^f(!i92s^!J=N>v+3ZW7sSJSVZexN8_8|-*}p|?6GbwPL2kG&vyqkjiC z-5#P;vgn)!7Xd82oAxV7cKl`J-MvuATYE{Y^!ksfC~JnmBL5)d!Hz}j+gLNOj!EC3 zONk6~+=~yuNDuwqux4Yj#5_zsWT#z?biGbm>!ta@jH>3x=h7~IP}t@*-;UX0Yywpy z+;VO=J>jj7XJg-a@G1gevsRV&2Os(*+=djsY5x_>6vAM+O@F*`E%efoAt;1{*PI=3 z!~AI$^K1N2CM(;IueSu5Z)y}n2u0eaYf&l=5)V6{r;XT;*b;mBhT8|fN%|BOYkwBA zq5V5{zcqNZi+f#a2A_Toh{qjpQ$EimJ8E@?#QX+zHo5&Cm(wTfr;>sDCRS&5QNOQt z(?6tMCT)7|@Td%6#F*nW$x^`ZuEo-{4A$uxc^Md#a}KfmgRQ;w+voOvJEkokuHRZ3 z6mw!1Y`<>m&uWiBu)q}MNT~u@OA5#jnp@=z9QF@;!Mf%zQni?xNj+_&!97P(4BKuE z-ea9}M=$U+ahm*!#@xu6TApoH*`)Yyv6hIPJLWY~0)WZ#pEvE!mjFQYZ0jLMJ5zKg ze%g8oVLbfI$w(Klzkf$Wosof|@6WV6Sj^%KBs zu3s#DY>XJBtp)cWg*J@9YrkS2KPCgIWWVtT6{25Ol)L3PT0En-W0_rX9tD`nUQb|O zIN6uH00~>PcKa3t_Lp~iH05CQecD6$e|K%-%&}CX$l0i%`7ZEN78BI@M~EDG zmHyG3^Cr9QOWALw!^uMMdO_W983ykYYf^4A*fF&WYHRIIfto?)ly=nNLd>5| z`uUk~MKYg3H?FC<9FD0SfsOFQuJwS>%fG4L0V8@m_7!uS4D^$0_UXQJMFIKHo9Pj= z2N2h~%%@*gXVq?>6q#M9wpV`IORKc==^QKNrkS?9+5BQ9cI)S%K<|(*2ndaFRI{c@ z6U@;fh^{-pfo0O#8=nZ-hzED4@%-6 zl4|!Biu<)|PQLH;*r13qhth$9UXvg1rRmJJNrpTiaPe|0_+BheUHTL52#o&`08ZMk zaw%4~u;0b<_&2v_A4`E3&XXpw{s$%khRSPu1=nz^=SCUDtWF>oKC^=avhyEI6RbL0L1bO0eI5Vc=kuSlPfS`j{8BaflPeFG z$J1Ld#N*PI2n^-hdwpEt^IP)*N`Nnu82c|z~L`J0zGX%w85V#hDI}hUXXDx9Mv*X6L_ z3y3``@kNW#Z(s!b@lG{w<%Ct?(9Ui zoZ-J+QYSIUcy#_Lx7;P$Qp6>By7qb`scJgC5-CF`g74R&5~J9bKuWX0-EBW|x|c#gv^aeLovIow&iWr2dYN|w^ksZ+ zgg@d>)`@K1DYxlb>UFPKY-nk|_7eo*=MVw3#PnclFJ`;_;8o-NU+5VXjbUPdmF@nh5RObq>CO=HfE4B7HEDuvYpOZ70 zVm?a)7IibUYO&FCWP|;j&wOYAY7#K^Wf9w)$nRb*sAV=$XZN4Et4%Vs1g; zC>Ty*e@+qmgKq>AK8kr0fv#vsHw!Q0*hWpVOMVx?lYxrEIyd5_`x9@3J_}Md=m4Tu zS0g1Of(bPjYeMp-75&hPh9E@k6hq*VnNMp!N%nQ8bfiU$@Z_^gvVaP?Wn4Y5_-Z1a zT6;wCi!x7Vs?MjLnlUr)*}oNP3&(@gJi*P8SJ?Tx+q)wfIkp$l7z$;S#LSzv6SaA7 zilZwYXD)6aOI-1fQeHi6JJ;#VO|0hq3xd${*?^8jEjX@si**;;&{FPm*NR#5f>u8{ ztY=t-ebZtQdCQYkKzXbyI1ZicoNFr~@rLZ5_uB@p_-QWAt#m}@*{uY=sQtM{v|Fzn z+>-2C%E`3(i?RLGfAF`wrN#TrBHpsVOKrRYtiWY~x@!2c7av1jnHtIPatqu(xI?j3 zeG5$bfaB**l)7-S!2C|ikj=dvX0R``o~Ibk|B^Y5wFaogN(I55`vj#MfrJSxw)2@L z<;-+s;uO;|oo3tULC>h+Dlq33^kP$GjP_=HJ*b-zqOj%6%M5}%hmJbqmsu8JQRjAZ zeR_Ay&4O=SM@NCk^i(ZuT5zeWi4c9x98v>Kmoy>AR;m7$*mWb?Y=LB*PojVs21D(g z2D{^f{$#NMtoJN=ntZvK-s8tJG5!f?1(mZI`4*eF=Jlnb@>}1F?b+|%PkG(4jgLmb+li1sE!6G z;!R0LeoR47)7EmSO;vTJ=*a2Ch6o+$`^=ij;{xT*+p9_s`IGNH1lHSu4{h}5e_+^o z`YoHzb}IbJ6>cn@-QL=gmzJP~9xq51k)Of@4y2z|{LHA{Sx%3EypYjfNt%2@k?#c= z|FD-t9{ZS{@#>}2ebkjoy$UL(Sa#@LbQLcSbSB$$*a66C9{m^wwRXQ@^x*at5njvC zh2#c3XZ->zZmJW=&PtFVb6i<_X{q;Wn?8xXgM{Cy={ndS{k~?J-`siy;QNtzW`Qs` zg#Wnx0Z8V9`+Myr<*jE1fdkmq(vm7vW1tRw`OePH{A=9Ex?-V>AedfLxRU`^mXNG~ zH}HOdD{oadCopZ8j$I+yU*YRUtmkLv2lK)^cd**|i)^$MY2MsnngeG7PHeo0AFuDn zkLrHvDQbQWx2$wVqaw*d{&~+9My|Fc_9R* zTF**Svkb8t<%5_A1z+BM;!mfKj{woz#VS8s)9j@HE1U3L_PmI)K3t2`S|s)Y3~@g; zw-1;_pBi?ie%c)x`{*{KQD?wk`)@!a5qp2f|9;QcI)MXVGW+hUK{e($K_JDX8hwY} zl{DFUm032sJ=obwP^;eEqVbRHF{hA^f$0UhYQ1>mkk2_Ky16^^N0H{tZvFk;+ALNP z&~=Dipq9mct)Wfu$)^u;vA~?R_t?O?)gAY(cPb<88B*H~HFv(qz7X)~c!k;gP33>l z=borf2tvUWz96}JW>fmBQh1H76m4i8No4R5I3 z^42ub8dX2@^}^JZ`p;m`ca#Elb{6U#4Ev9)gWDx9fBq`k_^C9m{-33`GrmMZiOVdk zuJvMqZEF)t+-u;hJ%~K{dlg@|l0fCr>4Sy|F#A@7+fR-NRh#kQHp{Erw?lTDzO_p# zlP39OIYWltsT_M?>YUM0ISKqeEYwVj_+COxCX_#XO?};n-L`?L)ll-`YG_YBzxZ8# z6%aGX6}K0^1ccSE1dz+v_eiUN3A0W-SB3Y!XKIcAh<4C6SrxuajhzM_*Am$82TDiV z?*H_uUzWx*b$(-=M=B&YC9~>zL4zUACU5q<5Vuu-wJx8R0F$`WLo3@K~zum z(0q{VEgjW5J2h%ADVef2cnJXk<9VXMSV;;*{obp!$@dx(*(JI~Zy1Jd-9jH&?l`*# zJ1>r^knS;dZe~JVxjN^t*k4nanTZLmXPs+9PMXY1dqRTZ2p-0)-P=&{!S~7Oim=6( zhyMlPyzI(4KeQeg9;!T{NJM#giEmiYhnq0qSOXUE`7}Nurk8yGF^YOc$ zu(XC*JHyH+q1%}@gkhY%+O7aEx;hL0M5QhiUT4S1dnH4qeyLE`fu?{&y5u(f56P?Z zCu+c_sj(T4T3hS7IN4#iXkhXH*{xTv(!}f38~fR5rifX%#5H70KrKO#}4)w$lrP z0Mj23kg>?SxYoT!Jxi2-fBy9Q^psB~_=+8mtv}lsGvk@5ACu$%q?v|>wvwXO)+*Tl z)5CSgL;e5pyUd7??3J0acQ_h0k(JGfjAUfw>@zY$C@Ml`&dTwnJDcouDBIb4oqfjP z_wn_8{Qkc8z1QRQem$R`=WCoUx|T+>wa!*dL^*lHCCMaK-}`YdTOk6^w$5F3gbVWx zQXrKzITS~7jZBYvig|d!O~N3HpS?zY6}?HE44Nxxrq~{;P8hrEj^0K1Dw|ictfP*e zg0Sy9-+(yMh(E?*Clw`@o?PdWr=Vh~TYbPmv+5NcCng()=9qNAsm6FsGCfFdWcjkZ zH$9}zOn!n9u%70@AE}5x00n2|+*T%>g&13VPBPC$en{)%YPe=#b2~4XFuLlBhwQZM zTo9b7P7PHX!Xjm^$bl7YKdCGd8coaz zwKK6)5!*c(vTBjBE;BLRt4W%Tt&Zo_Y2nqimtea#%|jE@;sqwA-0>m`LC@@H76zX# z&%{)JaVtU;)T8WIPE4@g!zow@q_)YyxtL6Wqt;j0h6!0MCZz(xoAURg8pib%`uH3_^~`3BeBXqoJH89rHra!{_AJOA-zRj$27B-ICJhN!B$~`z0kJT|1??$ z4>=1^7Y5818GC7445#Bl&85Oz#gZyLk*=qMt~KoPSL%FfwccAFcFXiH1UQxP3|bMJCQf-22sGgW-)PL{sHr$!n@e%oDtSW~kzC^&@GVt9k=PFnQZsQD z9@`DB%jj`F6O{>|vfj5^J*G6=hT$6F8YC($OV^o`yb-F+Z_#Um!vuOt-O_yuTNJu;-^b`JMjg;Kj`l2#Fw zoO}#fI*!wiS1)s5~^0Z@djGcJO`6AhgpJp}6d( zZ{=|y_+bjNAAw*t6rj&<4N)jPezrU5XcOePAz9u~$x)JC$B?vQyw;SUnn~bS*-D58 zWj+{CU3~8YQDJ@>3CH-MI-}NLnA8~F*T(OqG zuPnpBSwgF}-bdxa47KkHh8HYijLKqF$rSwzGkaaRcoJQSrmaXhV9Gz9$2a)R(w>rh zhJl^w_0u8LMVv6_Aq#uy=-!nZH;w~l)atd5Df`Y|OI)R&nYwuni7|{z4ON|g9vunO z!Tc*$|CZl~h($%|ifTG)IT{aE0TM8WX~S!~-ds$>*+K&L>qCWUsJ*#Z&q&+~pINjX*NJV5;$Tcu_kW@v4 z_atTdS_DpTkQ<(o%#VdDaU|_J&b57;5bCJYmr)2}P+*2D`X1~N<`NaF=7GdqdLX+| zJ|vrZ`c*MHvY@QI8s}!+=xj09?UTN$Y*n#&Kj@KU*5~BJf<;O7UrI+}H@hVAPGQv#vE_q`s#1kw3*cPn*PBJoQ`N<2pWfqgmJ60yQJR}#Lm%70 z6D8Z|lbe-a8sfIsyuB46oAXA(rb+`%+Y~Xr`1cs87_@ zW{5sp6cZm5Nc=H(MOILnZZl^0WR`$$6@|C0B>I&zoKtO2eHnF+!ZdOvl!8I;>2Dqu z=(60ML=Oy=Oici>r#8`pLvCu0zf1AMc+j>go7b)118PJ=LMkAEd>wwSC4Cgrr}Tw1 z*>oX(&`(8lUgP;4qEoYGPX|uLd?;a=7WIb2@9e6b+WeJ+(Z=Lb0NOLhj@!%7#|6Mn zuY127Z7AF?-l!d~ULUz&qMI_N$_)8>N-dIa{-M+s$Vo}rN+~{M;tCA_X~+g}H>$Q7 z-dhW({uyUmX?9~joI2jk%VUMCk%g~|Hc|U@gSEJBo6rxDXJC&8>1v^LlBc4ty2|w( zb*brey&&_f6tZ|~ttY_yqCr#;CyH&f} z8^5tNIW-ygtwA7If_9R4O92X5TTtClTv%gbQS-`$66AVX;Og2d>~Uw6b*WyU8kt!xZi~jM;sBWEnz;#f-AD=N_-W zp7js<4MV^476ewZ%S%6ctjN3_5afVb2uI^*i}hp8D+ySK8=j^R7tHfLxy(_Zzr|J0 zx5@F*%*|-p0MGRYLf`gBTlbP=9t6DWc4*;yl|Z^(GyiC>txP{sefv;0;J`YIO+Bki z_bqbe;Q$Y9lP0sEl~FTe?pqtRqxoLX-t>jd*YcIA`Vk^(!|?6h9W|>thiL|{o;BN- z#7;pD74Hju@mmfQdQ^XY+rF&y16G%A6}_71lB;qrlRZUE4^m>WvsVQb6YDR$ z-O6Q~!K_kdItWRu#)-CdRi1NEg0@zgP;4QGM)bzYq zW1UiY-5>faf7rO{G~6eLh9^2*b?#{qWPf1~-+y(4w?m@q*hy-WCv#jilfO$GExiTg zznT%^=ax>n1O(RDfKuI5CsvuUY{Xa!Qs|UONZYa^C|cBG69`J*ySh-e2MWXDPdvSB?8#68Og{rLI!J z^rDURPH}Qhm^PoLmajws4V(-_U=RX79s|4qm9yD=s_e1rGFeZwgch!7ii5~EOfu$Y z9xJS)ql}od?i77bfL#*L8Qkb@e_SVN^ccuTP0-U<(nuqc0uwuH^nkL<;PQYPe!c!y zQe=U*zHCS^Wa+Cyu-7_}U$Fh1yT{Mjr_c0*lByq19%AV>l3*^+_HHBYodzJ?yk}b( zXd$J|+$B`6i7K4U&n-eyziusdKea!~e}~A-OlZG44GdG!iqo04QY@*n|H(Whze#PD z8V1byiC#68(|K)K=&?^Lu?H}UJKs>kG&!H`d(o2~_p=4QDNNUImQ3p!%OYNZyK6f} zvRWVkK!i2uzM0T)1i=Y?|MW)-Y^3{1Y;nZ#4VWIVT%LCfrfC?+e7kRQ_)lSdZZTeg(WYi`4)fIU zFMVdt0jJa9PVIRRHXqYa{e$81HmPV|!SJAE;y%)BX~GydyBPQ?Icd4;W{q!Bwiz26 z#NN=#D(K|*Keq7QL@#$+ocYh(lvVEkJ77+h&Hj?}A(W9%@J6p1AT?fW zUwwK5^ciFy4tZJ-QL}p+@&ow3UnWb#R=sZjd)1FIs}}lGw(+(7bKvt=i)mydEc<4e4jifl`V&22)zUaOWR?hoc0z|sEIy#Zf21Tjh zZy+(Dy7!?F*33BaiBr(~FoNZIO`}iX(Y8A0Q~%{=!`L{A9U|-Fp`rfK+RYx}f3ieu zOil?czOtKG8xzWG>ifd*&s#3+rkDo;BS4`(GZjlFdyY_;YR!_;|g`zQWSuE^Ng7f&qs}KJ|ET1 z_~zoYItFM;`c_`quC0r%@pp$^5hsV0gVNCx>F(gQv2vogI=?+^tOnjsYle#E(jfUa z%p0DtLL5V5$$zTCb_3>Iq56Q}`_rq5u928##SI@+@yg}jv;nvk`4$N%FL#m65~N8t zg8=tEEyIrd1*+2+-6};V+!D(+7`|_wl7jZ3({9x6b4k9p2e(N7do#H$G)p|cj8$?x zgWcQU+l5g+n?Iqp#`T!Yt*)LndaQzdUa!$z^{ zDo&wg!N1kVxNvJoPa3_F!g%LY$>zMoMJX!>JVG)A!D;;GA*>$y%GVvaEJy4n`)!tdVXYqeZ(R(^aP$&=lH;{imQ9^2920Ar#t{eqKO zvU(R%3cEOGN(N0syeRKM?y-zyqnQ4C`n0q6uc^;H%VC@>Wxvlm%fRCvayZCnO|Rmc zPt*=tqG5a>(y-G;H*uxv#H;rF^kC|mg2QA<)`I*kR zBP)O*RO{A?pv(6pp<{dhMedRi&<`h^Ji{+fxZ#diWDUo(V#{!NMr%f6WJDYFgyJk7 zyj32!wC$oDM_HcCD>$5+IIm%rnn3JPig+R0jr111f9XCVwHTAUMmzz@U?MQdCoWhD zEoVj%^#c}4LpKyRZrg7x@;i^A1c(3x;f_u?yD>dSK;w|`Zx78X&vkfM$@-DMX`F26LlzYm{u9}m$78w~;ni9M!s^k#s}I1F zsh7nE5)Z2@X0+sCj-k(E?h-#ybWmA1+8%kUjuf(ba5*m9fFiRewVAYc0R&W#Q)gT1 z+m~Cv zTd749Pt!Y6 zIVFM&`uDo#D8I<`F;Wx(5K?4yd^A>CUbo+jD6if)qYyHY*OR!sM!K#yKk3Waq4&mE zn>S;6W;X84;Lr3-O4iQ2+tBh6Jo`Y_*aH2{`6G2BW8$a}X~eM*$2^0mq5>bkFoK*Gz3!!alI1PPOq=_+GGtB%sMe;=8VB9hVnUCMY>Q)ES2yP=$G`%;vC~CPLHX z(wA|!iT>7~l>S}Fc=Ky%)~3;Wxgf!)D)RNSqt4calij*Y%U9V^^Z%G$A3Ll6BRJFZ wkrS)*1zZ8a_yA4P^Ej*J+2XSh?NjAf^W`~>rw=oMmb@TMRb7>`htRP90dRFsNdN!< literal 0 HcmV?d00001 diff --git a/images/button_left.png b/images/button_left.png new file mode 100755 index 0000000000000000000000000000000000000000..c8f50fe8a074958d79d4283b0d970192b8356985 GIT binary patch literal 1422 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 b5<>7dwuodBX}(F000000NkvXXu0mjfj2%{o literal 0 HcmV?d00001 diff --git a/images/button_middle.png b/images/button_middle.png new file mode 100755 index 0000000000000000000000000000000000000000..949df5459607a741922fb3ef5f6b6fb6b0470317 GIT binary patch literal 247 zcmeAS@N?(olHy`uVBq!ia0vp^j6iI}!3HGf{@&OH5-1LGcVbv~PUa<$!O>_%)r1c48n{Iv*t(u1=&kHeO=jaaWjglt1YsaIu9sR?&;zf!g0N{ z&zkFy1A~jaa@~ZES-u9XH8o1}hst`xt_tZsGq$@QlXiDX>~D9V6Bs;Q{an^LB{Ts5CQ)7F literal 0 HcmV?d00001 diff --git a/images/button_middle_hover.png b/images/button_middle_hover.png new file mode 100755 index 0000000000000000000000000000000000000000..6eed1ce45a553de0b45df3157c0930025630266b GIT binary patch literal 244 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 Z{}=OXqL0RcN96zj002ovPDHLkV1gJiB#8h3 literal 0 HcmV?d00001 diff --git a/images/error.png b/images/error.png new file mode 100755 index 0000000000000000000000000000000000000000..b44adf4c54220203b95c4aa8369cc296ac18039c GIT binary patch literal 1212 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 literal 0 HcmV?d00001 diff --git a/images/favicon2.ico b/images/favicon2.ico new file mode 100755 index 0000000000000000000000000000000000000000..fe263eb14066d7115288474a3f7eb0c6d1b6897a GIT binary patch literal 15086 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