..- const VERSION_DATE = '28/08/2014'; const EXPECTED_PAGE_COOKIE = 'exp_page'; const MAIN_SEPARATOR = ' '; const DATE_FORMAT = 'd/m/Y'; const TIME_FORMAT = 'H:i:s'; const DATE_TIME_FORMAT = 'd/m/Y H:i:s'; const DATE_COMPACT_FORMAT = 'YmdHis'; const DATE_TIME_SQL_FORMAT = 'Y-m-d H:i:s'; const DATE_SQL_FORMAT = 'Y-m-d'; const HISTORY_LENGTH = 10; const STYLE_PATH = 'style/screen.css'; public static $UPLOAD_IMG_EXTS = array('jpg', 'jpeg', 'gif', 'png'); public static $UPLOAD_DOC_EXTS = array('jpg', 'jpeg', 'gif', 'png', 'doc', 'ppt', 'pdf', 'xls', 'docx', 'pptx', 'xlsx'); const ID_SEPARATOR = '_'; //Database constant const USER_TABLE = 'users'; const COMP_TABLE = 'companies'; const CODE_TABLE = 'codes'; const URL_TABLE = 'urls'; const MSG_TABLE = 'messages'; const CHAN_TABLE = 'channels'; const CONN_TABLE = 'connections'; const ART_TABLE = 'articles'; const OPT_TABLE = 'options'; const OPTVAL_TABLE = 'option_values'; const OPTNAME_TABLE = 'option_names'; const PROC_TABLE = 'procedures'; const STEP_TABLE = 'steps'; const IMG_TABLE = 'images'; const DOC_TABLE = 'docs'; const FILE_TABLE = 'files'; const SEARCH_TABLE = 'searchs'; const TABL_TABLE = 'tables'; //Code const MAX_LIST_LENGTH = 5; //Authorizations const MEMBER_ACTIVE = 1; const MEMBER_INACTIVE = 0; const CLEARANCE_MEMBER = 0; const CLEARANCE_ADMIN = 9; const EXT_ACCESS = 'external_access'; const USER_COOKIE_ID = 'count'; const USER_COOKIE_PASS = 'checksum'; const COOKIE_LIFESPAN = 7; const FIRST_LAST_SEP = ' '; const NAME_PASS_SEP = '-'; //HTTP Requests response const ERROR = '__ERROR__'; const SUCCESS = '__SUCCESS__'; const DISCONNECTED = '__DISCONNECTED__'; const NOT_FOUND = '__NOT_FOUND__'; const NOT_AUTH = '__NOT_AUTHORIZED__'; const FAIL_INSERT = '__FAIL_INSERT__'; const FAIL_UPDATE = '__FAIL_UPDATE__'; const FAIL_DELETE = '__FAIL_DELETE__'; //Chat Constants //TODO Transfer these constants to chat page const MESSAGE_USER = 'U'; const MESSAGE_ADD_CODE = 'A'; const MESSAGE_EDIT_CODE = 'E'; const MESSAGE_ADD_PROC = 'PA'; const MESSAGE_EDIT_PROC = 'PE'; const MESSAGE_ADD_DOC = 'DA'; const MESSAGE_EDIT_DOC = 'DE'; const MESSAGE_ADD_TABLE = 'TA'; const MESSAGE_EDIT_TABLE = 'TE'; const MESSAGE_ACTION = 'M'; const MESSAGE_PRIVATE = 'P'; const MESSAGE_IMG = 'I'; const MESSAGE_9GAG = '9'; const MESSAGE_NICK = 'N'; const MESSAGE_STATUS = 'S'; const MESSAGE_CONN = 'C'; const MESSAGE_INVITE = 'V'; const MESSAGE_REBOOT = 'R'; const MESSAGE_ARTICLE = 'B'; const MESSAGE_NEWS = 'NW'; const DEFAULT_COMPANY_LOGO = 'logo_unknown_24.png'; const ALL_CHAN_ID = 1; const ALL_CHAN_TEXT = 'A.l.l_C.h.a.n_I.n.c.l.u.d.e.d'; const DEFAULT_CHAN_ID = 2; const DEFAULT_CHAN = 'Principal'; const KEEP_ALIVE = 600; //seconds const REBOOT_DELAY = 15; //seconds const PM_SEP = '___'; const CHAT_IMG_MAX_WIDTH = 700; const CHAT_IMG_MAX_HEIGHT = 1080; const JSON_PREFIX = '[\-JSON-/]'; const MAX_NB_NEWS = 3; //Options Name Id Constants const LANG_FR = 'FR'; const OPT_TEXT = 'T'; const OPT_PASS = 'P'; const OPT_SELECT = 'S'; const OPT_NICKNAME = 1; const OPT_BG = 2; const OPT_BRIGHT_BG = 3; const OPT_HOVER = 4; const OPT_IMAGE_CHAT = 6; const OPT_STATUS = 7; const OPT_CONSOLE = 8; const OPT_EMAIL = 9; //Options Values Id Constants const OPT_CONSOLE_YES = 1; const OPT_CONSOLE_NO = 2; //Options Values Constants const OPT_VAL_YES = 'oui'; const OPT_VAL_NO = 'non'; //Search Constants const CODE_TYPE = 'c'; const PROC_TYPE = 'p'; const ART_TYPE = 'a'; const DOC_TYPE = 'd'; const TABLE_TYPE = 't'; public static $HASH_TO_PAGE = array(self::CODE_TYPE=>'code', 'code'=>'code', self::PROC_TYPE=>'procedure', 'proc'=>'procedure', 'procedure'=>'procedure', self::TABLE_TYPE=>'table', 'table'=>'table', self::DOC_TYPE=>'doc', 'documentation'=>'doc', 'doc'=>'doc', self::ART_TYPE=>'article', 'art'=>'article', 'article'=>'article', 'list'=>'list', 'liste'=>'list', 'chat'=>'chat', 'profil'=>'profile', 'profile'=>'profile', 'options'=>'options', 's'=>'search', 'r'=>'search', 'search'=>'search', 'recherche'=>'search', 'accueil'=>'welcome', 'erreur'=>'error', 'logout'=>'logout'); public static $TYPES = array( self::CODE_TYPE =>array('table' => self::CODE_TABLE, 'title' => 'Code'), self::PROC_TYPE =>array('table' => self::PROC_TABLE, 'title' => 'Procédure'), self::ART_TYPE =>array('table' => self::ART_TABLE, 'title' => 'Article'), self::DOC_TYPE =>array('table' => self::DOC_TABLE, 'title' => 'Documentation'), self::TABLE_TYPE=>array('table' => self::TABL_TABLE, 'title' => 'Table')); public static $PAGE_TITLES = array( 'code'=>'Code', 'chat'=>'Chat', 'doc'=>'Documentation', 'error'=>'Page introuvable', 'list'=>'La liste', 'options'=>'Paramètres', 'procedure'=>'Procédure', 'profile'=>'Profil', 'search'=>'Recherche', 'welcome'=>'Bienvenue', 'table'=>'Table', 'article'=>'Article de blog', 'logout'=>'Déconnexion'); //Doc constants const DOC_FOLDER = 'docs/'; const DOC_TMP_FOLDER = 'docs/tmp/'; const DOC_THUMB_FOLDER = 'docs/thumb/'; //Objects private $oMySql; private $oSearchEngine; private $oClassManagement; private $oAuth; //Variables private $iUserId; private $asUserInfo; private $sLanguage; /** * Constructor * @param ClassManagement $oClassManagement */ function __construct($oClassManagement) { parent::__construct(__CLASS__, Settings::DEBUG); $this->oClassManagement = $oClassManagement; $this->oClassManagement->incClass('auth'); $this->oClassManagement->incClass('mysqlmanager'); $this->oClassManagement->incClass('procedure'); $this->oClassManagement->incClass('searchengine'); $this->oClassManagement->incClass('mask'); //Hasher $this->oAuth = new Auth(); //Browser <> PHP <> MySql synchronization date_default_timezone_set(Settings::TIMEZONE); ini_set('default_charset', Settings::TEXT_ENC); header('Content-Type: text/html; charset='.Settings::TEXT_ENC); mb_internal_encoding(Settings::TEXT_ENC); mb_http_output(Settings::TEXT_ENC); mb_http_input(Settings::TEXT_ENC); mb_language('uni'); mb_regex_encoding(Settings::TEXT_ENC); //Passing settings down to mySQL $this->oMySql = new MySqlManager(Settings::DB_SERVER, Settings::DB_LOGIN, Settings::DB_PASS, Settings::DB_NAME, self::getSqlOptions(), Settings::DB_ENC); if($this->oMySql->sDbState == MySqlManager::DB_NO_DATA) $this->install(); //Init other variables $this->setUserId(0); $this->sLanguage = self::LANG_FR; $this->oSearchEngine = new SearchEngine($this->oMySql); } public static function getSqlOptions() { $asOptions = array(); $asOptions['tables'] = array ( self::USER_TABLE => array('first_name', 'last_name', MySqlManager::getId(self::COMP_TABLE), 'pass', 'auth_cookie', 'active', 'clearance'), self::COMP_TABLE => array(MySqlManager::getText(self::COMP_TABLE), 'logo'), self::CODE_TABLE => array(MySqlManager::getText(self::CODE_TABLE), 'description', MySqlManager::getId(self::USER_TABLE), 'refer_id'), self::URL_TABLE => array(MySqlManager::getId(self::CODE_TABLE), 'phrase'), self::MSG_TABLE => array(MySqlManager::getId(self::USER_TABLE), 'nickname', MySqlManager::getId(self::CHAN_TABLE), MySqlManager::getText(self::MSG_TABLE), 'type', 'date'), self::CHAN_TABLE => array('safe_name', MySqlManager::getText(self::CHAN_TABLE)), self::CONN_TABLE => array(MySqlManager::getId(self::USER_TABLE), MySqlManager::getId(self::CHAN_TABLE)), self::OPT_TABLE => array(MySqlManager::getId(self::USER_TABLE), MySqlManager::getId(self::OPTNAME_TABLE), MySqlManager::getId(self::OPTVAL_TABLE), MySqlManager::getText(self::OPT_TABLE)), self::OPTNAME_TABLE => array(MySqlManager::getText(self::OPTNAME_TABLE), 'type', 'language'), self::OPTVAL_TABLE => array(MySqlManager::getId(self::OPTNAME_TABLE), MySqlManager::getText(self::OPTVAL_TABLE), 'language'), self::PROC_TABLE => array(MySqlManager::getId(self::USER_TABLE), 'title', 'description', 'refer_id'), self::STEP_TABLE => array(MySqlManager::getId(self::PROC_TABLE), 'description'), self::IMG_TABLE => array(MySqlManager::getId(self::PROC_TABLE), MySqlManager::getId(self::STEP_TABLE), 'description', 'file_name'), self::DOC_TABLE => array(MySqlManager::getId(self::USER_TABLE), 'title', 'description', 'refer_id'), self::FILE_TABLE => array(MySqlManager::getId(self::DOC_TABLE), 'description', 'file_name'), self::SEARCH_TABLE => array('id_item', 'refer_id', 'type', 'keywords'), self::ART_TABLE => array('title', 'link', 'date', 'first_name', 'last_name', 'email'), self::TABL_TABLE => array(MySqlManager::getId(self::USER_TABLE), 'title', 'description', 'system', 'keywords', 'refer_id') ); $asOptions['types'] = array ( 'first_name' => "varchar(20) NOT NULL", 'last_name' => "varchar(20) NOT NULL", 'nickname' => "varchar(50) NOT NULL", 'email' => "varchar(100) NOT NULL", 'pass' => "varchar(255) NOT NULL", 'auth_cookie' => "varchar(255) NOT NULL", 'active' => "tinyint(1) DEFAULT ".self::MEMBER_ACTIVE, 'clearance' => "int(1) DEFAULT ".self::CLEARANCE_MEMBER, MySqlManager::getText(self::CODE_TABLE) => "longtext NOT NULL", 'title' => "varchar(200) NOT NULL", 'description' => "varchar(500) NOT NULL", 'link' => "varchar(200) NOT NULL", 'refer_id' => "int(10) UNSIGNED NOT NULL", 'phrase' => "varchar(50) NOT NULL", MySqlManager::getText(self::MSG_TABLE) => "varchar(500) NOT NULL", 'type' => "varchar(2) NOT NULL", 'safe_name' => "varchar(50) NOT NULL", MySqlManager::getText(self::CHAN_TABLE) => "varchar(50) NOT NULL", MySqlManager::getText(self::OPT_TABLE) => "varchar(100) NOT NULL", MySqlManager::getText(self::OPTNAME_TABLE) => "varchar(100) NOT NULL", MySqlManager::getText(self::OPTVAL_TABLE)=> "varchar(50) NOT NULL", 'language' => "varchar(2) NOT NULL", 'file_name' => "varchar(40) NOT NULL", 'preview_name' => "varchar(40) NOT NULL", 'id_item' => "int(10) UNSIGNED NOT NULL", 'keywords' => "longtext NOT NULL", MySqlManager::getText(self::COMP_TABLE) => "varchar(30) NOT NULL", 'logo' => "varchar(20) NOT NULL", 'date' => "date NOT NULL", 'system' => "varchar(3)" ); $asOptions['constraints'] = array ( self::USER_TABLE => "UNIQUE KEY `user_first_and_last_name` (`first_name`, `last_name`)", self::URL_TABLE => "UNIQUE KEY `uni_phrase` (`phrase`)", self::MSG_TABLE => "INDEX(`date`)", self::ART_TABLE => "INDEX(`title`)" ); $asOptions['cascading_delete'] = array ( self::CODE_TABLE => array(self::URL_TABLE), self::PROC_TABLE => array(self::STEP_TABLE, self::IMG_TABLE) ); return $asOptions; } public static function getTypeInfo($oInfo=array(), $sType='') { if($sType!='') { if($sType!='' && !array_key_exists($sType, self::$TYPES)) $this->addError('Type "'.$sType.'" inconnu'); else $asResult = array($sType=>self::$TYPES[$sType]); } else $asResult = self::$TYPES; //info if(is_string($oInfo)) $oInfo = array($oInfo); $bUnique = (count($oInfo)==1); if(!empty($oInfo)) { foreach($asResult as $sType=>$asTypeInfo) { $asResult[$sType] = array(); foreach($oInfo as $sInfo) { if(!array_key_exists($sInfo, $asTypeInfo)) $this->addError('Info "'.$sInfo.'" inconnue'); else $asResult[$sType][$sInfo] = $asTypeInfo[$sInfo]; } if($bUnique) $asResult[$sType] = $asResult[$sType][$sInfo]; } } return $asResult; } private function getPageTitles($sPage='') { $asPageTitles = self::$PAGE_TITLES; if($sPage!='' && !array_key_exists($sPage, $asPageTitles)) $this->addError('Page "'.$sPage.'" inconnu'); return $sPage==''?$asPageTitles:$asPageTitles[$sPage]; } private function getPagesFromHash($sHash='') { $asHashToPage = self::$HASH_TO_PAGE; if($sHash!='' && !array_key_exists($sHash, $asHashToPage)) $this->addError('Hash "'.$sHash.'" inconnu'); return $sHash==''?$asHashToPage:$asHashToPage[$sHash]; } private function install() { //Install DB $this->oMySql->install(); //Options $sOptionNameCol = MySqlManager::getText(self::OPTNAME_TABLE); $sOptionValueCol = MySqlManager::getText(self::OPTVAL_TABLE); $sOptionNameIdCol = MySqlManager::getId(self::OPTNAME_TABLE); $sOptionValueIdCol = MySqlManager::getId(self::OPTVAL_TABLE); $iNicknameOptId = $this->oMySql->insertRow(self::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_NICKNAME, $sOptionNameCol=>'pseudo du chat', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR)); $iBgColorOptId = $this->oMySql->insertRow(self::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_BG, $sOptionNameCol=>'couleur de fond', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR)); $iBgColorOpt2Id = $this->oMySql->insertRow(self::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_BRIGHT_BG, $sOptionNameCol=>'couleur de fond 2 (claire)', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR)); $iHoverColorOptId = $this->oMySql->insertRow(self::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_HOVER, $sOptionNameCol=>'couleur de survol', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR)); $iChatImageOptId = $this->oMySql->insertRow(self::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_IMAGE_CHAT, $sOptionNameCol=>'image du chat', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR)); $iStatusOptId = $this->oMySql->insertRow(self::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_STATUS, $sOptionNameCol=>'mission en cours', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR)); $iConsoleOptId = $this->oMySql->insertRow(self::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_CONSOLE, $sOptionNameCol=>'afficher la console du chat', 'type'=>self::OPT_SELECT, 'language'=>self::LANG_FR)); $iEmailOptId = $this->oMySql->insertRow(self::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_EMAIL, $sOptionNameCol=>'Email', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR)); //Console Option $asConsoleValues = array(self::OPT_CONSOLE_YES=>self::OPT_VAL_YES, self::OPT_CONSOLE_NO=>self::OPT_VAL_NO); foreach($asConsoleValues as $sConsoleValId=>$sConsoleValue){$this->oMySql->insertRow(self::OPTVAL_TABLE, array($sOptionValueIdCol=>$sConsoleValId, $sOptionNameIdCol=>self::OPT_CONSOLE, $sOptionValueCol=>$sConsoleValue, 'language'=>self::LANG_FR));} //Insert default and all channels $this->oMySql->insertRow(self::CHAN_TABLE, array('safe_name'=>self::getChanSafeName(self::ALL_CHAN_TEXT), MySqlManager::getText(self::CHAN_TABLE)=>self::ALL_CHAN_TEXT)); $this->oMySql->insertRow(self::CHAN_TABLE, array('safe_name'=>self::getChanSafeName(self::DEFAULT_CHAN), MySqlManager::getText(self::CHAN_TABLE)=>self::DEFAULT_CHAN)); //Install default users : admin and test $iAdminId = $this->addUser('françois', 'lutran', 'planeum', 'francois@lutran.fr', self::CLEARANCE_ADMIN); $this->addUser('test', 'test', 'test', 'test@test.com'); //Write the SAP blog parser bash script to main folder @file_put_contents('sap_website_parser.sh', "#!/bin/bash\n\n/usr/bin/php -f index.php a=external_access p=blogs auth_token=".$iAdminId.'_'.str_replace('$', '\$', $this->generateExternalAccessToken($iAdminId))); } private function setUserId($iUserId) { $this->iUserId = $iUserId; $this->asUserInfo = ($iUserId>0)?$this->getUserInfo($iUserId):array(); } public function getUserId() { return $this->iUserId; } public function getPage($sPage, $oItemId, $asVars=array()) { $oPage = new Mask('index'); $oPage->setTag('version', self::VERSION); $oPage->setTag('text_enc', Settings::TEXT_ENC); $oPage->setTag('index_link', $_GET['serv_name']); $oPage->setTag('rss_link', $this->generateExternalAccessLink('rss', $this->getUserid())); //Constants $asConstants = array( 'version'=>self::VERSION, 'version_date'=>self::VERSION_DATE, 'default_page'=>$sPage, 'default_id'=>$oItemId, 'errors'=>array('disconnected'=>self::DISCONNECTED, 'not_authorized'=>self::NOT_AUTH, 'not_found'=>self::NOT_FOUND, 'insert'=>self::FAIL_INSERT, 'update'=>self::FAIL_UPDATE, 'delete'=>self::FAIL_DELETE), 'success'=>self::SUCCESS, 'error'=>self::ERROR, 'keep_alive'=>self::KEEP_ALIVE, 'opt_type_text'=>self::OPT_TEXT, 'opt_type_pass'=>self::OPT_PASS, 'opt_type_select'=>self::OPT_SELECT, 'max_size'=>self::getMaxSize(), 'authorized_img_exts'=>self::$UPLOAD_IMG_EXTS, 'authorized_file_exts'=>self::$UPLOAD_DOC_EXTS, 'id_sep'=>self::ID_SEPARATOR, 'mask_folder'=>Mask::MASK_FOLDER, 'image_folder'=>Procedure::IMAGE_FOLDER, 'image_folder_tmp'=>Procedure::IMAGE_FOLDER_TMP, 'image_folder_thumb'=>Procedure::IMAGE_FOLDER_THUMB, 'default_chan'=>self::DEFAULT_CHAN, 'all_chan_id'=>self::ALL_CHAN_ID, 'all_chan_text'=>self::ALL_CHAN_TEXT, 'pm_separator'=>self::PM_SEP, 'reboot_delay'=>self::REBOOT_DELAY, 'versionHtml'=>$this->getItemBlock(), 'opt_console_no'=>self::OPT_CONSOLE_NO, 'types'=>$this->getTypeInfo('title')); $oPage->setTag('constants', $this->jsonConvert($asConstants)); //Variables $asVars['page_titles'] = $this->getPageTitles(); $asVars['user_id'] = $this->getUserId(); $asVars['hash_to_page'] = $this->getPagesFromHash(); $asVars['page_to_hash'] = array_flip($asVars['hash_to_page']); $asVars['opt_console'] = $this->getUserOptionValue(self::OPT_CONSOLE); $oPage->setTag('variables', $this->jsonConvert($asVars)); return $oPage->getMask(); } public function getLogonPage($bFirstConn) { $oPage = new Mask('logon'); $oPage->setTag('feedback', $bFirstConn?'':'Données incorrectes'); $oPage->setTag('version', self::VERSION); $oPage->setTag('name_pass_sep', self::NAME_PASS_SEP); return $oPage->getMask(); } public function getRss($sCat='') { //Class Feed $this->oClassManagement->incClass('rss'); //Building header $asDesc = array ( 'title'=>'Flux RSS Databap'.($sCat==''?'':' - '.$sCat), 'link'=>$this->getInternalLink('rss', $sCat), 'copyright'=>'Powered by Francois Lutran. RSS Feed Generator under GPLv3 License', 'description'=>'Flux RSS du chat'.($sCat==''?'':', section '.$sCat), 'language'=>'fr', 'webmaster_mail'=>'francois@lutran.fr' ); $oFeed = new Feed($asDesc); //Building items if($sCat=='news') { $asNews = $this->getNews(false); $iLinkId = count($asNews); foreach($asNews as $asRow) { //TODO mutualiser avec le reste $sChatlink = $this->getInternalLink('chat', $asRow[MySqlManager::getId(self::MSG_TABLE)]); $asItem = array ( 'title'=>'Lien'.($sCat==''?'':' - '.$sCat).' #'.$iLinkId, 'category'=>$sCat, 'description'=>$asRow['message'], 'author'=>$asRow['nickname'], 'link'=>$sChatlink, 'pub_date'=>$asRow['time'], 'guid'=>$sChatlink ); $oFeed->addItem($asItem); $iLinkId -= 1; } } else { switch($sCat) { case '9gag': $sRegEx = '(https?://|www\\.)(.*)9gag\\.com'; break; case 'youtube': $sRegEx = '(https?://|www\\.)(.*)youtube\\.com'; break; case '': $sRegEx = '(https?://|www\\.)[\.A-Za-z0-9\-]+\\.[a-zA-Z]{2,4}'; break; default: $sRegEx = '(https?://|www\\.)(.*)'.$sCat.'(.*)\\.[a-zA-Z]{2,4}'; break; } $asResult = $this->oMySql->selectRows(array('select'=>array('id_message', 'nickname', 'message', 'led'), 'from'=>'messages', 'constraint'=>array('message'=>$sRegEx), 'constOpe'=>array('message'=>' REGEXP '))); $sPattern = '/(https?\:\/\/|www\.)[\S]+\.[a-zA-Z]{2,4}([\S]*)/ui'; foreach($asResult as $iLinkId=>$asRow) { //get link out of message preg_match($sPattern, $asRow['message'], $asMatches); $asRow['link'] = (substr($asMatches[0], 0, 4)=='http')?$asMatches[0]:'http://'.$asMatches[0]; //add item $sChatlink = $this->getInternalLink('chat', $asRow['id_message']); $asItem = array ( 'title'=>'Lien'.($sCat==''?'':' - '.$sCat).' #'.($iLinkId+1), 'category'=>$sCat, 'description'=>'Lien posté par '.self::getNickNameFormat($asRow['nickname']).' à '.self::getDateFormat($asRow['led']).' : '.$asRow['message'].'', 'author'=>$asRow['nickname'], 'link'=>$sChatlink, 'pub_date'=>$asRow['led'], 'guid'=>$sChatlink ); $oFeed->addItem($asItem); } } return $oFeed->getFeed(); } public function syncSapBlog() { //Get articles list $asArticles = $this->getSAPBlogRss(); //Update and spread the news $asResult = array(); $iTimeStamp = time(); if(date('N', $iTimeStamp)>5 || date('G', $iTimeStamp)>19) $asResult[] = "Pas de mise-à-jour pendant le week end ou en soirée."; else { foreach($asArticles as $asArticle) { $iArticleId = $this->oMySql->selectValue(self::ART_TABLE, MySqlManager::getId(self::ART_TABLE), array('title'=>$asArticle['title'])); if($iArticleId==0) { $iArticleId = $this->oMySql->insertRow(self::ART_TABLE, $asArticle); $this->addMessage($iArticleId, self::MESSAGE_ARTICLE, self::DEFAULT_CHAN_ID); $this->oSearchEngine->buildIndex($iArticleId, self::ART_TYPE); $sResult = 'ADDED'; } else $sResult = 'OK'; $asResult[$iArticleId] = $sResult.' | '.implode(' | ', $asArticle); } } return MySqlManager::implodeAll($asResult, '->', "\n"); } private function getSAPBlogRss() { $asArticles = array(); //SCN SAP $sSAPDomain = 'http://scn.sap.com'; $asBlogPaths = array( '/community/data-warehousing/bw/blog', '/community/data-warehousing/blog', '/community/bw-hana/blog'); foreach($asBlogPaths as $sSAPBlogPath) { $sSAPBlogUrl = $sSAPDomain.$sSAPBlogPath; $oDom = $this->getRemotePageDom($sSAPBlogUrl); $aoArticles = $oDom->getElementsByTagName('header'); foreach($aoArticles as $oArticle) { if($oArticle->getAttribute('class')=='jive-blog-post-subject') { $asArticleInfo = array(); $aoLinks = $oArticle->getElementsByTagName('a'); foreach($aoLinks as $oLink) { switch($oLink->getAttribute('class')) { //Title & link case 'font-color-normal': $asArticleInfo['title'] = trim($oLink->nodeValue); $asArticleInfo['title'] = mb_substr($asArticleInfo['title'], -1)=='.'?mb_substr($asArticleInfo['title'], 0, -1):$asArticleInfo['title']; $asArticleInfo['link'] = $oLink->getAttribute('href'); $asArticleInfo['date'] = mb_substr(str_replace(array($sSAPBlogUrl.'/', '/'), array('', '-'), $asArticleInfo['link']), 0, 10); break; //Author case 'jiveTT-hover-user jive-username-link': $asNames = array_filter(explode(' ', ToolBox::mb_ucwords(trim($oLink->nodeValue)))); $asArticleInfo['first_name'] = array_shift($asNames); $asArticleInfo['last_name'] = implode('-', $asNames); $asArticleInfo['email'] = $sSAPDomain.$oLink->getAttribute('href'); break; } } $asArticles[] = $asArticleInfo; } } } //BI Portal $oDom = $this->getRemotePageDom('http://www.biportal.org/sap_bi_blog'); $aoArticles = $oDom->getElementsByTagName('li'); foreach($aoArticles as $oArticle) { if($oArticle->getAttribute('class')=='boxesListItem' && $oArticle->getAttribute('id') > 0) { $asArticleInfo = array(); $aoLinks = $oArticle->getElementsByTagName('a'); $oLink = $aoLinks->item(0); $asArticleInfo['link'] = $oLink->getAttribute('href'); $asArticleInfo['title'] = trim($oLink->nodeValue); $aoLinks = $oArticle->getElementsByTagName('span'); foreach($aoLinks as $oLink) { switch($oLink->getAttribute('class')) { case 'postedOn': $asArticleInfo['date'] = date(self::DATE_SQL_FORMAT, strtotime($oLink->nodeValue)); break; case 'postedByLink': $sName = trim($oLink->firstChild->nodeValue); $asArticleInfo['first_name'] = strstr($sName, ' ', true); $asArticleInfo['last_name'] = substr(strstr($sName, ' '), 1); $asArticleInfo['email'] = $oLink->firstChild->getAttribute('href'); break; } } $asArticles[] = $asArticleInfo; } } //SAP BW BW $oDom = $this->getRemotePageDom('http://sapbwbw.com/'); $aoArticles = $oDom->getElementsByTagName('header'); foreach($aoArticles as $oArticle) { if($oArticle->getAttribute('class')=='entry-header') { $asArticleInfo = array(); $aoLinks = $oArticle->getElementsByTagName('a'); $oLink = $aoLinks->item(0); $asArticleInfo['link'] = $oLink->getAttribute('href'); $asArticleInfo['title'] = trim($oLink->nodeValue); $aoLinks = $oArticle->getElementsByTagName('time'); $oLink = $aoLinks->item(0); $asArticleInfo['date'] = mb_substr($oLink->getAttribute('datetime'), 0, 10); $asArticleInfo['first_name'] = 'Claudio'; $asArticleInfo['last_name'] = 'Ciardelli'; $asArticleInfo['email'] = ''; $asArticles[] = $asArticleInfo; } } return $asArticles; } private function get9gagPost($sUrl) { $asPost = array('url'=>$sUrl); $oDom = $this->getRemotePageDom($sUrl); $oDivs = $oDom->getElementsByTagName('section'); foreach($oDivs as $oPost) {if($oPost->getAttribute('id')=='individual-post') break;} //Title $asPost['title'] = $oPost->getElementsByTagName('h2')->item(0)->nodeValue; //Image $oImages = $oPost->getElementsByTagName('img'); foreach($oImages as $oImage) { switch($oImage->getAttribute('class')) { case 'badge-item-animated-img': $o9gagImage = $oImage; break 2; case 'badge-item-img': $o9gagImage = $oImage; break; } } $asResult = $this->downloadToTmp($o9gagImage->getAttribute('src')); if($asResult['error']=='') { $asPost['url_img'] = $asResult['out']; $asPost['width'] = $asResult['width']; $asPost['height'] = $asResult['height']; } return $asPost; } private function getRemotePageDom($sUrl) { $oDom = new DOMDocument(); @$oDom->loadHTML(file_get_contents($sUrl)); return $oDom->getElementsByTagName('body')->item(0); } public function addUser($sFirstName, $sLastName, $sCompany, $sEmail='', $iClearance=self::CLEARANCE_MEMBER) { $sFirstName = mb_strtolower($sFirstName); $sLastName = mb_strtolower($sLastName); $sCompany = mb_strtolower($sCompany); $sEmail = mb_strtolower($sEmail); //Checking company existency in company table $sCompanyTextCol = MySqlManager::getText(self::COMP_TABLE); $iCompanyId = $this->oMySql->selectInsert(self::COMP_TABLE, array($sCompanyTextCol=>$sCompany, 'logo'=>self::DEFAULT_COMPANY_LOGO), array($sCompanyTextCol)); $asInfo = array('first_name'=>$sFirstName, 'last_name'=>$sLastName, 'active'=>self::MEMBER_ACTIVE, MySqlManager::getId(self::COMP_TABLE)=>$iCompanyId, 'pass'=>$this->oAuth->HashPassword(self::getLoginToken($sCompany)), 'clearance'=>$iClearance, 'led'=>'0000-00-00 00:00:00'); $iUserId = $this->oMySql->insertRow(self::USER_TABLE, $asInfo); //Admin Options $sOptionTable = self::OPT_TABLE; $sUserIdCol = MySqlManager::getId(self::USER_TABLE); $sOptNameIdCol = MySqlManager::getId(self::OPTNAME_TABLE); $sOptionTextCol = MySqlManager::getText(self::OPT_TABLE); $sOptionValIdCol = MySqlManager::getId(self::OPTVAL_TABLE); $this->oMySql->insertRow($sOptionTable, array($sUserIdCol=>$iUserId, $sOptNameIdCol=>self::OPT_NICKNAME, $sOptionTextCol=>$sFirstName)); //$this->oMySql->insertRow($sOptionTable, array($sUserIdCol=>$iUserId, $sOptNameIdCol=>self::OPT_BG, $sOptionTextCol=>'#04357B')); //$this->oMySql->insertRow($sOptionTable, array($sUserIdCol=>$iUserId, $sOptNameIdCol=>self::OPT_BRIGHT_BG, $sOptionTextCol=>'#D9E5F2')); //$this->oMySql->insertRow($sOptionTable, array($sUserIdCol=>$iUserId, $sOptNameIdCol=>self::OPT_HOVER, $sOptionTextCol=>'#EFAB00')); //$this->oMySql->insertRow($sOptionTable, array($sUserIdCol=>$iUserId, $sOptNameIdCol=>self::OPT_TOKEN, $sOptionTextCol=>$this->generateExternalAccessLink('rss', $iUserId))); //$this->oMySql->insertRow($sOptionTable, array($sUserIdCol=>$iUserId, $sOptNameIdCol=>self::OPT_IMAGE_CHAT, $sOptionTextCol=>'images/sap_gold_332.jpg')); $this->oMySql->insertRow($sOptionTable, array($sUserIdCol=>$iUserId, $sOptNameIdCol=>self::OPT_CONSOLE, $sOptionValIdCol=>self::OPT_CONSOLE_NO)); $this->oMySql->insertRow($sOptionTable, array($sUserIdCol=>$iUserId, $sOptNameIdCol=>self::OPT_EMAIL, $sOptionTextCol=>$sEmail)); return $iUserId; } public function buildCompleteIndex() { $this->oMySql->emptyTable(self::SEARCH_TABLE); foreach($this->getTypeInfo('table') as $sSearchType=>$sSearchTable) { $asItemIds = $this->oMySql->selectRows(array('select'=>MySqlManager::getId($sSearchTable), 'from'=>$sSearchTable)); foreach($asItemIds as $iItemId) $this->oSearchEngine->buildIndex($iItemId, $sSearchType); } } //insert new code / version public function addCode($asData) { $sContent = $asData['content']; $sDescription = $asData['description']; $sLink = str_replace(' ', '_', $asData['link']); //insert value in db $asInsert = array( MySqlManager::getText(self::CODE_TABLE)=>$sContent, 'description'=>$sDescription, 'id_user'=>$this->getUserId()); $iCodeId = $this->oMySql->insertRow(self::CODE_TABLE, $asInsert); //insert link if exists if($sLink!='') { $asInsert = array(MySqlManager::getId(self::CODE_TABLE)=>$iCodeId, 'phrase'=>$sLink); $this->oMySql->insertRow(self::URL_TABLE, $asInsert); } //refer id update $this->oMySql->updateRow(self::CODE_TABLE, $iCodeId, array('refer_id'=>$iCodeId)); //Add message $this->addMessage($iCodeId, self::MESSAGE_ADD_CODE, self::DEFAULT_CHAN_ID); //Add record in Search Table $this->oSearchEngine->buildIndex($iCodeId, self::CODE_TYPE); return $iCodeId; } public function editCode($oCode, $sContent) { $asRef = $this->getCodeInfo($oCode, 'first'); $iVersion = $this->oMySql->selectValue(self::CODE_TABLE, 'COUNT(id_code)', array('refer_id'=>$asRef['id_code']))+1; $asEdit = array('code'=>$sContent, 'description'=>$asRef['description'].' (v'.$iVersion.')', 'id_user'=>$this->iUserId, 'refer_id'=>$asRef['id_code']); $iCodeId = $this->oMySql->insertRow(self::CODE_TABLE, $asEdit); //Add message $this->addMessage($iCodeId, self::MESSAGE_EDIT_CODE, self::DEFAULT_CHAN_ID); //Add record in Search Table $this->oSearchEngine->buildIndex($iCodeId, self::CODE_TYPE); return $iCodeId; } public function addProcedure($asPost) { $oProcedure = new Procedure($this->oMySql); $asPost['id_user'] = $this->getUserId(); $oProcedure->inputForm($asPost); $asErrors = $oProcedure->checkIntegrity(); if(count($asErrors)==0) { //Previous procedure Id $iPrevProcId = isset($asPost['procedure_id'])?$asPost['procedure_id']:0; //Load procedure into database $bCreation = $oProcedure->saveProcedure($iPrevProcId); //Extract extra data $asProc = $oProcedure->getProcedure(); $iNewProcId = $asProc['proc_id']; $asUser = $this->getUserInfo($this->getUserId()); $oResult = array('result'=>'success', 'proc_id'=>$iNewProcId, 'led'=>$asProc['led'], 'name'=>$asUser['name'], 'company'=>$asUser['company']); //Add Message in chat if($bCreation) { $this->addMessage($iNewProcId, self::MESSAGE_ADD_PROC, self::DEFAULT_CHAN_ID); } else { $this->addMessage($iNewProcId, self::MESSAGE_EDIT_PROC, self::DEFAULT_CHAN_ID); } //Add record in Search Table $this->oSearchEngine->buildIndex($iNewProcId, self::PROC_TYPE); } else { $oResult = array('result'=>'fail', 'errors'=>$asErrors); } return self::jsonExport($oResult); } public function getProcedure($iProcId) { $oProcedure = new Procedure($this->oMySql); $oProcedure->loadProcedure($iProcId); $asProc = $oProcedure->getProcedure(); //Adding user info $asUser = $this->getUserInfo($asProc['id_user']); $asProc['name'] = $asUser['name']; $asProc['company'] = $asUser['company']; return self::jsonExport($asProc); } public function addDoc($asPost) { //Previous Doc Id $iPrevDocId = array_key_exists('doc_id', $asPost)?$asPost['doc_id']:0; $bCreation = ($iPrevDocId==0); //User $iUserId = $this->getUserId(); //Titles $sTitle = isset($asPost['title'])?$asPost['title']:''; $sDescription = isset($asPost['description'])?$asPost['description']:''; //Get docs $sImagePattern = '/c1_(?P\d+)_image_(?P\w+)/u'; foreach($asPost as $sFormId=>$sValue) { preg_match($sImagePattern, $sFormId, $asMatches); if(!empty($asMatches) && ($asMatches['doc_info'] == 'name' || $asMatches['doc_info'] == 'desc')) { $asDocs[$asMatches['doc_id']][$asMatches['doc_info']] = $sValue; } } //Load doc into database $asData = array('title'=>$sTitle, 'description'=>$sDescription, MySqlManager::getId(self::USER_TABLE)=>$iUserId); $iDbDocId = $this->oMySql->insertRow(self::DOC_TABLE, $asData); //Load doc files into database $asDocData[MySqlManager::getId(self::DOC_TABLE)] = $iDbDocId; foreach($asDocs as $asDocInfo) { //insert into database $sFileName = $asDocInfo['name']; $asDocData['description'] = $asDocInfo['desc']; $asDocData['file_name'] = $sFileName; $iDbImageId = $this->oMySql->insertRow(self::FILE_TABLE, $asDocData); //Move file $sTempFilePath = self::DOC_TMP_FOLDER.$sFileName; $sFilePath = self::DOC_FOLDER.$sFileName; if(!rename($sTempFilePath, $sFilePath)) { $this->addError('Unmoveable file : '.$sTempFilePath); } } //Add this doc to the group $iReferId = $bCreation?$iDbDocId:$this->oMySql->selectValue(self::DOC_TABLE, 'refer_id', $iPrevDocId); $this->oMySql->updateRow(self::DOC_TABLE, $iDbDocId, array('refer_id'=>$iReferId)); //Add Message in chat $this->addMessage($iDbDocId, $bCreation?self::MESSAGE_ADD_DOC:self::MESSAGE_EDIT_DOC, self::DEFAULT_CHAN_ID); //Add record in Search Table $this->oSearchEngine->buildIndex($iDbDocId, self::DOC_TYPE); return self::jsonExport(array('result'=>'success','doc_id'=>$iDbDocId)); } public function getDoc($iDocId) { //Extract doc data $asDoc = $this->oMySql->selectRow(self::DOC_TABLE, $iDocId); $asDoc['description'] = self::getDescriptionFormat($asDoc['description']); $asDoc['title'] = self::getDescriptionFormat($asDoc['title']); $asDoc['led'] = self::getDateFormat($asDoc['led']); //Extract extra data $asUser = $this->getUserInfo($asDoc[MySqlManager::getId(self::USER_TABLE)]); $asDoc['name'] = $asUser['name']; $asDoc['company'] = $asUser['company']; //Extract doc files $asFiles = $this->oMySql->selectRows(array('from'=>self::FILE_TABLE, 'constraint'=>array('id_doc'=>$iDocId))); foreach($asFiles as $asFile) { $asDoc['files'][$asFile[MySqlManager::getId(self::FILE_TABLE)]] = array('description'=>self::getDescriptionFormat($asFile['description']), 'ext'=>pathinfo($asFile['file_name'], PATHINFO_EXTENSION)); } return self::jsonExport($asDoc); } public function addTable($sSystem, $sTitle, $sDescription, $sKeyWords, $iPrevTableId, $bSimul=false) { $bCreation = ($iPrevTableId==0); $iDbTableId = 0; $sDesc = ''; //Previous table info if(!$bCreation) $asPrevTableInfo = $this->getTableInfo($iPrevTableId, false); //New table info $sTitle = mb_strtolower($bCreation?trim($sTitle):$asPrevTableInfo['title']); $sDescription = mb_strtolower(trim($sDescription)); //Check for existing table with the same name if($bCreation && $this->checkValue(self::TABL_TABLE, array('title'=>$sTitle))) $sDesc = ToolBox::findReplaceLinks('Une documentation existe déjà pour la table '.self::getTableFormat($sTitle)); elseif(!$bCreation && $iPrevTableId!=$this->getUpToDateId(self::TABL_TABLE, $sTitle)) $sDesc = ToolBox::findReplaceLinks('Une version plus récente de la table '.self::getTableFormat($sTitle).' existe'); elseif(!$bSimul) { //Load table into database $asData = array(MySqlManager::getId(self::USER_TABLE)=>$this->getUserId(), 'title'=>$sTitle, 'description'=>$sDescription, 'system'=>$sSystem, 'keywords'=>$sKeyWords); $iDbTableId = $this->oMySql->insertRow(self::TABL_TABLE, $asData); if(!$iDbTableId) $sDesc = 'Erreur inconnue dans la base de données'; else { //Add the group refer id $iReferId = $bCreation?$iDbTableId:$this->oMySql->selectValue(self::TABL_TABLE, 'refer_id', $iPrevTableId); $this->oMySql->updateRow(self::TABL_TABLE, $iDbTableId, array('refer_id'=>$iReferId)); //Add Message in chat $this->addMessage($iDbTableId, $bCreation?self::MESSAGE_ADD_TABLE:self::MESSAGE_EDIT_TABLE, self::DEFAULT_CHAN_ID); //Add record in Search Table $this->oSearchEngine->buildIndex($iDbTableId, self::TABLE_TYPE); } } return $this->getJsonPostResult($iDbTableId>0, $sDesc, array('id'=>$iDbTableId, 'name'=>$sTitle)); } public function getTable($oTableId) { $bReadById = is_numeric($oTableId); $iTableId = $bReadById?$oTableId:$this->getUpToDateId(self::TABL_TABLE, mb_strtolower($oTableId)); //Extract table data $asTable = $this->getTableInfo($iTableId); $bSuccess = array_key_exists(MySqlManager::getId(self::TABL_TABLE), $asTable); $sDesc = ''; if($bSuccess) { $asTable['date'] = self::getDateFormat($asTable['timestamp'], self::DATE_FORMAT); $asTable['title'] = $asTable['table_name']; unset($asTable['timestamp']); $asTable['id'] = $asTable[MySqlManager::getId(self::TABL_TABLE)]; //Extract extra data $asUser = $this->getUserInfo($asTable[MySqlManager::getId(self::USER_TABLE)]); $asTable['name'] = $asUser['name']; $asTable['company'] = $asUser['company']; //Out of date warning $sRightTableLink = ToolBox::findReplaceLinks('Il existe une documentation plus à jour pour la table '.self::getTableFormat($asTable['title'])); $asTable['warning'] = ($bReadById && $iTableId!=$this->getUpToDateId(self::TABL_TABLE, $iTableId))?$sRightTableLink:''; } else $sDesc = self::NOT_FOUND; return $this->getJsonPostResult($bSuccess, $sDesc, $asTable); } //TODO good idea ? If yes, apply to all types. Put in MySqlManager ? involve switchCodeId() private function getUpToDateId($sTableName, $oId) { if(is_numeric($oId)) $asConstraint = array('refer_id'=>$this->oMySql->selectValue(self::TABL_TABLE, 'refer_id', $oId)); //by Id else $asConstraint = array('title'=>$oId); //by phrase $sItemIdCol = 'id_item'; $asInfo = array('select'=>array("MAX(".MySqlManager::getId($sTableName).") AS ".$sItemIdCol), //selecting last version among codes having the same refer_id 'from'=>$sTableName, 'constraint'=>$asConstraint, 'groupBy'=>array('refer_id'), 'orderBy'=>array($sItemIdCol=>'desc')); $asResult = $this->oMySql->selectRows($asInfo); return array_shift($asResult); } public function getFile($iFileId) { $sFileName = $this->oMySql->selectValue(self::FILE_TABLE, 'file_name', $iFileId); $sFilePath = self::DOC_FOLDER.$sFileName; $sFileFullPath = dirname($_SERVER['SCRIPT_FILENAME'])."/".$sFilePath; if(!file_exists($sFilePath)) { die(); } else { //get mime type if(class_exists('finfo')) { $oFileInfo = new finfo(FILEINFO_MIME); $sMimetype = $oFileInfo->file($sFileFullPath); } else { $sMimetype = 'application/force-download'; } //set headers header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Cache-Control: public'); header('Content-Description: File Transfer'); header('Content-Type: '.$sMimetype); header('Content-Disposition: attachment; filename='.$sFileName); header('Content-Transfer-Encoding: binary'); header('Content-Length: '.@filesize($sFilePath)); // download if ($oFile = @fopen($sFilePath, 'rb')) { while(!feof($oFile)) { print(fread($oFile, 1024*8)); flush(); if(connection_status() != 0) { @fclose($oFile); } } @fclose($oFile); } } } public function uploadImage() { $this->oClassManagement->incClass('fileuploader'); $oFileUploader = new fileUploader(Procedure::IMAGE_FOLDER_TMP, self::$UPLOAD_IMG_EXTS); $asResult = $oFileUploader->handleUpload(); return $this->jsonConvert($asResult); } public function uploadDoc() { $this->oClassManagement->incClass('fileuploader'); $oFileUploader = new fileUploader(self::DOC_TMP_FOLDER, self::$UPLOAD_DOC_EXTS); $asResult = $oFileUploader->handleUpload(); return $this->jsonConvert($asResult); } private function getItemInfo($sType, $iItemId) { return call_user_func(array($this, 'get'.ucfirst($this->getPagesFromHash($sType)).'Info'), $iItemId); } //TODO: one function only with a type parameter private function getCodeInfo($oCode, $sMode='', $bCode=false) { $iCodeId = is_numeric($oCode)?$oCode:$this->getIdCodeFromPhrase($oCode); //Mode (get last or first id_code) if($sMode!='') { $this->switchCodeId($iCodeId, $sMode); } //Efficient request : don't request for the entire code if(!$bCode) { $asSelect = $this->oMySql->getTablecolumns(self::CODE_TABLE); unset($asSelect[MySqlManager::getText(self::CODE_TABLE)]); $asSelect = array_keys($asSelect); } else { $asSelect = "*"; } $asCode = $this->oMySql->selectRow(self::CODE_TABLE, $iCodeId, $asSelect); $asCode['title'] = self::getDescriptionFormat($asCode['description']); $asCode['description'] = self::getDescriptionFormat($asCode['description']); $asCode['timestamp'] = strtotime($asCode['led']); $asCode['led'] = self::getDateFormat($asCode['led']); return $asCode; } private function getProcedureInfo($iProcId) { $asProc = $this->oMySql->selectRow(self::PROC_TABLE, $iProcId); $asProc['title'] = self::getDescriptionFormat($asProc['title']); $asProc['description'] = self::getDescriptionFormat($asProc['description']); $asProc['timestamp'] = strtotime($asProc['led']); $asProc['led'] = self::getDateFormat($asProc['led']); return $asProc; } private function getDocInfo($iDocId) { $asDoc = $this->oMySql->selectRow(self::DOC_TABLE, $iDocId); $asDoc['title'] = self::getDescriptionFormat($asDoc['title']); $asDoc['description'] = self::getDescriptionFormat($asDoc['description']); $asDoc['timestamp'] = strtotime($asDoc['led']); $asDoc['led'] = self::getDateFormat($asDoc['led']); return $asDoc; } private function getTableInfo($iTableId, $bFormatting=true) { $asTable = $this->oMySql->selectRow(self::TABL_TABLE, $iTableId); if(!empty($asTable)) { $asTable['timestamp'] = strtotime($asTable['led']); if($bFormatting) { $asTable['system'] = self::getTableFormat($asTable['system']); $asTable['description'] = self::getDescriptionFormat($asTable['description']); $asTable['table_name'] = self::getTableFormat($asTable['title']); $asTable['title'] = self::getTableFormat($asTable['title']).' - '.$asTable['description']; $asTable['led'] = self::getDateFormat($asTable['led']); $asTable['formated_keywords'] = ToolBox::formatText($asTable['keywords']); } } return $asTable; } private function getArticleInfo($iArtId) { $asArt = $this->oMySql->selectRow(self::ART_TABLE, $iArtId); $asTransferredInfo = array('link_art'=>$asArt['link'], 'art_title'=>$asArt['title'], 'link_auth'=>$asArt['email']); $asTransferredInfo['art_date'] = self::getDateFormat($asArt['date'], self::DATE_FORMAT); $asTransferredInfo['name'] = self::getNameFormat($asArt['first_name'], $asArt['last_name']); $asTransferredInfo['title'] = self::getDescriptionFormat($asArt['title']); $asTransferredInfo['description'] = self::getDescriptionFormat($asArt['title']); $asTransferredInfo['timestamp'] = strtotime($asArt['led']); $asTransferredInfo['led'] = self::getDateFormat($asArt['led']); //Domain $asParsedUrl = parse_url($asArt['link']); $asTransferredInfo['domain'] = $asParsedUrl['host']; $asTransferredInfo['company'] = $asTransferredInfo['domain']; return $asTransferredInfo; } public function getUserInfo($iUserId, $bJson=false) { $asUserInfo = array(); if($iUserId==$this->getUserId() && !empty($this->asUserInfo)) { $asUserInfo = $this->asUserInfo; } elseif($iUserId > 0) { $asRow = $this->oMySql->selectRow(self::USER_TABLE, $iUserId); $sEmail = $this->getUserOptionValue(self::OPT_EMAIL, $iUserId); $asCompany = $this->oMySql->selectRow(self::COMP_TABLE, $asRow[MySqlManager::getId(self::COMP_TABLE)]); $asUserInfo = array( 'name'=>self::getNameFormat($asRow['first_name'], $asRow['last_name']), 'nickname'=>self::getNickNameFormat($this->getChatNickNames($iUserId)), 'email'=>$sEmail, 'company'=>self::getCompanyFormat($asCompany[MySqlManager::getText(self::COMP_TABLE)]), 'status'=>$this->getDescriptionFormat($this->getUserOptionValue(self::OPT_STATUS, $iUserId)), 'logo'=>$asCompany['logo'], 'clearance'=>$asRow['clearance'], 'user_led'=>self::getDateFormat($asRow['led'], self::DATE_FORMAT)); } return $bJson?$this->jsonExport($asUserInfo):$asUserInfo; } public function getUserClearance() { $asUserInfo = $this->getUserInfo($this->getUserId()); return $asUserInfo['clearance']; } public function getOptions() { $sOptValueIdCol = MySqlManager::getId(self::OPTVAL_TABLE); $sOptionTextCol = MySqlManager::getText(self::OPT_TABLE); $sOptNameTextCol = MySqlManager::getText(self::OPTNAME_TABLE); $sOptValueTextCol = MySqlManager::getText(self::OPTVAL_TABLE); //Available Options $asAvailableOptions = $this->getAvailableOptions(); //User options $asUserOptions = $this->getUserOptions(); //Build Options panel $asSelectedOptions = array(); foreach($asAvailableOptions as $sOptNameId=>$asOption) { $asSelectedOptions[$sOptNameId]['option_name'] = self::getDescriptionFormat($asOption[$sOptNameTextCol]); $asSelectedOptions[$sOptNameId]['user_value_id'] = array_key_exists($sOptNameId, $asUserOptions)?$asUserOptions[$sOptNameId][$sOptValueIdCol]:0; $asSelectedOptions[$sOptNameId]['user_value'] = array_key_exists($sOptNameId, $asUserOptions)?$asUserOptions[$sOptNameId][$sOptionTextCol]:''; $asSelectedOptions[$sOptNameId]['type'] = $asOption['type']; if($asOption['type']==self::OPT_SELECT) { $asOptionValuesInfo = array('select'=>array($sOptValueIdCol, $sOptValueTextCol), 'from'=>self::OPTVAL_TABLE, 'constraint'=>array('language'=>$this->sLanguage, MySqlManager::getId(self::OPTNAME_TABLE)=>$sOptNameId), 'orderBy'=>array('led'=>'ASC')); $asSelectedOptions[$sOptNameId]['select'] = $this->oMySql->selectRows($asOptionValuesInfo, true, $sOptValueIdCol); } } return $this->jsonExport($asSelectedOptions); } public function setOptions($asUserOptions, $bSilentUpdate=true) { foreach($this->getAvailableOptions() as $sOptNameId=>$asOption) { if(array_key_exists($sOptNameId, $asUserOptions)) { switch($asOption['type']) { case self::OPT_SELECT: //insert id of option value table $sUpdateCol = MySqlManager::getId(self::OPTVAL_TABLE); break; case self::OPT_TEXT: //insert value $sUpdateCol = MySqlManager::getText(self::OPT_TABLE); break; default: continue 2; } $sNewValue = $asUserOptions[$sOptNameId]; //Check identical data $asKeys = array(MySqlManager::getId(self::USER_TABLE)=>$this->getUserId(), MySqlManager::getId(self::OPTNAME_TABLE)=>$sOptNameId); $asData = array($sUpdateCol=>$sNewValue) + $asKeys; $sOldValue = $this->oMySql->selectValue(self::OPT_TABLE, $sUpdateCol, $asKeys); //Update value if($sOldValue!=$sNewValue) { //Update value $this->oMySql->insertUpdateRow(self::OPT_TABLE, $asData, array_keys($asKeys)); //Spread the word if(!$bSilentUpdate) { //TODO rassembler les messages similaires dans une fonction de template switch($sOptNameId) { case self::OPT_NICKNAME: $sType = self::MESSAGE_NICK; $sChanName = self::DEFAULT_CHAN; $sMessage = $sOldValue.' a changé son pseudo en '.$sNewValue; break; case self::OPT_STATUS: $sType = self::MESSAGE_STATUS; $sChanName = self::DEFAULT_CHAN; $sMessage = 'est sur une nouvelle mission : '.$this->getDescriptionFormat($sNewValue); break; default: continue 2; } $sChanId = $this->getChanId($sChanName); $this->addMessage($sMessage, $sType, $sChanId); } } } } } private function getAvailableOptions() { $sOptNameIdCol = MySqlManager::getId(self::OPTNAME_TABLE); $sOptNameTextCol = MySqlManager::getText(self::OPTNAME_TABLE); $asInfo = array('select'=>array($sOptNameIdCol, $sOptNameTextCol, 'type'), 'from'=>self::OPTNAME_TABLE, 'constraint'=>array('language'=>$this->sLanguage)); return $this->oMySql->selectRows($asInfo, true, $sOptNameIdCol); } private function getUserOptionValue($sOptionNameId, $iUserId=0) { $asUserOptions = $this->getUserOptions($sOptionNameId, $iUserId); $asOptionInfo = array_shift($asUserOptions); return $asOptionInfo[MySqlManager::getId(self::OPTVAL_TABLE)]; } private function getUserOptions($oOptionNameIds=array(), $iUserId=0) { $iUserId = $iUserId>0?$iUserId:$this->getUserId(); $sUserIdCol = MySqlManager::getId(self::USER_TABLE); $sOptNameIdCol = MySqlManager::getId(self::OPTNAME_TABLE); $sOptValueIdCol = MySqlManager::getId(self::OPTVAL_TABLE); $sOptionTextCol = MySqlManager::getText(self::OPT_TABLE); if(!is_array($oOptionNameIds)) { $oOptionNameIds = array($oOptionNameIds); } $asUserinfo = array('select'=>array($sOptNameIdCol, $sOptValueIdCol, $sOptionTextCol), 'from'=>self::OPT_TABLE, 'constraint'=>array($sUserIdCol=>$iUserId)); if(count($oOptionNameIds)>0) { $asUserinfo['constraint'][$sOptNameIdCol] = "(".implode(", ", $oOptionNameIds).")"; $asUserinfo['constOpe'] = array($sUserIdCol=>"=", $sOptNameIdCol=>" IN "); $asUserinfo['constVar'] = true; } $asOptions = $this->oMySql->selectRows($asUserinfo, true, $sOptNameIdCol); foreach($asOptions as $iOptionId=>$asOption) { if(!$asOption[$sOptValueIdCol]) $asOptions[$iOptionId][$sOptValueIdCol] = $asOptions[$iOptionId][$sOptionTextCol]; } return $asOptions; } public function getProfile($oUser) { switch($oUser) { case '': $iUserId = $this->getUserId(); break; case is_numeric($oUser): $iUserId = $oUser; break; case is_string($oUser): $oRes = $this->oMySql->selectValue(self::OPT_TABLE, MySqlManager::getId(self::USER_TABLE), array('option'=>mb_strtolower($oUser), MySqlManager::getId(self::OPTNAME_TABLE)=>self::OPT_NICKNAME)); $iUserId = !$oRes?$this->getUserId():$oRes; break; default: $iUserId = $this->getUserId(); break; } //User Info $asProfile['user'] = $this->getUserInfo($iUserId); unset($asProfile['user']['email']); unset($asProfile['user']['clearance']); //History Info $asTables = $this->getTypeInfo('table'); unset($asTables[self::ART_TYPE]); //Skip articles foreach($asTables as $sType=>$sTableName) { //Add Text $sText = mb_strtolower($this->getPageTitles($this->getPagesFromHash($sType))); if(!$sText) $this->addError('Pas de texte pour le type "'.$sType.'"'); //Loop through items $asSqlInfo = array('select'=>MySqlManager::getId($sTableName), 'from'=>$sTableName, 'constraint'=>array(MySqlManager::getId(self::USER_TABLE)=>$iUserId)); $asHistory = $this->oMySql->selectRows($asSqlInfo); foreach($asHistory as $iItemId) { $asInfo = $this->getItemInfo($sType, $iItemId); $sKey = $asInfo['timestamp'].$sType.$iItemId; $asProfile['history'][$sKey]['type'] = $sType; $asProfile['history'][$sKey]['id'] = $iItemId; $asProfile['history'][$sKey]['action'] = (($asInfo['refer_id']==$iItemId)?'Création':'Modification').' de '.$sText; $asProfile['history'][$sKey]['date'] = $asInfo['led']; $asProfile['history'][$sKey]['title'] = $asInfo['title']; } } krsort($asProfile['history']); return $this->jsonExport($asProfile); } private static function isPmChan($sChanSafeName) { $asResult = array('is_pm'=>false, 'chan_name'=>$sChanSafeName); preg_match('/(?P\d+)'.self::PM_SEP.'(?P\d+)/u', $sChanSafeName, $asMatch); if(!empty($asMatch)) { $asResult['is_pm'] = true; $asResult['from'] = $asMatch['from']; $asResult['to'] = $asMatch['to']; if($asMatch['from'] > $asMatch['to']) $asResult['chan_name'] = $asMatch['to'].self::PM_SEP.$asMatch['from']; else $asResult['chan_name'] = $asMatch['from'].self::PM_SEP.$asMatch['to']; } return $asResult; } private function checkChanAuth($sChanSafeName, $iUserId=0) { $asUserInfo = ($iUserId > 0)?$this->getUserInfo($iUserId):array('company'=>''); $asCompanies = $this->oMySql->selectRows(array('select'=>MySqlManager::getText(self::COMP_TABLE), 'from'=>self::COMP_TABLE)); $iCompChan = array_search($sChanSafeName, array_map(array('self', 'getChanSafeName'), $asCompanies)); $asPm = $this->isPmChan($sChanSafeName); return $sChanSafeName!='' && //Empty channel name ($iCompChan===false || $asUserInfo['company']==self::getCompanyFormat($asCompanies[$iCompChan])) && //Test Company Channel (!$asPm['is_pm'] || $iUserId==$asPm['from'] || $iUserId==$asPm['to']); //Test PM } public function joinChan($sChanName, $bFirstConn=false, $asAttendees=array()) { $bSuccess = false; $sDesc = ''; $asVars = array(); $sSafeChanName = self::getChanSafeName($sChanName); //Authorization to join channel $asMessages = array(); if($this->checkChanAuth($sSafeChanName, $this->getUserId())) { //On first connection, display on-join message for all channels if($bFirstConn) { $asConnChans = $this->getChannels($this->getUserId()); $bFirstChan = true; foreach($asConnChans as $iConnChanId=>$sConnChanName) { //Checking once for all channels if(!$bFirstChan || !$this->isUserConnected($iConnChanId)) { $asMessages[$iConnChanId] = $sConnChanName; } else break; $bFirstChan = false; } } //Add connection link in DB $sUserIdCol = MySqlManager::getId(self::USER_TABLE); $sChanIdCol = MySqlManager::getId(self::CHAN_TABLE); $asData = array('safe_name'=>$sSafeChanName, MySqlManager::getText(self::CHAN_TABLE)=>$sChanName); $iChanId = $this->oMySql->insertUpdateRow(self::CHAN_TABLE, $asData, array('safe_name'), false); //Is user already connected to this chan $bConnectedUser = $this->isUserConnected($iChanId); $iConnId = $this->oMySql->insertUpdateRow(self::CONN_TABLE, array($sUserIdCol=>$this->getUserId(), $sChanIdCol=>$iChanId), array($sUserIdCol, $sChanIdCol), false); if($iConnId>0) $bSuccess = true; if($bSuccess) { //Return connected channels $asVars['channels'] = $this->getChannels($this->getUserId()); //Add tab title (customized) //FIXME delete this shit and insert the channel type into channels DB table foreach($asVars['channels'] as $iConnectedChanId=>$sConnectedChanName) { $asPm = $this->isPmChan($sConnectedChanName); $asVars['channel_tab_names'][$iConnectedChanId] = $asPm['is_pm']?$this->getChatNickNames($asPm['from']==$this->getUserId()?$asPm['to']:$asPm['from']):$sConnectedChanName; } $asVars['current_chan_id'] = $iChanId; //Communicate on user's connection if(!$bConnectedUser) { $asMessages[$iChanId] = $this->oMySql->selectValue(self::CHAN_TABLE, MySqlManager::getText(self::CHAN_TABLE), $iChanId); } $sStatus = $this->getUserOptionValue(self::OPT_STATUS); $asUserInfo = $this->getUserInfo($this->getUserId()); foreach($asMessages as $iChanId=>$sMsgChanName) { $asPm = $this->isPmChan($sMsgChanName); $this->addMessage(' de '.$asUserInfo['company'].' ('.($sStatus==''?'aucune mission en cours':$this->getDescriptionFormat($sStatus)).') rejoint '.($asPm['is_pm']?'le chan privé':'#'.$sMsgChanName), self::MESSAGE_CONN, $iChanId); } //Send invites to attendees if(!empty($asAttendees)) { $asUserInfo = $this->getUserInfo($this->getUserId()); foreach($asAttendees as $sAttendee) { if($this->checkChanAuth($sSafeChanName, $sAttendee)) { $this->addMessage($sAttendee, self::MESSAGE_INVITE, $iChanId); } } } //Update chan leds $this->pingChans(); } else $sDesc = self::FAIL_UPDATE; } else $sDesc = 'Nom de chan non autorisé (nom de personne / nom de société interdit)'; return self::getJsonPostResult($bSuccess, $sDesc, $asVars); } private function isUserConnected($iChanId=0, $iUserId=0) { $iUserId = $iUserId>0?$iUserId:$this->getUserId(); $sUserIdCol = MySqlManager::getId(self::USER_TABLE); $asInfo = array('select' => MySqlManager::getId(self::CONN_TABLE), 'from' => self::CONN_TABLE, 'constraint'=> array($sUserIdCol=>$iUserId, 'led'=>"DATE_SUB(NOW(), INTERVAL ".self::KEEP_ALIVE." SECOND)"), 'constOpe' => array($sUserIdCol=>'=', 'led'=>'>'), 'constVar' => true, 'groupBy' => $sUserIdCol); //Add chan constraint if($iChanId>0) { $asInfo['constraint'][MySqlManager::getId(self::CHAN_TABLE)] = $iChanId; $asInfo['constOpe'][MySqlManager::getId(self::CHAN_TABLE)] = '='; } return (count($this->oMySql->selectRows($asInfo))>0); } public function pingChans() { $aiConstraints = array(MySqlManager::getId(self::USER_TABLE)=>$this->getUserId()); $asUpdates = array('led'=>date(self::DATE_TIME_SQL_FORMAT)); $this->oMySql->updateRows(self::CONN_TABLE, $aiConstraints, $asUpdates); } public function quitChan($sChanName) { $iChanId = $this->getChanId($sChanName); $iConnId = $this->getConnId($iChanId); if($iConnId>0) { $this->oMySql->deleteRow(self::CONN_TABLE, $iConnId); $asPm = $this->isPmChan($sChanName); $this->addMessage('quitte '.($asPm['is_pm']?'le chan privé':'#'.$sChanName), self::MESSAGE_CONN, $iChanId); } } private function getActiveChannels() { //Get connected users $asActiveChanUsers = $this->getConnectedUsers(false, false); $asActiveChans = array_keys($asActiveChanUsers); //Get Channel names $sChanIdCol = MySqlManager::getId(self::CHAN_TABLE); $asChanNames = $this->oMySql->selectRows(array('select'=>array($sChanIdCol, MySqlManager::getText(self::CHAN_TABLE)), 'from'=>self::CHAN_TABLE), true, $sChanIdCol); foreach($asActiveChans as $iChanId) { $asChannels[$asChanNames[$iChanId]] = count($asActiveChanUsers[$iChanId]); } //remove restricted channels $asPublicChannels = array(); foreach($asChannels as $sChanName=>$iChanCount) { if($this->checkChanAuth($this->getChanSafeName($sChanName))) $asPublicChannels[$sChanName] = $iChanCount; } return $asPublicChannels; } private function getChannels($iUserId=0) { $sChanIdCol = MySqlManager::getId(self::CHAN_TABLE, true); $sChanNameCol = MySqlManager::getText(self::CHAN_TABLE); $asInfo = array('select'=>array($sChanIdCol, $sChanNameCol), 'from'=> self::CONN_TABLE, 'join'=> array(self::CHAN_TABLE=>MySqlManager::getId(self::CHAN_TABLE)), 'orderBy'=> array(MySqlManager::getId(self::CONN_TABLE)=>'ASC')); if($iUserId > 0) $asInfo['constraint'] = array(MySqlManager::getId(self::USER_TABLE)=>$iUserId); $asChannels = $this->oMySql->selectRows($asInfo, true, MySqlManager::getId(self::CHAN_TABLE)); //remove restricted channels $asPublicChannels = array(); foreach($asChannels as $iChanId=>$sChanName) { if($this->checkChanAuth($this->getChanSafeName($sChanName), $iUserId)) $asPublicChannels[$iChanId] = $sChanName; } return $asPublicChannels; } private function getChanId($sChanName) { $sChanIdCol = MySqlManager::getId(self::CHAN_TABLE); $sSafeChanName = self::getChanSafeName($sChanName); $iChanId = $this->oMySql->selectValue(self::CHAN_TABLE, $sChanIdCol, array('safe_name'=>$sSafeChanName)); if($iChanId==0) { $this->addError('No channel id found with channel name (safe): '.$sSafeChanName.', unsafe: '.$sChanName); } return $iChanId; } private function getConnId($iChanId, $iUserId=0) { $sUserIdCol = MySqlManager::getId(self::USER_TABLE); $sConnIdCol = MySqlManager::getId(self::CONN_TABLE); $sChanIdCol = MySqlManager::getId(self::CHAN_TABLE); if($iUserId==0) $iUserId = $this->getUserId(); $iConnId = $this->oMySql->selectValue(self::CONN_TABLE, $sConnIdCol, array($sUserIdCol=>$iUserId, $sChanIdCol=>$iChanId)); if($iConnId==0) { $this->addError('No connection found for user: '.$iUserId.' and channel id: '.$iChanId); } return $iConnId; } public function addChatMessage($sMessage, $sChanName) { $sMessage = htmlspecialchars($sMessage); $sType = self::MESSAGE_USER; if(mb_substr($sMessage, 0, 1) == '/') { if(mb_substr($sMessage, 0, 4) == '/me ') { $sType = self::MESSAGE_ACTION; $sMessage = mb_substr($sMessage, 3); } elseif(mb_substr($sMessage, 0, 6) == '/slap ') { $sType = self::MESSAGE_ACTION; $sMessage = ' fout une grosse tarte à '.mb_substr($sMessage, 5); } elseif(mb_substr($sMessage, 0, 4) == '/bs ') { $sType = self::MESSAGE_ACTION; $sMessage = ' bitch-slaps '.mb_substr($sMessage, 3); } elseif(mb_substr($sMessage, 0, 6) == '/kick ') { $sType = self::MESSAGE_ACTION; $sMessage = ' met un coup de pied au cul de '.mb_substr($sMessage, 5); } elseif(mb_substr($sMessage, 0, 6) == '/nick ' && mb_strlen($sMessage)>6) { $sNewNick = $this->getNickNameFormat(mb_substr($sMessage, 5)); $sOldNick = $this->getNickNameFormat($this->getChatNickNames($this->getUserId())); //changing Nickname $this->setOptions(array(self::OPT_NICKNAME=>$sNewNick)); //Message $sType = self::MESSAGE_NICK; $sChanName = self::ALL_CHAN_TEXT; $sMessage = $sOldNick.' a changé son pseudo en '.$sNewNick; } elseif(mb_substr($sMessage, 0, 9) == '/mission ' && mb_strlen($sMessage)>9) { $sNewStatus = mb_substr($sMessage, 9); $sNewFormatStatus = $sNewStatus; //changing Nickname $this->setOptions(array(self::OPT_STATUS=>$sNewStatus)); //Message $sType = self::MESSAGE_STATUS; $sChanName = self::DEFAULT_CHAN; $sMessage = 'est sur une nouvelle mission : '.$sNewFormatStatus; } elseif(mb_substr($sMessage, 0, 6) == '/mail ' && mb_strlen($sMessage)>6) { $sImagePattern = '/\/mail (?P\w+) (?P.*)/u'; preg_match($sImagePattern, $sMessage, $asMatches); //Looking for user Id $iUserIdTo = $this->getUserIdFromNickName($asMatches['nickname']); //Handling mail if($iUserIdTo>0) { if(trim($asMatches['message'])!='') { if($this->sendPM($iUserIdTo, $asMatches['message'])) { $sMessage = 'a envoyé un mail à '.$asMatches['nickname']; } else { $sMessage = 'n\'a pas envoyé de mail à '.$asMatches['nickname'].' (raison inconnue, voir log)'; } } else { $sMessage = 'n\'a pas envoyé de mail à '.$asMatches['nickname'].' (message vide)'; } } else { $sMessage = 'n\'a pas envoyé de mail à '.$asMatches['nickname'].' (pseudo inconnu)'; } $sType = self::MESSAGE_ACTION; } elseif(mb_substr($sMessage, 0, 5) == '/mean') { $sPageContent = file_get_contents('http://www.randominsults.net/'); $sStartText = ''; $sEndText = ''; $iStartPos = mb_strpos($sPageContent, $sStartText); $iEndPos = mb_strpos($sPageContent, $sEndText); $sMessage = mb_substr($sPageContent, $iStartPos + mb_strlen($sStartText), $iEndPos - $iStartPos); } elseif(mb_substr($sMessage, 0, 5) == '/like') { $sType = self::MESSAGE_ACTION; $sMessage = ' plussoie'; } elseif(mb_substr($sMessage, 0, 4) == '/now') { $sType = self::MESSAGE_ACTION; $asWeekDays = array('lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche'); $asMonths = array('janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'); $sMessage = ' a demandé l\'heure. Pour sa gouverne, il est exactement '.date(self::TIME_FORMAT). ', le '.$asWeekDays[date('N')-1].' '.date('j').' '.$asMonths[date('n')-1].' '.date('Y').' (semaine '.date('W').')'; } elseif($sMessage == '/channels' || mb_substr($sMessage, 0, 5) == '/list' || $sMessage == '/chans') { //Always at least one channel open (the one the message is sent from) $sMessage = ' a demandé les chans disponibles. Pour sa gouverne, les chans ayant des membres connectés sont #'.MySqlManager::implodeAll($this->getActiveChannels(), ' (', ', #', '', ')'); $sType = self::MESSAGE_ACTION; } elseif((mb_substr($sMessage, 0, 5) == '/img ' || mb_substr($sMessage, 0, 5) == '/pic ') && mb_strlen($sMessage)>5) { $sUrl = trim(mb_substr($sMessage, 4)); $asResult = $this->downloadToTmp($sUrl); if($asResult['error']=='') { $sMessage = $this->getJsonMessage(array($asResult['out'], $asResult['width'], $asResult['height'], $sUrl)); $sType = self::MESSAGE_IMG; } } elseif(mb_substr($sMessage, 0, 6) == '/9gag ' && mb_strlen($sMessage)>6) { $sMessage = $this->getJsonMessage($this->get9gagPost(trim(mb_substr($sMessage, 6)))); $sType = self::MESSAGE_9GAG; } elseif(mb_substr($sMessage, 0, 7) == '/reboot' && $this->getUserClearance()==self::CLEARANCE_ADMIN) { $sMessage = 'L\'administrateur a demandé un reboot. Votre page va se rafraichir automatiquement dans '.self::REBOOT_DELAY.' secondes.'; $sType = self::MESSAGE_REBOOT; $sChanName = self::ALL_CHAN_TEXT; } elseif(mb_substr($sMessage, 0, 8) == '/invite ' && mb_strlen($sMessage)>8) { $sSafeChanName = $this->getChanSafeName($sChanName); $iUserId = $this->getUserIdFromNickName(trim(mb_substr($sMessage, 8))); if($iUserId>0 && $this->checkChanAuth($sSafeChanName, $iUserId)) { $sType = self::MESSAGE_INVITE; $sMessage = $iUserId; } } elseif(mb_substr($sMessage, 0, 6) == '/news ' && mb_strlen($sMessage)>6) { $sType = self::MESSAGE_NEWS; $sMessage = trim(substr($sMessage, 5)); } } elseif(mb_substr($sMessage, 0, 1) == '@' && mb_strpos($sMessage, ' ')>1) { $sType = self::MESSAGE_PRIVATE; } $sChanId = $this->getChanId($sChanName); return $this->addMessage($sMessage, $sType, $sChanId); } private function getJsonMessage($asData) { return self::JSON_PREFIX.$this->jsonConvert($asData); } private function downloadToTmp($sUrl) { $sFileInfo = pathinfo($sUrl); $sImageExt = mb_strtolower($sFileInfo['extension']); $sFilePath = self::DOC_TMP_FOLDER.uniqid().'.'.$sImageExt; return ToolBox::createThumbnail($sUrl, self::CHAT_IMG_MAX_WIDTH, self::CHAT_IMG_MAX_HEIGHT, $sFilePath, false, Databap::$UPLOAD_IMG_EXTS); } private function sendPM($iUserIdTo, $sMessage) { $bSuccess = false; $asUserFrom = $this->getUserInfo($this->getUserId()); $asUserTo = $this->getUserInfo($iUserIdTo); $sFrom = $asUserFrom['name'].' '; $sTo = $asUserTo['name'].' <'.$asUserTo['email'].'>'; $sMessage .= "\n\n\n".'Ne répondez pas à ce mail. Connectez-vous sur Databap.'; $sResult = ToolBox::sendMail($sFrom, 'Databap PM', $sMessage, $sTo, array(), false); $bSuccess = ($sResult==ToolBox::MAIL_SUCCESS); if(!$bSuccess) $this->addError($sResult); return $bSuccess; } private function addMessage($sMessage, $sType, $iChanId) { $bResult = false; if($iChanId>0) { $asInsert = array( MySqlManager::getId(self::USER_TABLE) => $this->getUserId(), 'nickname' => $this->getChatNickNames($this->getUserId()), MySqlManager::getId(self::CHAN_TABLE) => $iChanId, MySqlManager::getText(self::MSG_TABLE) => $sMessage, 'type' => $sType, 'date' => 'CURDATE()'); $bResult = $this->oMySql->insertRow(self::MSG_TABLE, $asInsert); } else { $this->addError('Message deleted: No channel found'); } return $bResult; } public function getMessages($iFirstMsgId="0") { //Update chan ping $this->pingChans(); //Get messages and users' infos $sChanIdCol = MySqlManager::getId(self::CHAN_TABLE, true); $sChanTextCol = MySqlManager::getText(self::CHAN_TABLE); $sMsgIdCol = MySqlManager::getId(self::MSG_TABLE, true); $sMsgTextCol = MySqlManager::getText(self::MSG_TABLE); $sMsgTableLed = MySqlManager::getFullColumnName(self::MSG_TABLE, 'led'); $sMsgTableChanIdCol = MySqlManager::getFullColumnName(self::MSG_TABLE, MySqlManager::getId(self::CHAN_TABLE)); $sUserIdCol = MySqlManager::getId(self::USER_TABLE, true); $sMsgTableUserIdCol = MySqlManager::getFullColumnName(self::MSG_TABLE, MySqlManager::getId(self::USER_TABLE)); $sUserTableUserIdCol = MySqlManager::getId(self::USER_TABLE, true); $sConnTableUserIdCol = MySqlManager::getFullColumnName(self::CONN_TABLE, MySqlManager::getId(self::USER_TABLE)); $sConnTableChanIdCol = MySqlManager::getFullColumnName(self::CONN_TABLE, MySqlManager::getId(self::CHAN_TABLE)); //channel related messages $sCurDate = date(Databap::DATE_SQL_FORMAT); $asInfo = array('select' => array($sMsgTableChanIdCol, $sMsgIdCol, $sMsgTextCol, 'type', $sMsgTableLed, 'first_name', 'last_name', $sUserIdCol, 'nickname'), 'from' => self::CONN_TABLE, 'joinOn' => array( self::MSG_TABLE =>array($sMsgTableChanIdCol, '=', $sConnTableChanIdCol), self::USER_TABLE=>array($sUserTableUserIdCol, '=', $sMsgTableUserIdCol)), 'constraint'=> array($sConnTableUserIdCol=>$this->getUserId(), $sMsgIdCol=>$iFirstMsgId, 'date'=>$sCurDate), 'constOpe' => array($sConnTableUserIdCol=>'=', $sMsgIdCol=>'>', 'date'=>'=')); $asSqlMessages = $this->oMySql->selectRows($asInfo, true, 'id_message'); //Global messages $asInfo['from'] = self::MSG_TABLE; $asInfo['joinOn'] = array(self::USER_TABLE=>array($sUserTableUserIdCol, '=', $sMsgTableUserIdCol)); $asInfo['constraint'] = array($sMsgTableChanIdCol=>self::ALL_CHAN_ID, $sMsgIdCol=>$iFirstMsgId, 'date'=>$sCurDate); $asInfo['constOpe'] = array($sMsgTableChanIdCol=>'=', $sMsgIdCol=>'>', 'date'=>'='); $asSqlGlobalMessages = $this->oMySql->selectRows($asInfo, true, 'id_message'); //Invites messages $asInfo['constraint'] = array($sMsgIdCol=>$iFirstMsgId, 'date'=>$sCurDate, 'type'=>self::MESSAGE_INVITE, 'message'=>$this->getUserId()); $asInfo['constOpe'] = array($sMsgIdCol=>'>', 'date'=>'=', 'type'=>'=', 'message'=>'='); $asSqlInviteMessages = $this->oMySql->selectRows($asInfo, true, 'id_message'); //Merge flows if(!empty($asSqlGlobalMessages)) $asSqlMessages = array_diff_key($asSqlMessages, $asSqlGlobalMessages) + $asSqlGlobalMessages; if(!empty($asSqlInviteMessages)) $asSqlMessages = array_diff_key($asSqlMessages, $asSqlInviteMessages) + $asSqlInviteMessages; //Sort messages ksort($asSqlMessages); //Sort out messages for Json Export $iPrefixLen = mb_strlen(self::JSON_PREFIX); //$iConsoleDisplay = $this->getUserOptionValue(self::OPT_CONSOLE); $asMessages = array('messages'=>array(), 'last_message_id'=>0); foreach($asSqlMessages as $iMessageId=>$asMessageInfo) { //Connection message filter //if($iConsoleDisplay==self::OPT_CONSOLE_NO && $asMessageInfo['type']==self::MESSAGE_CONN) continue; //General message info $iChanId = $asMessageInfo[MySqlManager::getId(self::CHAN_TABLE)]; $iUserId = $asMessageInfo[MySqlManager::getId(self::USER_TABLE)]; $sMessageType = $asMessageInfo['type']; $asMessages['messages'][$iMessageId]['id_chan'] = $iChanId; $asMessages['messages'][$iMessageId]['message'] = $asMessageInfo[$sMsgTextCol]; $asMessages['messages'][$iMessageId]['msg_class'] = $sMessageType; $asMessages['messages'][$iMessageId]['time'] = self::getDateFormat($asMessageInfo['led'], self::TIME_FORMAT); $asMessages['messages'][$iMessageId]['name'] = self::getNameFormat($asMessageInfo['first_name'], $asMessageInfo['last_name']); $asMessages['messages'][$iMessageId]['nickname'] = self::getNickNameFormat($asMessageInfo['nickname']); //generated messages switch($sMessageType) { case self::MESSAGE_ADD_CODE: case self::MESSAGE_EDIT_CODE: $asCode = $this->getCodeInfo($asMessages['messages'][$iMessageId]['message']); $asMessages['messages'][$iMessageId]['description'] = $asCode['description']; break; case self::MESSAGE_ADD_PROC: case self::MESSAGE_EDIT_PROC: $asProc = $this->getProcedureInfo($asMessages['messages'][$iMessageId]['message']); $asMessages['messages'][$iMessageId]['description'] = $asProc['title']; break; case self::MESSAGE_ADD_DOC: case self::MESSAGE_EDIT_DOC: $asDoc = $this->getDocInfo($asMessages['messages'][$iMessageId]['message']); $asMessages['messages'][$iMessageId]['description'] = $asDoc['title']; break; case self::MESSAGE_ADD_TABLE: case self::MESSAGE_EDIT_TABLE: $asTable = $this->getTableInfo($asMessages['messages'][$iMessageId]['message']); $asMessages['messages'][$iMessageId]['description'] = $asTable['title']; break; case self::MESSAGE_ARTICLE: $asTransferredInfo = $this->getArticleInfo($asMessages['messages'][$iMessageId]['message']); $asMessages['messages'][$iMessageId] = array_merge($asMessages['messages'][$iMessageId], $asTransferredInfo); break; case self::MESSAGE_INVITE: //Switch Chan ID with name for the user to join $asMessages['messages'][$iMessageId]['id_chan'] = $this->oMySql->selectValue(self::CHAN_TABLE, 'safe_name', $iChanId); break; } //Json message if(mb_substr($asMessages['messages'][$iMessageId]['message'], 0, $iPrefixLen) == self::JSON_PREFIX) { $asMessages['messages'][$iMessageId]['message'] = json_decode(mb_substr($asMessages['messages'][$iMessageId]['message'], $iPrefixLen)); } else //Normal message { //Internal links $asMessages['messages'][$iMessageId]['message'] = Toolbox::findReplaceLinks($asMessages['messages'][$iMessageId]['message']); //Dynamic chan link $asPatterns = '/(^|\s)#(\w*[^\s]+\w*)/u'; $asLinks = '\1#\2'; $asMessages['messages'][$iMessageId]['message'] = preg_replace($asPatterns, $asLinks, $asMessages['messages'][$iMessageId]['message']); } } //Set last message Id (if new messages since $iFirstMsgId) if(!empty($asMessages['messages'])) { $asMessages['last_message_id'] = max(array_keys($asMessages['messages'])); } return $this->jsonExport($asMessages); } public function getNews($bExport=true) { $sMsgIdCol = MySqlManager::getId(self::MSG_TABLE); $sMsgTxtCol = MySqlManager::getText(self::MSG_TABLE); //News $asInfo['select'] = array($sMsgIdCol, 'nickname', $sMsgTxtCol, 'type', 'led'); $asInfo['from'] = self::MSG_TABLE; $asInfo['constraint'] = array('type'=>self::MESSAGE_NEWS); $asInfo['orderBy'] = array('led'=>'DESC'); if($bExport) $asInfo['limit'] = 3; $asNews = $this->oMySql->selectRows($asInfo); //Status //$asInfo['select'] = array($sMsgIdCol, 'nickname', "CONCAT(nickname, SPACE(1), ".$sMsgTxtCol." AS ".$sMsgTxtCol, 'led'); $asInfo['constraint'] = array('type'=>self::MESSAGE_STATUS); $asStatus = $this->oMySql->selectRows($asInfo); //Sorting //FIXME find a way to do it in SQL $asNews = array_merge($asNews, $asStatus); foreach($asNews as $iKey=>$asNewsInfo) $asNewsSort[$iKey] = strtotime($asNewsInfo['led']); arsort($asNewsSort); foreach($asNewsSort as $iKey=>$iTimestamp) { if($asNews[$iKey]['type']==self::MESSAGE_STATUS) $asNews[$iKey][$sMsgTxtCol] = $asNews[$iKey]['nickname'].' '.$asNews[$iKey][$sMsgTxtCol]; $asNews2[] = $asNews[$iKey]; if($bExport && count($asNews2)==self::MAX_NB_NEWS) break; } $asFormatNews = array(); foreach($asNews2 as $asNew) { $iListId = '-'.$asNew[$sMsgIdCol]; $asFormatNews[$iListId][$sMsgIdCol] = $asNew[$sMsgIdCol]; $asFormatNews[$iListId]['time'] = $asNew['led']; $asFormatNews[$iListId]['time_desc'] = ToolBox::getDateTimeDesc($asNew['led']); $asFormatNews[$iListId]['message'] = self::getDescriptionFormat($asNew['message']); $asFormatNews[$iListId]['nickname'] = self::getNickNameFormat($asNew['nickname']); } $sSuccess = (count($asFormatNews)>0); return $bExport?$this->getJsonPostResult($sSuccess, $sSuccess?'':'Aucune news', array('news'=>$asFormatNews)):$asFormatNews; } private function getConnectedChans($iuserId=0) { $iuserId = $iuserId>0?$iuserId:$this->getUserId(); $sUserIdCol = MySqlManager::getId(self::USER_TABLE); $asInfo = array('select' => array(MySqlManager::getId(self::CHAN_TABLE, true), MySqlManager::getText(self::CHAN_TABLE)), 'from' => self::CONN_TABLE, 'join' => array(self::CHAN_TABLE=>MySqlManager::getId(self::CHAN_TABLE)), 'constraint'=> array($sUserIdCol=>$iUserId, 'led'=>"DATE_SUB(NOW(), INTERVAL ".self::KEEP_ALIVE." SECOND)"), 'constOpe' => array($sUserIdCol=>'=', 'led'=>'>'), 'constVar' => true); return $this->oMySql->selectRows($asInfo, true, MySqlManager::getId(self::CONN_TABLE)); } public function getConnectedUsers($bUserRestricted=false, $bJson=true) { $sQuery = " SELECT /* config.php 1313 */ conn2.id_channel, conn2.id_user, conn2.led, IF(DATE_SUB(NOW(), INTERVAL 1 MINUTE) < conn2.led, 0, 1) AS afk, users.first_name, users.last_name, companies.company, companies.logo, option_nickname.option AS nickname, option_status.option AS status FROM connections AS conn1 LEFT JOIN connections AS conn2 ON conn2.id_channel = conn1.id_channel LEFT JOIN users ON users.id_user = conn2.id_user LEFT JOIN companies ON companies.id_company = users.id_company LEFT JOIN `options` AS option_nickname ON option_nickname.id_user = users.id_user AND option_nickname.id_option_name = ".self::OPT_NICKNAME." LEFT JOIN `options` AS option_status ON option_status.id_user = users.id_user AND option_status.id_option_name = ".self::OPT_STATUS." WHERE conn2.led > DATE_SUB(NOW(), INTERVAL ".self::KEEP_ALIVE." SECOND)". ($bUserRestricted?"AND conn1.id_user = ".$this->getUserId():"")." GROUP BY conn2.id_channel, conn2.id_user ORDER BY option_nickname.option ASC"; $asUserChannels = $this->oMySql->getArrayQuery($sQuery, true); //Last messages $iUserIdCol = MySqlManager::getId(self::USER_TABLE); $asLastMsg = $this->oMySql->selectRows(array('select'=>array($iUserIdCol, 'MAX(led)'), 'from'=>self::MSG_TABLE), true, $iUserIdCol); $asConnectedUsers = array(); foreach($asUserChannels as $asUser) { $sChanId = $asUser[MySqlManager::getId(self::CHAN_TABLE)]; $iUserId = $asUser[$iUserIdCol]; $sNickName = $asUser['nickname']; $asConnectedUsers[$sChanId][$sNickName.$iUserId]['id_user'] = $iUserId; $asConnectedUsers[$sChanId][$sNickName.$iUserId]['name'] = self::getNameFormat($asUser['first_name'], $asUser['last_name']); $asConnectedUsers[$sChanId][$sNickName.$iUserId]['company'] = self::getCompanyFormat($asUser['company']); $asConnectedUsers[$sChanId][$sNickName.$iUserId]['status'] = $asUser['status']; $asConnectedUsers[$sChanId][$sNickName.$iUserId]['logo'] = $asUser['logo']; $asConnectedUsers[$sChanId][$sNickName.$iUserId]['nickname'] = self::getNickNameFormat($sNickName==''?$asUser['first_name']:$sNickName); $asConnectedUsers[$sChanId][$sNickName.$iUserId]['last_activity'] = array_key_exists($iUserId, $asLastMsg)?self::getDateFormat($asLastMsg[$iUserId], self::TIME_FORMAT):''; $asConnectedUsers[$sChanId][$sNickName.$iUserId]['ping'] = self::getDateFormat($asUser['led'], self::TIME_FORMAT); $asConnectedUsers[$sChanId][$sNickName.$iUserId]['afk'] = $asUser['afk']; } return $bJson?$this->jsonExport($asConnectedUsers):$asConnectedUsers; } private function getUserIdFromNickName($sNickName) { $asContraints = array( 'LOWER(`'.MySqlManager::getText(self::OPT_TABLE).'`)' => mb_strtolower($sNickName), MySqlManager::getId(self::OPTNAME_TABLE) => self::OPT_NICKNAME); return $this->oMySql->selectValue(self::OPT_TABLE, MySqlManager::getId(self::USER_TABLE), $asContraints); } private function getChatNickNames($iUserId=0) { $sUserIdCol = MySqlManager::getId(self::USER_TABLE); $sNicknameCol = MySqlManager::getText(self::OPT_TABLE); $asConstraints = array(MySqlManager::getId(self::OPTNAME_TABLE)=>self::OPT_NICKNAME); if($iUserId>0) { $asConstraints[MySqlManager::getId(self::USER_TABLE)] = $iUserId; $oResult = $this->oMySql->selectValue(self::OPT_TABLE, $sNicknameCol, $asConstraints); } else { $asInfo = array('select'=>array($sUserIdCol, $sNicknameCol), 'from'=>self::OPT_TABLE, 'constraint'=>$asConstraints); $oResult = $this->oMySql->selectRows($asInfo, true, $sUserIdCol); } return $oResult; } private function switchCodeId(&$iCodeId, $sMode) { switch($sMode) { case 'first': $iCodeId = $this->oMySql->selectValue(self::CODE_TABLE, 'refer_id', $iCodeId); break; case 'last': $iRefId = $this->oMySql->selectValue(self::CODE_TABLE, 'refer_id', $iCodeId); $iCodeId = $this->oMySql->selectValue(self::CODE_TABLE, 'MAX(id_code)', array('refer_id'=>$iRefId)); break; } } private function getIdCodeFromPhrase($sPhrase) { $iCodeId = $this->oMySql->selectValue(self::URL_TABLE, MySqlManager::getId(self::CODE_TABLE), array('phrase'=>$sPhrase)); $this->switchCodeId($iCodeId, 'last'); return $iCodeId; } private function getPhraseFromIdCode($iCodeId) { $this->switchCodeId($iCodeId, 'first'); return $this->oMySql->selectValue(self::URL_TABLE, 'phrase', array('id_code'=>$iCodeId)); } private function getCodeVersions($iRefCodeId) { $asCodeVersions = array(); if($iRefCodeId>0) { $asInfo = array('select'=>array(MySqlManager::getId(self::CODE_TABLE)), 'from'=>self::CODE_TABLE, 'constraint'=>array('refer_id'=>$iRefCodeId), 'orderBy'=>array('id_code'=>'asc')); $asCodeIds = $this->oMySql->selectRows($asInfo); foreach($asCodeIds as $iCodeId) { $asCodeVersions[] = $this->getCodeInfo($iCodeId); } } return $asCodeVersions; } public function getColoredCode($oCode) { $asCode = $this->getCodeInfo($oCode, '', true); //code $this->oClassManagement->incClass('reader'); $oReader = new Reader($asCode['code']); $asCode['code'] = $oReader->getColoredCode(); //phrase $sPhrase = $this->getPhraseFromIdCode($asCode['id_code']); if($sPhrase !== false) { $asCode['phrase'] = $sPhrase; } //user $asUsers[$asCode['id_user']] = $this->getUserInfo($asCode['id_user']); $asCode = array_merge($asCode, $asUsers[$asCode['id_user']]); //versions $asCodeVersions = $this->getCodeVersions($asCode['refer_id']); $iCodeRowId = 0; foreach($asCodeVersions as $iRowId=>$asCodeVersion) { if($asCodeVersion['id_code']==$asCode['id_code']) $iCodeRowId = $iRowId; } $asCode['truncated'] = ($iCodeRowId > self::MAX_LIST_LENGTH)?$asCodeVersions[$iCodeRowId - 1 - self::MAX_LIST_LENGTH]['id_code']:0; foreach($asCodeVersions as $iRowId=>$asCodeVersion) { if($iCodeRowId - $iRowId <= self::MAX_LIST_LENGTH) { if(!array_key_exists($asCodeVersion['id_user'], $asUsers)) { $asUsers[$asCodeVersion['id_user']] = $this->getUserInfo($asCodeVersion['id_user']); } if($asCodeVersion['id_code']!=$asCode['id_code']) { $asVersionInfo = array_merge($asCodeVersion, $asUsers[$asCodeVersion['id_user']]); $asCode['other_versions'][] = $asVersionInfo; } } } return $this->jsonExport($asCode); } public function getNudeCode($oCode) { $asCode = $this->getCodeInfo($oCode, '', true); //$sCode = Reader::convText2Html($asCode['code']); return $asCode['code']; } public function getRawCode($oCode, $bPrint=false) { $asCode = $this->getCodeInfo($oCode, '', true); $asUser = $this->getUserInfo($asCode['id_user']); $sEncodedCode = $this->jsonConvert($asCode['code']); $sEncodedDesc = $this->jsonConvert($asCode['description']); $oRawCodePage = new Mask('raw_code'); $oRawCodePage->setTags(array( 'text_enc'=>Settings::TEXT_ENC, 'author'=>$asUser['name'].' ('.$asUser['company'].')', 'content'=>$sEncodedCode, 'title'=>$sEncodedDesc, 'print'=>$bPrint?'true':'false')); return $oRawCodePage->getMask(); } public function getSavedCode($oCode) { $asCode = $this->getCodeInfo($oCode, '', true); $sPhrase = $this->getPhraseFromIdCode($asCode['id_code']); if(!$sPhrase) { $sPhrase = 'code_numero_'.$asCode['id_code']; } //set headers header('Pragma: public'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Cache-Control: public'); header('Content-Description: File Transfer'); header('Content-Type: application/force-download'); header('Content-Disposition: attachment; filename='.$sPhrase.'.abap'); header('Content-Transfer-Encoding: binary'); //header('Content-Length: '.filesize($sFilePath)); return $asCode['code']; } public function getItemList() { $asUsers = $asItemList = array(); $sIdUserCol = MySqlManager::getId(self::USER_TABLE); //TODO phrases for all item types? $asTypeTables = $this->getTypeInfo('table'); foreach($asTypeTables as $sType=>$sTable) { //selecting last version among codes having the same refer_id $sTableIdCol = MySqlManager::getId($sTable); $asInfo = array('select' => array("MAX({$sTableIdCol}) AS id_item"), 'from' => $sTable, 'groupBy' => array(($sType==self::ART_TYPE)?$sTableIdCol:'refer_id'), //no versioning for articles 'orderBy' => array('id_item'=>'desc')); //Build code info structure $asTypedItemIds = array_filter($this->oMySql->selectRows($asInfo)); //null value returned from query (MAX(...)) foreach($asTypedItemIds as $iItemId) { //Getting item info $asItem = $this->getItemInfo($sType, $iItemId); $asItem['type'] = $sType; $asItem['id_item'] = $iItemId; //Replacing user's id with user's name & company (if not done already) if(array_key_exists($sIdUserCol, $asItem)) { $iUserId = $asItem[$sIdUserCol]; if(!array_key_exists($iUserId, $asUsers)) $asUsers[$iUserId] = $this->getUserInfo($iUserId); $asItem['name'] = $asUsers[$iUserId]['name']; $asItem['company'] = $asUsers[$iUserId]['company']; } //Preparing key for reverse sorting $asItemList[$asItem['timestamp'].$asItem['type'].$asItem['id_item']] = $asItem; } } krsort($asItemList); return $this->jsonExport($asItemList); } public function getCodeBlock() { $oMask = new Mask(); $oMask->initFile('code_block'); $oMask->setTag('item', $this->getItemBlock()); return $oMask->getMask(); } private function getItemBlock() { $oMask = new Mask('item'); return $oMask->getMask(); } public static function checkNoAuthCookieResetAction($sAction) { return in_array($sAction, array('messages', 'upload_image', 'user_info', 'rss')); } public function logMeIn($sToken, $sAction) { $iUserId = 0; $sNameToken = ''; $bResetPass = true; $sUserTableId = MySqlManager::getId(self::USER_TABLE); //login using form if($sAction!=self::EXT_ACCESS) { if($sToken!='') { $sNameToken = strstr($sToken, self::NAME_PASS_SEP, true); $sPassToken = substr(strstr($sToken, self::NAME_PASS_SEP), 1); //Check name //TODO replace SPACE(1) with self::FIRST_LAST_SEP (separate first and last name on logon page) $asConsts = array('MD5(CONCAT(first_name, SPACE(1), last_name))'=>$sNameToken, 'active'=>self::MEMBER_ACTIVE); $asInvConsts = array('MD5(CONCAT(last_name, SPACE(1), first_name))'=>$sNameToken, 'active'=>self::MEMBER_ACTIVE); $iUserId = $this->oMySql->selectValue(self::USER_TABLE, $sUserTableId, $asConsts); if(!$iUserId) $iUserId = $this->oMySql->selectValue(self::USER_TABLE, $sUserTableId, $asInvConsts); //Check Pass if(!$this->oAuth->CheckPassword($sPassToken, $this->oMySql->selectValue(self::USER_TABLE, 'pass', $iUserId))) $iUserId = 0; } //auto login by cookie elseif(isset($_COOKIE[self::USER_COOKIE_ID])) { $asConstraints = array( $sUserTableId=>$_COOKIE[self::USER_COOKIE_ID], 'auth_cookie'=>$_COOKIE[self::USER_COOKIE_PASS], 'active'=>self::MEMBER_ACTIVE); $asUserInfo = $this->oMySql->selectRow(self::USER_TABLE, $asConstraints, array($sUserTableId, 'led')); $iUserId = $asUserInfo[$sUserTableId]; //Check pass reset necessity $bResetPass = (mb_substr($asUserInfo['led'], 0, 10) != date(Databap::DATE_SQL_FORMAT)); } } //Login using Token (limited access) elseif($sToken!='') { $iUserId = $this->checkExternalAccessToken($sToken); $bResetPass = false; } if($iUserId>0) { $this->setUserId($iUserId); if(!self::checkNoAuthCookieResetAction($sAction) && $bResetPass) { $this->resetAuthCookie(); } //Post-Redirect-Get if user manually logging from logon page if($sNameToken!='') { header('HTTP/1.1 303 See Other'); header('Location: '.$_SERVER['REQUEST_URI']); exit(); } } return ($this->getUserId()>0); } private static function getLoginToken($sPass) { return md5($sPass.$_GET['serv_name']); } public function checkSetPass($sToken, $sNewToken) { $bSuccess = false; $sDesc = ''; if($this->oAuth->CheckPassword($sToken, $this->oMySql->selectValue(self::USER_TABLE, 'pass', $this->getUserId()))) { $bSuccess = $this->oMySql->updateRow(self::USER_TABLE, $this->getUserId(), array('pass'=>$this->oAuth->HashPassword($sNewToken))); $sDesc = $bSuccess?'Mot de passe modifié avec succès':'Une erreur au niveau de la base données est apparue'; } else $sDesc = 'Le mot de passe actuel est erroné'; return $this->getJsonPostResult($bSuccess, $sDesc); } public function resetPass($iUserId) { if($iUserId>0) { $sUserIdCol = MySqlManager::getId(self::USER_TABLE, true); $asInfo = array('select'=>array($sUserIdCol, MySqlManager::getText(self::COMP_TABLE)), 'from'=> self::USER_TABLE, 'join'=> array(self::COMP_TABLE=>MySqlManager::getId(self::COMP_TABLE)), 'constraint'=>array($sUserIdCol=>$iUserId)); $asUsers = $this->oMySql->selectRows($asInfo); foreach($asUsers as $asUser) { $sToken = $this->oAuth->HashPassword(self::getLoginToken($asUser[MySqlManager::getText(self::COMP_TABLE)])); $iUserId = $asUser[MySqlManager::getId(self::USER_TABLE)]; $this->oMySql->updateRow(self::USER_TABLE, $iUserId, array('pass'=>$sToken)); } } else return 'KO'; return 'OK'; } private function getExternalAccessPass($iUserId) { $sPass = ''; if($iUserId>0) { $asUser = $this->oMySql->selectRow(self::USER_TABLE, $iUserId, array('first_name', 'last_name', MySqlManager::getId(self::COMP_TABLE))); $sCompanyName = $this->oMySql->selectvalue(self::COMP_TABLE, MySqlManager::getText(self::COMP_TABLE), $asUser[MySqlManager::getId(self::COMP_TABLE)]); $sPass = $asUser['first_name'].$asUser['last_name'].$sCompanyName; } else $this->addError('generating token : invalid user id "'.$iUserId.'"'); return $sPass; } private function generateExternalAccessToken($iUserId) { return $this->oAuth->HashPassword($this->getExternalAccessPass($iUserId)); } private function checkExternalAccessToken($sKey) { $iUserId = mb_strstr($sKey, '_', true); $asConstraints = array(MySqlManager::getId(self::USER_TABLE)=>$iUserId, 'active'=>self::MEMBER_ACTIVE); $sToken = mb_substr($sKey, mb_strlen($iUserId)+1); return ($this->checkValue(self::USER_TABLE, $asConstraints) && $this->oAuth->CheckPassword($this->getExternalAccessPass($iUserId), $sToken))?$iUserId:0; } private function generateExternalAccessLink($sType, $iUserId=0) { if($iUserId==0) $iUserId = $this->getUserId(); return $_GET['serv_name'].'?a='.self::EXT_ACCESS.'&p='.$sType.'&auth_token='.$iUserId.'_'.$this->generateExternalAccessToken($iUserId); } private function getInternalLink($sPage, $oId=0) { return $_GET['serv_name'].'#'.$sPage.($oId?'-'.$oId:''); } private function getAuthCookie() { return $this->oAuth->HashPassword( $_SERVER['HTTP_USER_AGENT']. $_SERVER['REMOTE_ADDR']. $_SERVER['REQUEST_TIME']. mb_strstr(microtime(), ' ', true). $_SERVER['SERVER_SIGNATURE']. $_SERVER['SERVER_ADMIN']); } private function resetAuthCookie() { $iUserId = $this->getUserId(); $sNewPass = $this->getAuthCookie(); $iTimeLimit = time()+60*60*24*self::COOKIE_LIFESPAN; $this->oMySql->updateRow(self::USER_TABLE, $iUserId, array('auth_cookie'=>$sNewPass)); setcookie(self::USER_COOKIE_ID, $iUserId, $iTimeLimit); setcookie(self::USER_COOKIE_PASS, $sNewPass, $iTimeLimit); } public function logMeOut() { $this->disconnectChat(); $this->setUserId(0); setcookie(self::USER_COOKIE_ID, '', time()-60*60); setcookie(self::USER_COOKIE_PASS, '', time()-60*60); } /* Not needed so far public function setExpectedPage($sExpectedPage) { setcookie(self::EXPECTED_PAGE_COOKIE, $sExpectedPage, time()+60*60); } public function redirectExpectedPage() { if(array_key_exists(self::EXPECTED_PAGE_COOKIE, $_COOKIE)) { $sLocation = $_COOKIE[self::EXPECTED_PAGE_COOKIE]; setcookie(self::EXPECTED_PAGE_COOKIE, '', time()-60*60); header('Location:'.$sLocation); } } */ public function getArticle($iArtId) { return $this->jsonExport($this->getArticleInfo($iArtId)); } public function redirectArticle($iArtId) { $asArtInfo = $this->getArticleInfo($iArtId); header('Location:'.$asArtInfo['link_art']); } public function disconnectChat() { $sTime = $this->oMySql->selectRows(array('select'=>'DATE_SUB(NOW(), INTERVAL '.self::KEEP_ALIVE.' SECOND)')); //Is the user connected? $sUserIdColName = MySqlManager::getId(self::USER_TABLE); $bConnected = $this->oMySql->selectRows(array('select'=>array('COUNT(1)'), 'from'=>self::CONN_TABLE, 'constraint'=>array($sUserIdColName=>$this->getUserId(), 'led'=>$sTime), 'constOpe'=>array($sUserIdColName=>'=', 'led'=>'>'))); if($bConnected) { $this->oMySql->updateRows(self::CONN_TABLE, array(MySqlManager::getId(self::USER_TABLE)=>$this->getUserId()), array('led'=>$sTime)); $this->addMessage('se déconnecte', self::MESSAGE_CONN, self::DEFAULT_CHAN_ID); } } public function checkValue($sTableName, $asConstraints) { return $this->oMySql->selectValue($sTableName, 'COUNT(1)', $asConstraints); } public function resetChanSafeNames() { $iChanIdCol = MySqlManager::getId(self::CHAN_TABLE); $asChans = $this->oMySql->selectRows(array('select'=>array($iChanIdCol, MySqlManager::getText(self::CHAN_TABLE)), 'from'=>self::CHAN_TABLE), true, $iChanIdCol); $asResult = array(); foreach($asChans as $iChanId=>$sChanName) { $asResult[$iChanId] = ($this->oMySql->updateRow(self::CHAN_TABLE, $iChanId, array('safe_name'=>self::getChanSafeName($sChanName))) > 0)?'Fixed':'Not Fixed'; } return MySqlManager::implodeAll($asResult, ' : ', "\n", 'Result reset ID channel ', '.'); } public static function getChanSafeName($sChanName) { //TODO replace unsafe chars with unique id $sChanSafeName = preg_replace('/[^a-z0-9]/u', '_', mb_strtolower($sChanName)); //Sort PM chans $asPm = self::isPmChan($sChanSafeName); if(!$asPm['is_pm']) $sChanSafeName = $asPm['chan_name']; return $sChanSafeName; } public function getResults($sSearchWords) { $this->oSearchEngine->setWords($sSearchWords); $asResults = $this->oSearchEngine->getResults(); //complementary infos $asCompleteResults = array(); foreach($asResults as $asItemInfo) { //Item Info $iItemId = $asItemInfo['id_item']; $sType = $asItemInfo['type']; $asItemInfo += $this->getItemInfo($sType, $iItemId); //User Info if($sType != self::ART_TYPE) //Already available in item info { $asUserInfo = $this->getUserInfo($asItemInfo[MySqlManager::getId(self::USER_TABLE)]); $asItemInfo['name'] = $asUserInfo['name']; $asItemInfo['company'] = $asUserInfo['company']; } //TODO: phrase $asCompleteResults[] = $asItemInfo; } return $this->jsonExport($asCompleteResults); } public function getStyleSheet() { $sStyle = file_get_contents(self::STYLE_PATH); $asDefaultColors = array( self::OPT_BG=>'#04357B', self::OPT_BRIGHT_BG=>'#D9E5F2', self::OPT_HOVER=>'#EFAB00', self::OPT_IMAGE_CHAT=>'images/sap_gold_332.jpg'); //Inserting Color Ids foreach($asDefaultColors as $iOptionNameId=>$sDefaultColor) { $asColorAnchors[$iOptionNameId] = '[OPT#'.$iOptionNameId.']'; } $sStyle = str_replace($asDefaultColors, $asColorAnchors, $sStyle); //Switching color Ids with user colors $asOptionvalues = $this->getUserOptions(array_keys($asDefaultColors)); foreach($asColorAnchors as $iOptionNameId=>$sColorAnchor) { $sOptionValue = (array_key_exists($iOptionNameId, $asOptionvalues) && $asOptionvalues[$iOptionNameId]['option']!='')?$asOptionvalues[$iOptionNameId]['option']:$asDefaultColors[$iOptionNameId]; $sStyle = str_replace($sColorAnchor, $sOptionValue, $sStyle); } //setting header content type header("Content-Type: text/css"); return $sStyle; } public static function getDateFormat($oTime, $sFormat=Databap::DATE_TIME_FORMAT) { $iTimeStamp = is_numeric($oTime)?$oTime:strtotime($oTime); return date($sFormat, $iTimeStamp); } public static function getNameFormat($sFirstName, $sLastName) { return ToolBox::capitalizeWords(trim($sFirstName.self::FIRST_LAST_SEP.$sLastName), ' -');; } public static function getNickNameFormat($sNickName) { $sNickName = ToolBox::capitalizeWords(trim($sNickName), ' -'); return str_replace(' ', '_', $sNickName); } public static function getCompanyFormat($sCompany) { return mb_strlen($sCompany)>3?ToolBox::mb_ucwords($sCompany):mb_strtoupper($sCompany); } public static function getDescriptionFormat($sDescription) { return ToolBox::mb_ucfirst(ToolBox::findReplaceLinks($sDescription)); } public static function getTableFormat($sTable) { return mb_strtoupper($sTable); } public function getJsonPostResult($bSuccess, $sDesc, $asVars=array()) { if(!$bSuccess) $this->addError($sDesc); return self::jsonExport(array('result'=>$bSuccess?self::SUCCESS:self::ERROR, 'desc'=>$sDesc)+$asVars); } public static function jsonExport($asData) { header('Content-type: application/json'); return self::jsonConvert($asData); } public static function jsonConvert($asData) { //return htmlspecialchars(json_encode($asData), ENT_NOQUOTES); return json_encode($asData); } public static function getMaxSize() { $iPostSize = self::toBytes(ini_get('post_max_size')); $iUploadSize = self::toBytes(ini_get('upload_max_filesize')); return min($iPostSize, $iUploadSize); } public static function toBytes($str) { $val = trim($str); $last = mb_strtolower($str[mb_strlen($str)-1]); switch($last) { case 'g': $val *= 1024; case 'm': $val *= 1024; case 'k': $val *= 1024; } return $val; } } ?>