Files
databap/config.php

4466 lines
147 KiB
PHP
Executable File

<?php
/**
* Ideas
* code page : hover -> wait 1sec -> if(focus) -> expand {-5 lines, + 5 lines}
* Translations in EN / ES
*/
/**
* Manage includes
* @author franzz
*/
class ClassManagement extends PhpObject
{
const INC_FOLDER = 'inc/';
const INC_EXT = '.php';
const SETTINGS_FILE = 'settings.php';
private $asIncFiles;
function __construct()
{
parent::__construct();
$this->asIncFiles = array();
$this->incFile(self::SETTINGS_FILE);
}
function __destruct()
{
parent::__destruct();
}
public function incClass($sClassName)
{
return $this->incFile(self::INC_FOLDER.$sClassName.self::INC_EXT);
}
public function incFile($sFilePath, $bMandatory=true)
{
$bIncluded = false;
if(!in_array($sFilePath, $this->asIncFiles))
{
$sMissingFile = 'File "'.$sFilePath.'" missing.';
if(file_exists($sFilePath))
{
$bIncluded = require_once($sFilePath);
$this->asIncFiles[] = $sFilePath;
}
elseif($bMandatory)
{
die($sMissingFile.' Stopping process.');
}
else
{
$this->addError($sMissingFile);
}
}
return $bIncluded;
}
}
/**
* Common class for all classes.
* Handles the error log process
* @author franzz
*/
class PhpObject
{
//Log file name
const LOG_FILENAME = 'log.html';
//Message types
const NOTICE_TAB = 'Notice';
const WARNING_TAB = 'Warning';
const ERROR_TAB = 'Error';
const ALL_TAB = 'All';
//Extraction mode
const MODE_ARRAY = 0;
const MODE_TEXT = 1;
const MODE_HTML = 2;
const MODE_FILE = 3;
//Class variables
private $asMessageStack;
private $iExtractMode;
private $bDebug;
function __construct($iExtractMode=self::MODE_FILE)
{
$this->resetMessageStack();
$this->iExtractMode = $iExtractMode;
$this->setDebug(false);
}
protected function setDebug($bSwitch)
{
$this->bDebug = $bSwitch;
}
private static function getLogPath()
{
return dirname(__FILE__).'/'.self::LOG_FILENAME;
}
private function resetMessageStack($sType=self::ALL_TAB)
{
if($sType==self::ALL_TAB)
{
$this->resetMessageStack(self::NOTICE_TAB);
$this->resetMessageStack(self::WARNING_TAB);
$this->resetMessageStack(self::ERROR_TAB);
}
else
{
$this->asMessageStack[$sType] = array();
}
}
protected function addNotice($sNotice)
{
$this->addTrace(self::NOTICE_TAB, $sNotice);
}
protected function addWarning($sWarning)
{
$this->addTrace(self::WARNING_TAB, $sWarning);
}
protected function addError($sError)
{
$this->addTrace(self::ERROR_TAB, $sError);
}
private function addTrace($sType, $sMessage)
{
$this->asMessageStack[$sType][] = $sMessage;
}
protected function getCleanMessageStack($sType=self::ALL_TAB)
{
$asMessages = ($sType==self::ALL_TAB)?$this->asMessageStack:$this->asMessageStack[$sType];
$this->resetMessageStack($sType);
return $this->glueMessages($asMessages);
}
protected function getCleanMessageStacks($aoExtsources, $sType=self::ALL_TAB)
{
$aoExtsources[] = $this;
$aoMessages = array();
foreach($aoExtsources as $oExtSource)
{
$oMessages = $oExtSource->getCleanMessageStack($sType);
if($oMessages!='')
{
$aoMessages[get_class($oExtSource)] = $oMessages;
}
}
return $this->glueMessages($aoMessages);
}
private function glueMessages($asMessages)
{
switch($this->iExtractMode)
{
case self::MODE_TEXT:
$oMessageStack = self::recursiveImplode("\n", $asMessages);
break;
case self::MODE_HTML:
$oMessageStack = self::recursiveImplode('<br />', $asMessages);
break;
case self::MODE_ARRAY:
$oMessageStack = $asMessages;
break;
case self::MODE_FILE:
$oMessageStack = self::recursiveImplode("\n", $asMessages);
break;
}
return $oMessageStack;
}
private static function flattenMessageStack($asTab, $sGlobalKey='')
{
$asFlatTab = array();
foreach($asTab as $oKey=>$oRow)
{
$sKey = is_numeric($oKey)?$sGlobalKey:$oKey.' - ';
if(is_array($oRow))
{
$asFlatTab = array_merge($asFlatTab, self::flattenMessageStack($oRow, $sKey));
}
else
{
$asFlatTab[] = $sKey.$oRow;
}
}
return $asFlatTab;
}
private static function recursiveImplode($sGlue, $asTab)
{
$asTab = self::flattenMessageStack($asTab);
return implode($sGlue, $asTab);
}
function __destruct()
{
$sErrorStack = $this->getCleanMessageStack($this->bDebug?self::ALL_TAB:self::ERROR_TAB);
if($sErrorStack!='')
{
switch($this->iExtractMode)
{
case self::MODE_TEXT:
echo $sErrorStack;
break;
case self::MODE_HTML:
echo $sErrorStack;
break;
case self::MODE_ARRAY:
break;
case self::MODE_FILE:
@file_put_contents(self::getLogPath(), "\n\n".date('r')."\n".$sErrorStack, FILE_APPEND);
break;
}
}
}
}
/**
* Application Core
* @author franzz
*/
class Databap extends PhpObject
{
//Common Constants
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.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 = '_';
//Code
const MAX_LIST_LENGTH = 5;
//Authorizations
const CLEARANCE_MEMBER = 0;
const CLEARANCE_ADMIN = 9;
const EXT_ACCESS = 'external_access';
const USER_COOKIE_ID = 'id_user';
const USER_COOKIE_PASS = 'checksum';
const COOKIE_LIFETIME = 7;
const TOKEN_LENGTH = 32;
//HTTP Requests response
const DISCONNECTED = '__DISCONNECTED__';
const ERROR = '__ERROR__';
const SUCCESS = '__SUCCESS__';
//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_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 DEFAULT_COMPANY_LOGO = 'tux_24.png';
const DEFAULT_CHAN = 'Principal';
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 KEEP_ALIVE = 600; //seconds
const REBOOT_DELAY = 15; //seconds
const PM_SEP = '___';
const CHAT_IMG_MAX_WIDTH = 700;
const CHAT_IMG_MAX_HEIGHT = 10000;
const JSON_PREFIX = '[\-JSON-/]';
//Options Constants
const LANG_FR = 'FR';
const OPT_TEXT = 'T';
const OPT_SELECT = 'S';
const OPT_NICKNAME = 1;
const OPT_BG = 2;
const OPT_BRIGHT_BG = 3;
const OPT_HOVER = 4;
const OPT_TOKEN = 5;
const OPT_IMAGE_CHAT = 6;
const OPT_STATUS = 7;
//Search Constants
const PROC_TYPE = 'p';
const CODE_TYPE = 'c';
const DOC_TYPE = 'd';
const ART_TYPE = 'a';
//Doc constants
const DOC_FOLDER = 'docs/';
const DOC_TMP_FOLDER = 'docs/tmp/';
//Objects
private $oMySql;
private $oProcedure;
private $oSearchEngine;
private $oClassManagement;
//Variables
private $iUserId;
private $asUserInfo;
private $sLanguage;
function __construct($oClassManagement)
{
parent::__construct();
$this->oMySql = new MySqlManager();
if($this->oMySql->sDbState == MySqlManager::DB_NO_DATA) $this->install();
$this->oProcedure = new Procedure($this->oMySql);
$this->setUserId(0);
$this->sLanguage = self::LANG_FR;
$this->oSearchEngine = new SearchEngine($this->oMySql);
$this->oClassManagement = $oClassManagement;
}
private function install()
{
//Install DB
$this->oMySql->install();
//Options
$sOptionNameCol = MySqlManager::getText(MySqlManager::OPTNAME_TABLE);
$sOptionNameIdCol = MySqlManager::getId(MySqlManager::OPTNAME_TABLE);
$iNicknameOptId = $this->oMySql->insertRow(MySqlManager::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_NICKNAME, $sOptionNameCol=>'pseudo du chat', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR));
$iBgColorOptId = $this->oMySql->insertRow(MySqlManager::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_BG, $sOptionNameCol=>'couleur de fond', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR));
$iBgColorOpt2Id = $this->oMySql->insertRow(MySqlManager::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(MySqlManager::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_HOVER, $sOptionNameCol=>'couleur de survol', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR));
$iHoverColorOptId = $this->oMySql->insertRow(MySqlManager::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_TOKEN, $sOptionNameCol=>'token', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR));
$iChatImageOptId = $this->oMySql->insertRow(MySqlManager::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_IMAGE_CHAT, $sOptionNameCol=>'image du chat', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR));
$iChatImageOptId = $this->oMySql->insertRow(MySqlManager::OPTNAME_TABLE, array($sOptionNameIdCol=>self::OPT_STATUS, $sOptionNameCol=>'Mission en cours', 'type'=>self::OPT_TEXT, 'language'=>self::LANG_FR));
//Insert default and all channels
$this->oMySql->insertRow(MySqlManager::CHAN_TABLE, array('safe_name'=>self::getChanSafeName(self::ALL_CHAN_TEXT), MySqlManager::getText(MySqlManager::CHAN_TABLE)=>self::ALL_CHAN_TEXT));
$this->oMySql->insertRow(MySqlManager::CHAN_TABLE, array('safe_name'=>self::getChanSafeName(self::DEFAULT_CHAN), MySqlManager::getText(MySqlManager::CHAN_TABLE)=>self::DEFAULT_CHAN));
//Install default users : admin and test
$this->addUser('francois', 'lutran', 'cgi', 'francois@lutran.fr', self::CLEARANCE_ADMIN);
$this->addUser('test', 'test', 'test', 'test@test.com');
}
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, $asVars)
{
$oPage = new Mask('index');
$oPage->setTag('first_page', $sPage);
$oPage->setTag('index_link', $asVars['serv_name']);
$oPage->setTag('line_break', "Global databap constants\n");
//Rss Link
$oPage->setTag('rss_link', $this->getUserOptionValue(self::OPT_TOKEN));
//Pass GET variables down to jQuery
$asVars['user_id'] = $this->getUserId();
$sLastKey = end(array_keys($asVars));
foreach($asVars as $sName => $sValue)
{
$oPage->addInstance('VARS', array('var_name'=>$sName, 'var_value'=>$sValue, 'coma'=>$sName==$sLastKey?'':', '));
}
//Pages
$asMaskPaths = glob(Mask::MASK_FOLDER.'*.html');
$asMaskNames = array_map('basename', $asMaskPaths, array_fill(1, count($asMaskPaths), '.html'));
$sLastKey = end(array_keys($asMaskNames));
foreach($asMaskNames as $sKey=>$sMaskName)
{
$oPage->addInstance('PAGES', array('page_name'=>$sMaskName, 'page_value'=>$sMaskName, 'coma'=>$sKey==$sLastKey?'':', '));
}
//Constants
$asConstants = array( 'disconnected'=>self::DISCONNECTED,
'error'=>self::ERROR,
'keep_alive'=>self::KEEP_ALIVE,
'opt_type_text'=>self::OPT_TEXT,
'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);
$oPage->setTag('constants', $this->jsonConvert($asConstants));
return $oPage->getMask();
}
public function getRss($sCat='')
{
//Class Feed
$this->oClassManagement->incClass('rss');
//Building header
$asDesc = array
(
'title'=>'Flux RSS Databap'.($sCat==''?'':' - '.$sCat),
'link'=>$_GET['serv_name'].'rss'.($sCat==''?'':'-'.$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
switch(strtolower($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]*)/i';
foreach($asResult as $iLinkId=>$asRow)
{
//get link out of message
preg_match($sPattern, $asRow['message'], $asMatches);
$asRow['link'] = $asMatches[0];
//add item
$asItem = array
(
'title'=>'Lien'.($sCat==''?'':' - '.$sCat).' #'.($iLinkId+1),
'category'=>$sCat,
'description'=>'Lien post&eacute; par '.self::getNickNameFormat($asRow['nickname']).' &agrave; '.self::getDateFormat($asRow['led']).' : <a href="'.$asRow['link'].'" target="_blank">'.$asRow['message'].'</a>',
'author'=>$asRow['nickname'],
'link'=>$_GET['serv_name'].'chat-'.$asRow['id_message'],
'pub_date'=>$asRow['led'],
'guid'=>$_GET['serv_name'].'chat-'.$asRow['id_message']
);
$oFeed->addItem($asItem);
}
return $oFeed->getFeed();
}
public function syncSapBlog()
{
//Get articles list
$asArticles = $this->getSAPBlogRss();
//Update and spread the news
$asResult = array();
if(date('N')>5) $asResult[] = "Pas de mise-&agrave;-jour pendant le week end !";
else
{
foreach($asArticles as $asArticle)
{
$iArticleId = $this->oMySql->selectValue(MySqlManager::ART_TABLE, MySqlManager::getId(MySqlManager::ART_TABLE), array('title'=>$asArticle['title']));
if($iArticleId==0)
{
$iArticleId = $this->oMySql->insertRow(MySqlManager::ART_TABLE, $asArticle);
$this->addMessage($iArticleId, self::MESSAGE_ARTICLE, self::ALL_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()
{
$sSAPDomain = 'http://scn.sap.com';
$sSAPBlogUrl = $sSAPDomain.'/community/data-warehousing/netweaver-bw/blog';
$oDom = $this->getRemotePageDom($sSAPBlogUrl);
$aoArticles = $oDom->getElementsByTagName('header');
$asArticles = array();
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'] = ucfirst(trim($oLink->nodeValue));
$asArticleInfo['title'] = substr($asArticleInfo['title'], -1)=='.'?substr($asArticleInfo['title'], 0, -1):$asArticleInfo['title'];
$asArticleInfo['link'] = $oLink->getAttribute('href');
$asArticleInfo['date'] = substr(str_replace(array($sSAPBlogUrl.'/', '/'), array('', '-'), $asArticleInfo['link']), 0, 10);
break;
//Author
case 'jiveTT-hover-user jive-username-link':
$asNames = array_filter(explode(' ', ucwords(trim($oLink->nodeValue))));
$asArticleInfo['first_name'] = array_shift($asNames);
$asArticleInfo['last_name'] = implode('-', $asNames);
$asArticleInfo['email'] = $sSAPDomain.$oLink->getAttribute('href');
break;
}
}
$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 = strtolower($sFirstName);
$sLastName = strtolower($sLastName);
$sCompany = strtolower($sCompany);
$sEmail = strtolower($sEmail);
//Checking company existency in company table
$sCompanyTextCol = MySqlManager::getText(MySqlManager::COMP_TABLE);
$iCompanyId = $this->oMySql->selectInsert(MySqlManager::COMP_TABLE, array($sCompanyTextCol=>strtolower($sCompany), 'logo'=>self::DEFAULT_COMPANY_LOGO), array($sCompanyTextCol));
$asInfo = array('first_name'=>$sFirstName,
'last_name'=>$sLastName,
'email'=>$sEmail,
MySqlManager::getId(MySqlManager::COMP_TABLE)=>$iCompanyId,
'clearance'=>$iClearance,
'led'=>'0000-00-00 00:00:00');
$iUserId = $this->oMySql->insertRow(MySqlManager::USER_TABLE, $asInfo);
//Admin Options
$sOptionTable = MySqlManager::OPT_TABLE;
$sUserIdCol = MySqlManager::getId(MySqlManager::USER_TABLE);
$sOptNameIdCol = MySqlManager::getId(MySqlManager::OPTNAME_TABLE);
$sOptionTextCol = MySqlManager::getText(MySqlManager::OPT_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->generateRssLink($iUserId)));
//$this->oMySql->insertRow($sOptionTable, array($sUserIdCol=>$iUserId, $sOptNameIdCol=>self::OPT_IMAGE_CHAT, $sOptionTextCol=>'images/sap_gold_332.jpg'));
}
public function resetToken()
{
$asRs = $this->oMySql->selectRows(array('from'=>'`options`', 'constraint'=>array('id_option_name'=>self::OPT_TOKEN)));
foreach($asRs as $asR)
{
$sTokenLink = $this->generateRssLink($asR['id_user']);
$this->oMySql->updateRow('`options`', array('id_option'=>$asR['id_option']), array('`option`'=>$sTokenLink));
}
return $asRs;
}
private function generateRssLink($iUserId=0)
{
if($iUserId==0) $iUserId = $this->getUserId();
return $_GET['serv_name'].'?a='.self::EXT_ACCESS.'&p=rss&auth_token='.$iUserId.'_'.$this->generateToken($iUserId);
}
private function generateToken($iUserId)
{
$sEncryptedToken = '';
if($iUserId>0)
{
$asUser = $this->oMySql->selectRow(MySqlManager::USER_TABLE, $iUserId, array('first_name', 'last_name', 'email', MySqlManager::getId(MySqlManager::COMP_TABLE)));
$sEncryptedToken = self::encryptPassword($asUser['first_name'].$asUser['last_name'].$asUser['email'].$asUser[MySqlManager::getId(MySqlManager::COMP_TABLE)]);
}
else
{
$this->addError('generating token : invalid user id "'.$iUserId.'"');
}
return $sEncryptedToken;
}
public function buildCompleteIndex()
{
$asSearchTypes = array( self::CODE_TYPE=>MySqlManager::CODE_TABLE,
self::PROC_TYPE=>MySqlManager::PROC_TABLE,
self::ART_TYPE=>MySqlManager::ART_TABLE);
$this->oMySql->getArrayQuery("TRUNCATE ".MySqlManager::SEARCH_TABLE);
foreach($asSearchTypes 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(MySqlManager::CODE_TABLE)=>$sContent,
'description'=>$sDescription,
'id_user'=>$this->getUserId());
$iCodeId = $this->oMySql->insertRow(MySqlManager::CODE_TABLE, $asInsert);
//insert link if exists
if($sLink!='')
{
$asInsert = array(MySqlManager::getId(MySqlManager::CODE_TABLE)=>$iCodeId, 'phrase'=>$sLink);
$this->oMySql->insertRow(MySqlManager::URL_TABLE, $asInsert);
}
//refer id update
$this->oMySql->updateRow(MySqlManager::CODE_TABLE, $iCodeId, array('refer_id'=>$iCodeId));
//Add message
$this->addMessage($iCodeId, self::MESSAGE_ADD_CODE, self::ALL_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(MySqlManager::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(MySqlManager::CODE_TABLE, $asEdit);
//Add message
$this->addMessage($iCodeId, self::MESSAGE_EDIT_CODE, self::ALL_CHAN_ID);
//Add record in Search Table
$this->oSearchEngine->buildIndex($iCodeId, self::CODE_TYPE);
return $iCodeId;
}
public function addProcedure($asPost)
{
$asPost['id_user'] = $this->getUserId();
$this->oProcedure->inputForm($asPost);
$asErrors = $this->oProcedure->checkIntegrity();
if(count($asErrors)==0)
{
//Previous procedure Id
$iPrevProcId = isset($asPost['procedure_id'])?$asPost['procedure_id']:0;
//Load procedure into database
$bCreation = $this->oProcedure->saveProcedure($iPrevProcId);
//Extract extra data
$asProc = $this->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::ALL_CHAN_ID);
}
else
{
$this->addMessage($iNewProcId, self::MESSAGE_EDIT_PROC, self::ALL_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)
{
$this->oProcedure->loadProcedure($iProcId);
$asProc = $this->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 = $asPost['doc_id'];
$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<doc_id>\d+)_image_(?P<doc_info>\w+)/';
foreach($asPost as $sFormId=>$sValue)
{
preg_match($sImagePattern, $sFormId, $asMatches);
if($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, 'file_name'=>$sFileName, MySqlManager::getId(MySqlManager::USER_TABLE)=>$iUserId);
$iDbDocId = $this->oMySql->insertRow(MySqlManager::DOC_TABLE, $asData);
//Load doc files into database
$asDocData[MySqlManager::getId(MySqlManager::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(MySqlManager::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(MySqlManager::DOC_TABLE, 'refer_id', $iPrevDocId);
$this->oMySql->updateRow(MySqlManager::DOC_TABLE, $iDbDocId, array('refer_id'=>$iReferId));
//Add Message in chat
if($bCreation)
{
$this->addMessage($iDbDocId, self::MESSAGE_ADD_DOC, self::ALL_CHAN_ID);
}
else
{
$this->addMessage($iDbDocId, self::MESSAGE_EDIT_DOC, self::ALL_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(MySqlManager::DOC_TABLE, $iDocId);
//Extract extra data
$asUser = $this->getUserInfo($asDoc['id_user']);
$asDoc['name'] = $asUser['name'];
$asDoc['company'] = $asUser['company'];
//Extract doc files
$asFiles = $this->oMySql->selectRows(array('from'=>MySqlManager::FILE_TABLE, 'constraint'=>array('id_doc'=>$iDocId)));
foreach($asFiles as $asFile)
{
$asDoc['files'][$asFile[MySqlManager::getId(MySqlManager::FILE_TABLE)]] = array('description'=>$asFile['description']);
}
return self::jsonExport($asDoc);
}
public function getFile($iFileId)
{
$sFileName = $this->oMySql->selectValue(MySqlManager::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()
{
$oFileUploader = new fileUploader(Procedure::IMAGE_FOLDER_TMP, self::$UPLOAD_IMG_EXTS);
$asResult = $oFileUploader->handleUpload();
return $this->jsonConvert($asResult);
}
public function uploadDoc()
{
$oFileUploader = new fileUploader(self::DOC_TMP_FOLDER, self::$UPLOAD_DOC_EXTS);
$asResult = $oFileUploader->handleUpload();
return $this->jsonConvert($asResult);
}
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 = MySqlManager::getTablecolumns(MySqlManager::CODE_TABLE);
unset($asSelect[MySqlManager::getText(MySqlManager::CODE_TABLE)]);
$asSelect = array_keys($asSelect);
}
else
{
$asSelect = "*";
}
$asCode = $this->oMySql->selectRow(MySqlManager::CODE_TABLE, $iCodeId, $asSelect);
$asCode['description'] = self::getDescriptionFormat($asCode['description']);
$asCode['led'] = self::getDateFormat($asCode['led']);
return $asCode;
}
private function getProcInfo($iProcId)
{
$asProc = $this->oMySql->selectRow(MySqlManager::PROC_TABLE, $iProcId);
$asProc['description'] = self::getDescriptionFormat($asProc['description']);
$asProc['led'] = self::getDateFormat($asProc['led']);
return $asProc;
}
private function getArticleInfo($iArtId)
{
$asArt = $this->oMySql->selectRow(MySqlManager::ART_TABLE, $iArtId);
$asTransferredInfo = array('link_art'=>$asArt['link'], 'title'=>$asArt['title'], 'link_auth'=>$asArt['email']);
$asTransferredInfo['date'] = self::getDateFormat($asArt['date'], self::DATE_FORMAT);
$asTransferredInfo['name'] = self::getNameFormat($asArt['first_name'], $asArt['last_name']);
$asTransferredInfo['description'] = self::getDescriptionFormat($asArt['title']);
$asTransferredInfo['led'] = self::getDateFormat($asArt['led']);
$asTransferredInfo['company'] = 'SAP';
return $asTransferredInfo;
}
public function getUserInfo($iUserId, $bJson=false)
{
if($iUserId==$this->getUserId() && !empty($this->asUserInfo))
{
$asUserInfo = $this->asUserInfo;
}
else
{
$asRow = $this->oMySql->selectRow(MySqlManager::USER_TABLE, $iUserId);
$asCompany = $this->oMySql->selectRow(MySqlManager::COMP_TABLE, $asRow[MySqlManager::getId(MySqlManager::COMP_TABLE)]);
$asUserInfo = array( 'name'=>self::getNameFormat($asRow['first_name'], $asRow['last_name']),
'nickname'=>self::getNickNameFormat($this->getChatNickNames($iUserId)),
'email'=>$asRow['email'],
'company'=>self::getCompanyFormat($asCompany[MySqlManager::getText(MySqlManager::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(MySqlManager::OPTVAL_TABLE);
$sOptionTextCol = MySqlManager::getText(MySqlManager::OPT_TABLE);
$sOptNameTextCol = MySqlManager::getText(MySqlManager::OPTNAME_TABLE);
$sOptValueTextCol = MySqlManager::getText(MySqlManager::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'=>MySqlManager::OPTVAL_TABLE,
'constraint'=>array('language'=>$this->sLanguage,
MySqlManager::getId(MySqlManager::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(MySqlManager::OPTVAL_TABLE);
break;
case self::OPT_TEXT: //insert value
$sUpdateCol = MySqlManager::getText(MySqlManager::OPT_TABLE);
break;
default:
continue 2;
}
$sNewValue = $asUserOptions[$sOptNameId];
//Check identical data
$asKeys = array(MySqlManager::getId(MySqlManager::USER_TABLE)=>$this->getUserId(), MySqlManager::getId(MySqlManager::OPTNAME_TABLE)=>$sOptNameId);
$asData = array($sUpdateCol=>$sNewValue) + $asKeys;
$sOldValue = $this->oMySql->selectValue(MySqlManager::OPT_TABLE, $sUpdateCol, $asKeys);
//Update value
if($sOldValue!=$sNewValue)
{
//Update value
$this->oMySql->insertUpdateRow(MySqlManager::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::ALL_CHAN_TEXT;
$sMessage = $sOldValue.' a chang&eacute; son pseudo en '.$sNewValue;
break;
case self::OPT_STATUS:
$sType = self::MESSAGE_STATUS;
$sChanName = self::ALL_CHAN_TEXT;
$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(MySqlManager::OPTNAME_TABLE);
$sOptNameTextCol = MySqlManager::getText(MySqlManager::OPTNAME_TABLE);
$asInfo = array('select'=>array($sOptNameIdCol, $sOptNameTextCol, 'type'),
'from'=>MySqlManager::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['option'];
}
private function getUserOptions($oOptionNameIds=array(), $iUserId=0)
{
$iUserId = $iUserId>0?$iUserId:$this->getUserId();
$sUserIdCol = MySqlManager::getId(MySqlManager::USER_TABLE);
$sOptNameIdCol = MySqlManager::getId(MySqlManager::OPTNAME_TABLE);
$sOptValueIdCol = MySqlManager::getId(MySqlManager::OPTVAL_TABLE);
$sOptionTextCol = MySqlManager::getText(MySqlManager::OPT_TABLE);
if(!is_array($oOptionNameIds))
{
$oOptionNameIds = array($oOptionNameIds);
}
$asUserinfo = array('select'=>array($sOptNameIdCol, $sOptValueIdCol, $sOptionTextCol),
'from'=>MySqlManager::OPT_TABLE,
'constraint'=>array($sUserIdCol=>$iUserId));
if(count($oOptionNameIds)>0)
{
$asUserinfo['constraint'][$sOptNameIdCol] = "(".implode(", ", $oOptionNameIds).")";
$asUserinfo['constOpe'] = array($sUserIdCol=>"=", $sOptNameIdCol=>" IN ");
$asUserinfo['constVar'] = true;
}
return $this->oMySql->selectRows($asUserinfo, true, $sOptNameIdCol);
}
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(MySqlManager::USER_TABLE, MySqlManager::getId(MySqlManager::USER_TABLE), array('user'=>$oUser));
$iUserId = !$oRes?$this->getUserId():$oRes;
break;
default:
$iUserId = $this->getUserId();
break;
}
//User Info
$asProfile = $this->getUserInfo($iUserId);
//History Info
$iFullCodeId = MySqlManager::getId(MySqlManager::CODE_TABLE, true);
$iFullLedName = MySqlManager::getFullColumnName(MySqlManager::CODE_TABLE, 'led');
$asInfo = array('select'=>array($iFullCodeId, 'description', 'refer_id', $iFullLedName, 'phrase'),
'from'=>MySqlManager::CODE_TABLE,
'join'=>array(MySqlManager::URL_TABLE=>MySqlManager::getId(MySqlManager::CODE_TABLE)),
'constraint'=>array('id_user'=>$iUserId),
'orderBy'=>array('led'=>'DESC'));
$asHistory = $this->oMySql->selectRows($asInfo);
foreach($asHistory as $asCode)
{
$asProfile['history'][$asCode['id_code']]['action'] = (($asCode['refer_id']==$asCode['id_code'])?'Création':'Modification').' de code';
$asProfile['history'][$asCode['id_code']]['date'] = self::getDateFormat($asCode['led']);
$asProfile['history'][$asCode['id_code']]['description'] = $asCode['description'];
$asProfile['history'][$asCode['id_code']]['phrase'] = ($asCode['phrase']=='')?$asCode['id_code']:$asCode['phrase'];
}
return $this->jsonExport($asProfile);
}
private static function isPmChan($sChanSafeName)
{
$asResult = array('is_pm'=>false, 'chan_name'=>$sChanSafeName);
preg_match('/(?P<from>\d+)'.self::PM_SEP.'(?P<to>\d+)/', $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(MySqlManager::COMP_TABLE), 'from'=>MySqlManager::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())
{
$asResult = array('success'=>self::ERROR);
$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(MySqlManager::USER_TABLE);
$sChanIdCol = MySqlManager::getId(MySqlManager::CHAN_TABLE);
$asData = array('safe_name'=>$sSafeChanName, MySqlManager::getText(MySqlManager::CHAN_TABLE)=>$sChanName);
$iChanId = $this->oMySql->insertUpdateRow(MySqlManager::CHAN_TABLE, $asData, array('safe_name'), false);
//Is user already connected to this chan
$bConnectedUser = $this->isUserConnected($iChanId);
$iConnId = $this->oMySql->insertUpdateRow(MySqlManager::CONN_TABLE, array($sUserIdCol=>$this->getUserId(), $sChanIdCol=>$iChanId), array($sUserIdCol, $sChanIdCol), false);
if($iConnId>0) $asResult['success'] = self::SUCCESS;
if($asResult['success']==self::SUCCESS)
{
//Return connected channels
$asResult['channels'] = $this->getChannels($this->getUserId());
//Add tab title (customized)
//TODO delete this shit and insert the channel type into channels DB table
foreach($asResult['channels'] as $iConnectedChanId=>$sConnectedChanName)
{
$asPm = $this->isPmChan($sConnectedChanName);
$asResult['channel_tab_names'][$iConnectedChanId] = $asPm['is_pm']?$this->getChatNickNames($asPm['from']==$this->getUserId()?$asPm['to']:$asPm['from']):$sConnectedChanName;
}
$asResult['current_chan_id'] = $iChanId;
//Communicate on user's connection
if(!$bConnectedUser)
{
$asMessages[$iChanId] = $this->oMySql->selectValue(MySqlManager::CHAN_TABLE, MySqlManager::getText(MySqlManager::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&eacute;':'#'.$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();
}
}
return self::jsonExport($asResult);
}
private function isUserConnected($iChanId=0, $iUserId=0)
{
$iUserId = $iUserId>0?$iUserId:$this->getUserId();
$sUserIdCol = MySqlManager::getId(MySqlManager::USER_TABLE);
$asInfo = array('select' => MySqlManager::getId(MySqlManager::CONN_TABLE),
'from' => MySqlManager::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(MySqlManager::CHAN_TABLE)] = $iChanId;
$asInfo['constOpe'][MySqlManager::getId(MySqlManager::CHAN_TABLE)] = '=';
}
//$this->oMySql->bTrace = true;
return (count($this->oMySql->selectRows($asInfo))>0);
}
public function pingChans()
{
$aiConstraints = array(MySqlManager::getId(MySqlManager::USER_TABLE)=>$this->getUserId());
$asUpdates = array('led'=>date(self::DATE_TIME_SQL_FORMAT));
$this->oMySql->updateRows(MySqlManager::CONN_TABLE, $aiConstraints, $asUpdates);
}
public function quitChan($sChanName)
{
$iChanId = $this->getChanId($sChanName);
$iConnId = $this->getConnId($iChanId);
if($iConnId>0)
{
$this->oMySql->deleteRow(MySqlManager::CONN_TABLE, $iConnId);
$asPm = $this->isPmChan($sChanName);
$this->addMessage('quitte '.($asPm['is_pm']?'le chan priv&eacute;':'#'.$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(MySqlManager::CHAN_TABLE);
$asChanNames = $this->oMySql->selectRows(array('select'=>array($sChanIdCol, MySqlManager::getText(MySqlManager::CHAN_TABLE)), 'from'=>MySqlManager::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(MySqlManager::CHAN_TABLE, true);
$sChanNameCol = MySqlManager::getText(MySqlManager::CHAN_TABLE);
$asInfo = array('select'=>array($sChanIdCol, $sChanNameCol),
'from'=> MySqlManager::CONN_TABLE,
'join'=> array(MySqlManager::CHAN_TABLE=>MySqlManager::getId(MySqlManager::CHAN_TABLE)),
'orderBy'=> array(MySqlManager::getId(MySqlManager::CONN_TABLE)=>'ASC'));
if($iUserId > 0) $asInfo['constraint'] = array(MySqlManager::getId(MySqlManager::USER_TABLE)=>$iUserId);
$asChannels = $this->oMySql->selectRows($asInfo, true, MySqlManager::getId(MySqlManager::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(MySqlManager::CHAN_TABLE);
$sSafeChanName = self::getChanSafeName($sChanName);
$iChanId = $this->oMySql->selectValue(MySqlManager::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(MySqlManager::USER_TABLE);
$sConnIdCol = MySqlManager::getId(MySqlManager::CONN_TABLE);
$sChanIdCol = MySqlManager::getId(MySqlManager::CHAN_TABLE);
if($iUserId==0) $iUserId = $this->getUserId();
$iConnId = $this->oMySql->selectValue(MySqlManager::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(substr($sMessage, 0, 1) == '/')
{
if(substr($sMessage, 0, 4) == '/me ')
{
$sType = self::MESSAGE_ACTION;
$sMessage = substr($sMessage, 3);
}
elseif(substr($sMessage, 0, 6) == '/slap ')
{
$sType = self::MESSAGE_ACTION;
$sMessage = ' fout une grosse tarte &agrave; '.substr($sMessage, 5);
}
elseif(substr($sMessage, 0, 4) == '/bs ')
{
$sType = self::MESSAGE_ACTION;
$sMessage = ' bitch-slaps '.substr($sMessage, 3);
}
elseif(substr($sMessage, 0, 6) == '/kick ')
{
$sType = self::MESSAGE_ACTION;
$sMessage = ' met un coup de pied au cul de '.substr($sMessage, 5);
}
elseif(substr($sMessage, 0, 6) == '/nick ' && strlen($sMessage)>6)
{
$sNewNick = $this->getNickNameFormat(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&eacute; son pseudo en '.$sNewNick;
}
elseif(substr($sMessage, 0, 9) == '/mission ' && strlen($sMessage)>9)
{
$sNewStatus = substr($sMessage, 9);
$sNewFormatStatus = $this->getDescriptionFormat($sNewStatus);
//changing Nickname
$this->setOptions(array(self::OPT_STATUS=>$sNewStatus));
//Message
$sType = self::MESSAGE_STATUS;
$sChanName = self::ALL_CHAN_TEXT;
$sMessage = 'est sur une nouvelle mission : '.$sNewFormatStatus;
}
elseif(substr($sMessage, 0, 6) == '/mail ' && strlen($sMessage)>6)
{
$sImagePattern = '/\/mail (?P<nickname>\w+) (?P<message>.*)/';
preg_match($sImagePattern, $sMessage, $asMatches);
//Looking for user Id
$asContraints = array( 'LOWER(`'.MySqlManager::getText(MySqlManager::OPT_TABLE).'`)'=>strtolower($asMatches['nickname']),
MySqlManager::getId(MySqlManager::OPTNAME_TABLE)=>self::OPT_NICKNAME);
$iUserIdTo = $this->oMySql->selectValue(MySqlManager::OPT_TABLE, MySqlManager::getId(MySqlManager::USER_TABLE), $asContraints);
//Handling mail
if($iUserIdTo>0)
{
if(trim($asMatches['message'])!='')
{
if($this->sendPM($iUserIdTo, $asMatches['message']))
{
$sMessage = 'a envoy&eacute; un mail &agrave; '.$asMatches['nickname'];
}
else
{
$sMessage = 'n\'a pas envoy&eacute; de mail &agrave; '.$asMatches['nickname'].' (raison inconnue, voir log)';
}
}
else
{
$sMessage = 'n\'a pas envoy&eacute; de mail &agrave; '.$asMatches['nickname'].' (message vide)';
}
}
else
{
$sMessage = 'n\'a pas envoy&eacute; de mail &agrave; '.$asMatches['nickname'].' (pseudo inconnu)';
}
$sType = self::MESSAGE_ACTION;
}
elseif(substr($sMessage, 0, 5) == '/mean')
{
$sPageContent = file_get_contents('http://www.randominsults.net/');
$sStartText = '<strong><i>';
$sEndText = '</i></strong>';
$iStartPos = strpos($sPageContent, $sStartText);
$iEndPos = strpos($sPageContent, $sEndText);
$sMessage = substr($sPageContent, $iStartPos + strlen($sStartText), $iEndPos - $iStartPos);
}
elseif(substr($sMessage, 0, 5) == '/like')
{
$sType = self::MESSAGE_ACTION;
$sMessage = ' plussoie';
}
elseif(substr($sMessage, 0, 4) == '/now')
{
$sType = self::MESSAGE_ACTION;
$asWeekDays = array('lundi', 'mardi', 'mercredi', 'jeudi', 'vendredi', 'samedi', 'dimanche');
$asMonths = array('janvier', 'f&eacute;vrier', 'mars', 'avril', 'mai', 'juin', 'juillet', 'ao&ucirc;t', 'septembre', 'octobre', 'novembre', 'd&eacute;cembre');
$sMessage = ' a demand&eacute; 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' || substr($sMessage, 0, 5) == '/list' || $sMessage == '/chans')
{
//Always at least one channel open (the one the message is sent from)
$sMessage = ' a demand&eacute; les chans disponibles. Pour sa gouverne, les chans ayant des membres connect&eacute;s sont #'.MySqlManager::implodeAll($this->getActiveChannels(), ' (', ', #', '', ')');
$sType = self::MESSAGE_ACTION;
}
elseif(substr($sMessage, 0, 5) == '/img ' && strlen($sMessage)>5)
{
$sUrl = trim(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(substr($sMessage, 0, 6) == '/9gag ' && strlen($sMessage)>6)
{
$sMessage = $this->getJsonMessage($this->get9gagPost(trim(substr($sMessage, 6))));
$sType = self::MESSAGE_9GAG;
}
elseif(substr($sMessage, 0, 7) == '/reboot' && $this->getUserClearance()==self::CLEARANCE_ADMIN)
{
$sMessage = 'L\'administrateur a demand&eacute; un reboot. Votre page va se rafraichir automatiquement dans '.self::REBOOT_DELAY.' secondes.';
$sType = self::MESSAGE_REBOOT;
}
}
elseif(substr($sMessage, 0, 1) == '@' && 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 = 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);
}
private function sendPM($iUserIdTo, $sMessage)
{
$bSuccess = false;
$asUserFrom = $this->getUserInfo($this->getUserId());
$asUserTo = $this->getUserInfo($iUserIdTo);
$sFrom = $asUserFrom['name'].' <www-data@lutran.fr>';
$sTo = $asUserTo['name'].' <'.$asUserTo['email'].'>';
$sMessage .= "\n\n\n".'<i>Ne r&eacute;pondez pas &agrave; ce mail. Connectez-vous sur <a href="http://databap.lutran.fr/chat">Databap</a>.</i>';
$sResult = ToolBox::sendMail($sFrom, $sTo, 'Databap <www-data@lutran.fr>', 'Databap PM', $sMessage);
$bSuccess = ($sResult=='');
if(!$bSuccess) $this->addError($sResult);
return $bSuccess;
}
private function addMessage($sMessage, $sType, $iChanId)
{
$bResult = false;
if($iChanId>0)
{
$asInsert = array( MySqlManager::getId(MySqlManager::USER_TABLE) => $this->getUserId(),
'nickname' => $this->getChatNickNames($this->getUserId()),
MySqlManager::getId(MySqlManager::CHAN_TABLE) => $iChanId,
MySqlManager::getText(MySqlManager::MSG_TABLE) => $sMessage,
'type' => $sType,
'date' => 'CURDATE()');
$bResult = $this->oMySql->insertRow(MySqlManager::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(MySqlManager::CHAN_TABLE, true);
$sChanTextCol = MySqlManager::getText(MySqlManager::CHAN_TABLE);
$sMsgIdCol = MySqlManager::getId(MySqlManager::MSG_TABLE, true);
$sMsgTextCol = MySqlManager::getText(MySqlManager::MSG_TABLE);
$sMsgTableLed = MySqlManager::getFullColumnName(MySqlManager::MSG_TABLE, 'led');
$sMsgTableChanIdCol = MySqlManager::getFullColumnName(MySqlManager::MSG_TABLE, MySqlManager::getId(MySqlManager::CHAN_TABLE));
$sUserIdCol = MySqlManager::getId(MySqlManager::USER_TABLE, true);
$sMsgTableUserIdCol = MySqlManager::getFullColumnName(MySqlManager::MSG_TABLE, MySqlManager::getId(MySqlManager::USER_TABLE));
$sUserTableUserIdCol = MySqlManager::getId(MySqlManager::USER_TABLE, true);
$sConnTableUserIdCol = MySqlManager::getFullColumnName(MySqlManager::CONN_TABLE, MySqlManager::getId(MySqlManager::USER_TABLE));
$sConnTableChanIdCol = MySqlManager::getFullColumnName(MySqlManager::CONN_TABLE, MySqlManager::getId(MySqlManager::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' => MySqlManager::CONN_TABLE,
'joinOn' => array( MySqlManager::MSG_TABLE =>array($sMsgTableChanIdCol, '=', $sConnTableChanIdCol),
MySqlManager::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'] = MySqlManager::MSG_TABLE;
$asInfo['joinOn'] = array(MySqlManager::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 = strlen(self::JSON_PREFIX);
$asMessages = array('messages'=>array(), 'last_message_id'=>0);
foreach($asSqlMessages as $iMessageId=>$asMessageInfo)
{
$iChanId = $asMessageInfo[MySqlManager::getId(MySqlManager::CHAN_TABLE)];
$iUserId = $asMessageInfo[MySqlManager::getId(MySqlManager::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
if($sMessageType==self::MESSAGE_ADD_CODE || $sMessageType==self::MESSAGE_EDIT_CODE)
{
$asCode = $this->getCodeInfo($asMessages['messages'][$iMessageId]['message']);
$asMessages['messages'][$iMessageId]['description'] = $asCode['description'];
}
elseif($sMessageType==self::MESSAGE_ADD_PROC || $sMessageType==self::MESSAGE_EDIT_PROC)
{
$asProc = $this->getProcInfo($asMessages['messages'][$iMessageId]['message']);
$asMessages['messages'][$iMessageId]['description'] = $asProc['description'];
}
elseif($sMessageType==self::MESSAGE_ARTICLE)
{
$asTransferredInfo = $this->getArticleInfo($asMessages['messages'][$iMessageId]['message']);
$asMessages['messages'][$iMessageId]['message'] = $this->getJsonMessage($asTransferredInfo);
}
//Switch Chan ID with name for the user to join
if($sMessageType==self::MESSAGE_INVITE)
{
$asMessages['messages'][$iMessageId]['id_chan'] = $this->oMySql->selectValue(MySqlManager::CHAN_TABLE, 'safe_name', $iChanId);
}
//Json message
if(substr($asMessages['messages'][$iMessageId]['message'], 0, $iPrefixLen) == self::JSON_PREFIX)
{
$asMessages['messages'][$iMessageId]['message'] = json_decode(substr($asMessages['messages'][$iMessageId]['message'], $iPrefixLen));
}
else //Normal message
{
//Dynamic web link
$asPatterns = array('`((?:https?|ftp)://\S+[[:alnum:]]/?)`si', '`((?<!//)(www\.\S+[[:alnum:]]/?))`si');
$asLinks = array('<a href="$1" target="_blank">$1</a> ', '<a href="http://$1" target="_blank">$1</a>');
$asMessages['messages'][$iMessageId]['message'] = preg_replace($asPatterns, $asLinks, $asMessages['messages'][$iMessageId]['message']);
//Dynamic chan link
$asPatterns = '/(^|\s)#(\w*[^\s]+\w*)/';
$asLinks = '\1<span class="chan_link clickable">#<span class="chan_text">\2</span></span>';
$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);
}
private function getConnectedChans($iuserId=0)
{
$iuserId = $iuserId>0?$iuserId:$this->getUserId();
$sUserIdCol = MySqlManager::getId(MySqlManager::USER_TABLE);
$asInfo = array('select' => array(MySqlManager::getId(MySqlManager::CHAN_TABLE, true), MySqlManager::getText(MySqlManager::CHAN_TABLE)),
'from' => MySqlManager::CONN_TABLE,
'join' => array(MySqlManager::CHAN_TABLE=>MySqlManager::getId(MySqlManager::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(MySqlManager::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(MySqlManager::USER_TABLE);
$asLastMsg = $this->oMySql->selectRows(array('select'=>array($iUserIdCol, 'MAX(led)'), 'from'=>MySqlManager::MSG_TABLE), true, $iUserIdCol);
$asConnectedUsers = array();
foreach($asUserChannels as $asUser)
{
$sChanId = $asUser[MySqlManager::getId(MySqlManager::CHAN_TABLE)];
$iUserId = $asUser[$iUserIdCol];
$asConnectedUsers[$sChanId][$iUserId]['id_user'] = $iUserId;
$asConnectedUsers[$sChanId][$iUserId]['name'] = self::getNameFormat($asUser['first_name'], $asUser['last_name']);
$asConnectedUsers[$sChanId][$iUserId]['company'] = self::getCompanyFormat($asUser['company']);
$asConnectedUsers[$sChanId][$iUserId]['status'] = $asUser['status'];
$asConnectedUsers[$sChanId][$iUserId]['logo'] = $asUser['logo'];
$asConnectedUsers[$sChanId][$iUserId]['nickname'] = self::getNickNameFormat($asUser['nickname']==''?$asUser['first_name']:$asUser['nickname']);
$asConnectedUsers[$sChanId][$iUserId]['last_activity'] = array_key_exists($iUserId, $asLastMsg)?self::getDateFormat($asLastMsg[$iUserId], self::TIME_FORMAT):'';
$asConnectedUsers[$sChanId][$iUserId]['ping'] = self::getDateFormat($asUser['led'], self::TIME_FORMAT);
$asConnectedUsers[$sChanId][$iUserId]['afk'] = $asUser['afk'];
}
return $bJson?$this->jsonExport($asConnectedUsers):$asConnectedUsers;
}
private function getChatNickNames($iUserId=0)
{
$sUserIdCol = MySqlManager::getId(MySqlManager::USER_TABLE);
$sNicknameCol = MySqlManager::getText(MySqlManager::OPT_TABLE);
$asConstraints = array(MySqlManager::getId(MySqlManager::OPTNAME_TABLE)=>self::OPT_NICKNAME);
if($iUserId>0)
{
$asConstraints[MySqlManager::getId(MySqlManager::USER_TABLE)] = $iUserId;
$oResult = $this->oMySql->selectValue(MySqlManager::OPT_TABLE, $sNicknameCol, $asConstraints);
}
else
{
$asInfo = array('select'=>array($sUserIdCol, $sNicknameCol),
'from'=>MySqlManager::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(MySqlManager::CODE_TABLE, 'refer_id', $iCodeId);
break;
case 'last':
$iRefId = $this->oMySql->selectValue(MySqlManager::CODE_TABLE, 'refer_id', $iCodeId);
$iCodeId = $this->oMySql->selectValue(MySqlManager::CODE_TABLE, 'MAX(id_code)', array('refer_id'=>$iRefId));
break;
}
}
private function getIdCodeFromPhrase($sPhrase)
{
$iCodeId = $this->oMySql->selectValue(MySqlManager::URL_TABLE, MySqlManager::getId(MySqlManager::CODE_TABLE), array('phrase'=>$sPhrase));
$this->switchCodeId($iCodeId, 'last');
return $iCodeId;
}
private function getPhraseFromIdCode($iCodeId)
{
$this->switchCodeId($iCodeId, 'first');
return $this->oMySql->selectValue(MySqlManager::URL_TABLE, 'phrase', array('id_code'=>$iCodeId));
}
private function getCodeVersions($iRefCodeId)
{
$asInfo = array('select'=>array(MySqlManager::getId(MySqlManager::CODE_TABLE)),
'from'=>MySqlManager::CODE_TABLE,
'constraint'=>array('refer_id'=>$iRefCodeId),
'orderBy'=>array('id_code'=>'asc'));
$asCodeIds = $this->oMySql->selectRows($asInfo);
$asCodeVersions = array();
foreach($asCodeIds as $iCodeId)
{
$asCodeVersions[] = $this->getCodeInfo($iCodeId);
}
return $asCodeVersions;
}
public function getColoredCode($oCode)
{
$asCode = $this->getCodeInfo($oCode, '', true);
//code
$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)
{
$asCode = $this->getCodeInfo($oCode, '', true);
$asUser = $this->getUserInfo($asCode['id_user']);
$sEncodedCode = $this->jsonConvert($asCode['code']);
$sEncodedDesc = $this->jsonConvert($asCode['description']);
return '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<meta name="author" content="'.$asUser['name'].' ('.$asUser['company'].')" />
<link rel="shortcut icon" href="images/favicon_gc3.ico" />
<title>Databap &bull;</title>
</head>
<body>
<pre id="content"></pre>
<script>
document.getElementById("content").textContent = '.$sEncodedCode.';
document.title = document.title+" "+'.$sEncodedDesc.';
</script>
</body>
</html>';
}
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 getPrintCode($oCode)
{
return $this->getRawCode($oCode).'<script>window.print();</script>';
}
public function getItemList()
{
$sIdCodeCol = MySqlManager::getId(MySqlManager::CODE_TABLE);
$sIdProcCol = MySqlManager::getId(MySqlManager::PROC_TABLE);
$sIdArtCol = MySqlManager::getId(MySqlManager::ART_TABLE);
$sIdCodeColFull = MySqlManager::getId(MySqlManager::CODE_TABLE, true);
$sIdUserCol = MySqlManager::getId(MySqlManager::USER_TABLE);
$sIdUserColFull = MySqlManager::getId(MySqlManager::USER_TABLE, true);
$sLedColFull = MySqlManager::getFullColumnName(MySqlManager::CODE_TABLE, 'led') ;
//Get code Ids
$asInfo = array('select'=>array("MAX($sIdCodeCol) AS id_item"),
'from'=>MySqlManager::CODE_TABLE,
'groupBy'=>array('refer_id'),
'orderBy'=>array('id_item'=>'desc'));
$asCodeIds = $this->oMySql->selectRows($asInfo);
//get Proc Ids
$asInfo = array('select'=>array("MAX($sIdProcCol) AS id_item"),
'from'=>MySqlManager::PROC_TABLE,
'constraint'=>array('refer_id'=>"0"),
'orderBy'=>array('id_item'=>'desc'));
$asProcIds = $this->oMySql->selectRows($asInfo);
//get Article Ids
$asInfo = array('select'=>array($sIdArtCol." AS id_item"),
'from'=>MySqlManager::ART_TABLE,
'orderBy'=>array('id_item'=>'desc'));
$asArtIds = $this->oMySql->selectRows($asInfo);
$asItemIds = array(Databap::CODE_TYPE=>$asCodeIds, Databap::PROC_TYPE=>$asProcIds, Databap::ART_TYPE=>$asArtIds);
//Build code info structure
$asUsers = $asCode = $asItemList = array();
foreach($asItemIds as $sType=>$asTypedItemIds)
{
switch($sType)
{
case Databap::CODE_TYPE:
$sFuncType = 'Code';
break;
case Databap::PROC_TYPE:
$sFuncType = 'Proc';
break;
case Databap::ART_TYPE:
$sFuncType = 'Article';
break;
}
foreach($asTypedItemIds as $iItemId)
{
//null value returned from query (MAX(...))
if($iItemId>0)
{
$asItem = call_user_func(array($this, 'get'.$sFuncType.'Info'), $iItemId);
if(array_key_exists($sIdUserCol, $asItem))
{
$iUserId = $asItem[$sIdUserCol];
if(!array_key_exists($iUserId, $asUsers))
{
$asUsers[$iUserId] = $this->getUserInfo($iUserId);
}
$asItemList[$sType][$iItemId] = array_merge($asUsers[$iUserId], $asItem);
}
else $asItemList[$sType][$iItemId] = $asItem;
//$asCodeList[$iItemId]['phrase'] = $this->getPhraseFromIdCode($iCodeId);
}
}
}
return $this->jsonExport($asItemList);
}
public function getCodeBlock()
{
$oMask = new Mask();
$oMask->initFile('code_block');
return $oMask->getMask();
}
public static function checkNoPassResetAction($sAction)
{
return in_array($sAction, array('messages', 'upload_image', 'user_info', 'rss'));
}
public function logMeIn($sName, $sCompany, $sToken, $sAction)
{
$iUserId = 0;
$bResetPass = true;
$sUserTableId = MySqlManager::getId(MySqlManager::USER_TABLE);
$sCompanyTableId = MySqlManager::getId(MySqlManager::COMP_TABLE);
$sCompanyTableText = MySqlManager::getText(MySqlManager::COMP_TABLE);
//login using form
if($sName!='' && $sCompany!='')
{
$asNames = explode(' ', strtolower($sName));
$sCompany = strtolower($sCompany);
//Get Company's Id
$iCompanyId = $this->oMySql->selectValue(MySqlManager::COMP_TABLE, $sCompanyTableId, array($sCompanyTableText=>$sCompany));
$asConsts = array('first_name'=>$asNames[0], 'last_name'=>$asNames[1], $sCompanyTableId=>$iCompanyId);
$iUserId = $this->oMySql->selectValue(MySqlManager::USER_TABLE, $sUserTableId, $asConsts);
if(!$iUserId)
{
$asInvConsts = array('first_name'=>$asNames[1], 'last_name'=>$asNames[0], $sCompanyTableId=>$iCompanyId);
$iUserId = $this->oMySql->selectValue(MySqlManager::USER_TABLE, $sUserTableId, $asInvConsts);
}
}
//auto login by cookie
elseif(isset($_COOKIE[self::USER_COOKIE_ID]))
{
$asConstraints = array( $sUserTableId=>$_COOKIE[self::USER_COOKIE_ID],
'pass'=>$_COOKIE[self::USER_COOKIE_PASS]);
$asUserInfo = $this->oMySql->selectRow(MySqlManager::USER_TABLE, $asConstraints, array($sUserTableId, 'led'));
$iUserId = $asUserInfo[$sUserTableId];
//Check pass reset necessity
$bResetPass = (substr($asUserInfo['led'], 0, 10) != date(Databap::DATE_SQL_FORMAT));
}
//Login using Token (limited access)
elseif($sAction==self::EXT_ACCESS && $sToken!='')
{
$iUserId = $this->checkToken($sToken);
$bResetPass = false;
}
if($iUserId>0)
{
$this->setUserId($iUserId);
if(!self::checkNoPassResetAction($sAction) && $bResetPass)
{
$this->resetPassword();
}
}
return ($this->getUserId()>0);
}
public function checkToken($sKey)
{
$iUserId = strstr($sKey, '_', true);
$sToken = substr($sKey, strlen($iUserId)+1);
return (strlen($sToken)==self::TOKEN_LENGTH && $this->generateToken($iUserId)==$sToken)?$iUserId:0;
}
public function resetNecessary($iUserId)
{
$sLed = substr($this->oMySql->selectValue(MySqlManager::USER_TABLE, 'led', $iUserId), 0, 10);
return $sLed != date(Databap::DATE_SQL_FORMAT);
}
public function resetPassword()
{
$iUserId = $this->getUserId();
$sNewPass = self::getCookiePass();
$iTimeLimit = time()+60*60*24*self::COOKIE_LIFETIME;
$this->oMySql->updateRow(MySqlManager::USER_TABLE, $iUserId, array('pass'=>$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 redirectArticle($iArtId)
{
$asArtInfo = $this->getArticleInfo($iArtId);
header('Location:'.$asArtInfo['link_art']);
}
public function disconnectChat()
{
//$this->getConnectedChans();
$sTime = $this->oMySql->selectRows(array('select'=>'DATE_SUB(NOW(), INTERVAL '.self::KEEP_ALIVE.' SECOND)'));
$this->oMySql->updateRows(MySqlManager::CONN_TABLE, array(MySqlManager::getId(MySqlManager::USER_TABLE)=>$this->getUserId()), array('led'=>$sTime));
$this->addMessage('se d&eacute;connecte', self::MESSAGE_CONN, self::ALL_CHAN_ID);
}
public function checkValue($sTableName, $asConstraints)
{
return $this->oMySql->selectValue($sTableName, 'COUNT(1)', $asConstraints);
}
private static function getCookiePass()
{
return self::encryptPassword( $_SERVER['HTTP_USER_AGENT'].
$_SERVER['REMOTE_ADDR'].
$_SERVER['REQUEST_TIME'].
strstr(microtime(), ' ', true).
$_SERVER['SERVER_SIGNATURE'].
$_SERVER['SERVER_ADMIN']);
}
private static function encryptPassword($sPass)
{
$sRandomText = 'F_RA-1H"2{bvj)5f?0sd3r#fP,K]U|w}hGiN@(sZ.sDe!7*x/:Mq+&';
for($iIndex=0; $iIndex < strlen($sPass); $iIndex++)
{
$sPass[$iIndex] = $sRandomText[$iIndex%strlen($sRandomText)] ^ $sPass[$iIndex];
}
return md5($sPass);
}
public static function getChanSafeName($sChanName)
{
$sChanSafeName = preg_replace('/[^a-z0-9]/', '_', 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 $iCodeId=>$asCodeInfo)
{
//phrase
$sPhrase = $this->getPhraseFromIdCode($asCodeInfo['id_code']);
if($sPhrase !== false)
{
$asCodeInfo['phrase'] = $sPhrase;
}
$asCompleteResults[$iCodeId] = $asCodeInfo;
}
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.' '.$sLastName), ' -');;
}
public static function getNickNameFormat($sNickName)
{
$sNickName = ToolBox::capitalizeWords(trim($sNickName), ' -');
return str_replace(' ', '_', $sNickName);
}
public static function getCompanyFormat($sCompany)
{
return ucwords($sCompany);
}
public static function getDescriptionFormat($sDescription)
{
return ucfirst($sDescription);
}
public static function jsonExport($asData, $bConvert=false)
{
header('Content-type: application/json');
if($bConvert)
{
$asData = MySqlManager::cleanData($asData, 'utf8_encode');
}
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 = strtolower($str[strlen($str)-1]);
switch($last) {
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
return $val;
}
}
/**
* TODO
* Code Manager
* @author franzz
*/
class Code extends PhpObject
{
//Objects
private $oMySql;
//Database tables and columns
private $sProcTable;
function __construct($oMySql)
{
parent::__construct();
$this->oMySql = $oMySql;
}
}
/**
* Procedure Manager
* @author franzz
*/
class Procedure extends PhpObject
{
//Constants
const THUMB_MAX_SIZE = 100;
const IMAGE_FOLDER = 'screenshot/';
const IMAGE_FOLDER_TMP = 'screenshot/tmp/';
const IMAGE_FOLDER_THUMB = 'screenshot/thumbnails/';
//Objects
private $oMySql;
//Procedure Elements
private $iProcId;
private $iUserId;
private $sTitle;
private $sDescription;
private $dLed;
private $asSteps; // [id_step]=>text
private $asImages; // [id_step][id_image]=>array('name'=>file name, 'desc'=> description)
function __construct($oMySql)
{
parent::__construct();
$this->oMySql = $oMySql;
$this->iPrevProcId = 0;
$this->setProcedureId(0);
$this->sTitle = '';
$this->sDescription = '';
$this->dLed = '';
$this->asSteps = array();
$this->asImages = array();
}
public function getProcedureId()
{
return $this->iProcId;
}
public function getProcedureLed()
{
return $this->dLed;
}
public function setProcedureId($iProcId)
{
$this->iProcId = $iProcId;
}
public function inputForm($asPost)
{
//User
$this->iUserId = $asPost['id_user'];
//Titles
$this->sTitle = isset($asPost['title'])?$asPost['title']:'';
$this->sDescription = isset($asPost['description'])?$asPost['description']:'';
//Steps
$sStepPattern = '/c(?P<step_id>\d+)_step_text/';
$sImagePattern = '/c(?P<step_id>\d+)_(?P<image_id>\d+)_image_(?P<image_info>\w+)/';
foreach($asPost as $sFormId=>$sValue)
{
//Step Text
preg_match($sStepPattern, $sFormId, $asMatches);
if(isset($asMatches['step_id']))
{
$this->asSteps[$asMatches['step_id']] = $sValue;
}
else
{
preg_match($sImagePattern, $sFormId, $asMatches);
if
(
isset($asMatches['step_id'], $asMatches['image_id'], $asMatches['image_info']) &&
($asMatches['image_info'] == 'name' || $asMatches['image_info']== 'desc')
)
{
$this->asImages[$asMatches['step_id']][$asMatches['image_id']][$asMatches['image_info']] = $sValue;
}
}
}
}
private function isImageSaved($sFileName, $bInTemp=false)
{
$sPath = $bInTemp?self::IMAGE_FOLDER_TMP:self::IMAGE_FOLDER;
return file_exists($sPath.$sFileName);
}
public function checkIntegrity()
{
$asErrors = array();
//Check title
if($this->sTitle=='') $asErrors['title'] = 'Un titre est n&eacute;cessaire';
//Check steps
if(count($this->asSteps)==0)
{
$asErrors['step'] = 'Au moins une &eacute;tape est n&eacute;cessaire';
}
else
{
foreach($this->asSteps as $iStepId=>$sText)
{
if($sText=='')
{
$asErrors['step_'.$iStepId] = 'Une &eacute;tape ne poss&egrave;de pas de texte';
}
}
}
//Check images
foreach($this->asImages as $iStepId=>$asImages)
{
foreach($asImages as $iImageId=>$asFileInfo)
{
//file exists in temp or already stored
if(!$this->isImageSaved($asFileInfo['name']) && !$this->isImageSaved($asFileInfo['name'], true))
{
$asErrors['image_'.$iStepId.'_'.$iImageId] = 'Une image n\'a pas &eacute;t&eacute; t&eacute;l&eacute;charg&eacute;e';
}
if($asFileInfo['desc']=='')
{
$asErrors['image_'.$iStepId.'_'.$iImageId] = 'Une image n\'a pas de nom (description)';
}
}
}
return $asErrors;
}
public function saveProcedure($iPrevProcId)
{
//Add new procedure
$asData = array('title'=>$this->sTitle, 'description'=>$this->sDescription, MySqlManager::getId(MySqlManager::USER_TABLE)=>$this->iUserId);
$iDbProcId = $this->oMySql->insertRow(MySqlManager::PROC_TABLE, $asData);
//Add new steps
$asStepData = $asImgData = array(MySqlManager::getId(MySqlManager::PROC_TABLE)=>$iDbProcId);
foreach($this->asSteps as $iStepId=>$sStepDesc)
{
$asStepData['description'] = $sStepDesc;
$iDbStepId = $this->oMySql->insertRow(MySqlManager::STEP_TABLE, $asStepData);
//Add new images
$asImgData[MySqlManager::getId(MySqlManager::STEP_TABLE)] = $iDbStepId;
foreach($this->asImages[$iStepId] as $asImageInfo)
{
$asImgData['description'] = $asImageInfo['desc'];
$asImgData['file_name'] = $asImageInfo['name'];
$iDbImageId = $this->oMySql->insertRow(MySqlManager::IMG_TABLE, $asImgData);
$this->saveImage($asImgData['file_name']);
}
}
//Add this procedure to the group
$bCreation = ($iPrevProcId==0);
//$this->oMySql->deleteRow(MySqlManager::PROC_TABLE, $this->iPrevProcId);
//$this->oMySql->updateRow(MySqlManager::PROC_TABLE, $iPrevProcId, array('refer_id'=>$iDbProcId));
$iReferId = $bCreation?$iDbProcId:$this->oMySql->selectValue(MySqlManager::PROC_TABLE, 'refer_id', $iPrevProcId);
$this->oMySql->updateRow(MySqlManager::PROC_TABLE, $iDbProcId, array('refer_id'=>$iReferId));
//Update new Procedure Id
//$this->setProcedureId($iDbProcId);
//Reload Procedure
$this->loadProcedure($iDbProcId);
//return creation or edition
return $bCreation;
}
private function saveImage($sFileName)
{
if(!$this->isImageSaved($sFileName))
{
$sTempFilePath = self::IMAGE_FOLDER_TMP.$sFileName;
$sFilePath = self::IMAGE_FOLDER.$sFileName;
//Real Size Image
if(!rename($sTempFilePath, $sFilePath))
{
$this->addError('Unmoveable file : '.$sTempFilePath);
}
//Thumbnail picture
$asResult = ToolBox::createThumbnail($sFilePath, self::THUMB_MAX_SIZE, self::THUMB_MAX_SIZE, self::IMAGE_FOLDER_THUMB);
if($asResult['error']!='') $this->addError('Unable to create thumbnail : '.$asResult['out']. '('.$asResult['error'].')');
}
}
public function loadProcedure($iProcId)
{
//Column names
$sProcIdCol = MySqlManager::getId(MySqlManager::PROC_TABLE);
$sStepIdCol = MySqlManager::getId(MySqlManager::STEP_TABLE);
$sImageIdCol = MySqlManager::getId(MySqlManager::IMG_TABLE);
//Get last id available
$this->setProcedureId($iProcId);
$this->refreshProcId();
$asInfo = array('from'=>MySqlManager::PROC_TABLE, 'constraint'=>array($sProcIdCol=>$this->getProcedureId()));
//Load procedure info
$asResult = $this->oMySql->selectRow(MySqlManager::PROC_TABLE, $asInfo['constraint']);
$this->sTitle = $asResult['title'];
$this->sDescription = $asResult['description'];
$this->iUserId = $asResult[MySqlManager::getId(MySqlManager::USER_TABLE)];
$this->dLed = $asResult['led'];
//Load steps info
$asInfo['from'] = MySqlManager::STEP_TABLE;
$this->asSteps = $this->oMySql->selectRows($asInfo, true, $sStepIdCol);
//Load images info
$asInfo['from'] = MySqlManager::IMG_TABLE;
foreach($this->oMySql->selectRows($asInfo) as $asRow)
{
$this->asImages[$asRow[$sStepIdCol]][$asRow[$sImageIdCol]]['name'] = $asRow['file_name'];
$this->asImages[$asRow[$sStepIdCol]][$asRow[$sImageIdCol]]['desc'] = $asRow['description'];
}
}
public function getProcedure()
{
// [id_step]=>text
// [id_step][id_image]=>array('name'=>file name, 'desc'=> description)
/*
$asSteps = $asImages = array();
$iLocalStepId = 1;
foreach($this->asSteps as $iStepId=>$sStepDesc)
{
$asSteps[$iLocalStepId] = $sStepDesc;
if(array_key_exists($iStepId, $this->asImages))
{
$asImages[] =
}
$iLocalStepId++;
}*/
return array( 'proc_id'=>$this->iProcId,
'id_user'=>$this->iUserId,
'title'=>Databap::getDescriptionFormat($this->sTitle),
'description'=>Databap::getDescriptionFormat($this->sDescription),
'led'=>Databap::getDateFormat($this->dLed),
'steps'=>$this->asSteps,
'images'=>$this->asImages);
}
private function refreshProcId()
{
/*
$iReferId = $this->getProcedureId();
do
{
$iProcId = $iReferId;
$iReferId = $this->oMySql->selectValue(MySqlManager::PROC_TABLE, 'refer_id', $iProcId);
}
while($iReferId!=0);
$this->setProcedureId($iProcId);
*/
$iReferId = $this->oMySql->selectValue(MySqlManager::PROC_TABLE, 'refer_id', $this->getProcedureId());
$sSelect = "MAX(".MySqlManager::getId(MySqlManager::PROC_TABLE).")";
$iProcId = $this->oMySql->selectValue(MySqlManager::PROC_TABLE, $sSelect, array('refer_id'=>$iReferId));
$this->setProcedureId($iProcId);
}
}
/* if feeling the need of creating a tables for code lines :
codes :
ALTER TABLE codes ADD line_low int(10) AFTER code;
ALTER TABLE codes ADD line_high int(10) AFTER line_low;
lines :
id_line
id_code
line
*/
class SearchEngine extends PhpObject
{
//Objects
private $oMySql;
//variables
private $asWords;
private $iLevelMax;
private $asItemRanks;
private $asItemInfos;
private $asCodeInfos;
private $asUserInfos;
//Constants
const RESULT_A_PAGE = 20;
const KEYWORDS_SEPARATOR = ' ';
function __construct($oMySql)
{
parent::__construct();
$this->oMySql = $oMySql;
$this->asWords = $this->setWords('');
$this->asItemRanks = array();
$this->asItemInfos = array();
$this->asCodeInfos = array();
$this->asUserInfos = array();
}
public function buildIndex($iItemId, $sType)
{
//Build keywords
$sWords = '';
switch($sType)
{
case Databap::CODE_TYPE:
$asItemData = $this->oMySql->selectRow(MySqlManager::CODE_TABLE, $iItemId);
$sWords = $asItemData[MySqlManager::getText(MySqlManager::CODE_TABLE)].self::KEYWORDS_SEPARATOR.$asItemData['description'];
break;
case Databap::PROC_TYPE:
$asItemData = $this->oMySql->selectRow(MySqlManager::PROC_TABLE, $iItemId);
$asItemStepsData = $this->oMySql->selectRows(array('select'=>'description', 'from'=>MySqlManager::STEP_TABLE, 'constraint'=>array('id_procedure'=>$iItemId)));
$sWords = $asItemData['description'].self::KEYWORDS_SEPARATOR.
$asItemData['title'].self::KEYWORDS_SEPARATOR.
implode(self::KEYWORDS_SEPARATOR, $asItemStepsData);
break;
case Databap::ART_TYPE:
$asItemData = $this->oMySql->selectRow(MySqlManager::ART_TABLE, $iItemId);
$sWords = $asItemData['first_name'].self::KEYWORDS_SEPARATOR.
$asItemData['last_name'].self::KEYWORDS_SEPARATOR.
$asItemData['title'];
break;
default:
$this->addError('function'.__FUNCTION__.'(): Incorrect type "'.$sType.'"');
break;
}
$sWords = strtolower(str_replace("\n", self::KEYWORDS_SEPARATOR, $sWords));
$sWords = preg_replace('/(\W+)/', self::KEYWORDS_SEPARATOR, $sWords);
//Add / Modify search database
$asData = array('id_item'=>$iItemId, 'type'=>$sType, 'refer_id'=>$asItemData['refer_id'], 'keywords'=>$sWords);
$this->oMySql->insertUpdateRow(MySqlManager::SEARCH_TABLE, $asData, array('id_item', 'type'));
}
public function setWords($sSearchWords)
{
$this->asWords = $this->getParsedWords($sSearchWords);
$this->iLevelMax = count($this->asWords);
$this->setResults();
}
private function setResults()
{
if($this->iLevelMax>0)
{
//set Results and Ranking
$aiLevels = range(1, $this->iLevelMax);
arsort($aiLevels);
foreach($aiLevels as $iLevel)
{
//all possibilies at level $iLevel
$iIndex = 0;
while(($iIndex + $iLevel) <= $this->iLevelMax)
{
//building query
$asSequence = array_slice($this->asWords, $iIndex, $iLevel);
$this->oMySql->cleanSql($asSequence);
//$sRegExp = implode('(.{0,2})', $asSequence);
$sRegExp = implode(' ?', $asSequence);
//TODO replace with selectRow()
$sQuery = "SELECT id_search, id_item, type FROM searchs WHERE keywords REGEXP '{$sRegExp}'";
//search sequence
$asRows = $this->oMySql->getArrayQuery($sQuery, true);
foreach($asRows as $asRow)
{
$iItemId = $asRow['id_item'];
unset($asRow['id_item']);
//TODO switch case type
switch($asRow['type'])
{
case Databap::CODE_TYPE:
$this->setCodeInfo($iItemId);
$this->setUserInfo($this->getCodeInfo($iItemId, MySqlManager::getId(MySqlManager::USER_TABLE)));
break;
}
$this->asItemInfos[$iItemId] = $asRow;
$this->incItemRank($iItemId, $iLevel);
}
$iIndex++;
}
}
}
}
public function getResults()
{
$asResult = array();
//Mixing info
arsort($this->asItemRanks);
foreach($this->asItemRanks as $iItemId=>$iRank)
{
switch($this->asItemInfos[$iItemId]['type'])
{
case Databap::CODE_TYPE:
//$asRow['code'] = $this->formatCode($asRow['code'], $sRegExp);
break;
case Databap::PROC_TYPE:
break;
default:
continue;
}
//code
$iUserId = $this->getCodeInfo($iItemId, MySqlManager::getId(MySqlManager::USER_TABLE));
/* TODO
$sCodeLines = implode("\n...\n", $this->getCodeInfo($iItemId, 'code'));
$oCode = new Reader($sCodeLines);
$sCodeLines = $oCode->getColoredCode();
*/
$sCodeLines = '';
$asResult[$iItemId] = array('id_code'=>$iItemId,
'code'=>$sCodeLines,
'description'=>$this->getCodeInfo($iItemId, 'description'),
'name'=>Databap::getNameFormat($this->getUserInfo($iUserId, 'first_name'), $this->getUserInfo($iUserId, 'last_name')),
'company'=>Databap::getCompanyFormat($this->getUserInfo($iUserId, 'company')),
'led'=>Databap::getDateFormat($this->getCodeInfo($iItemId, 'led')));
}
return $asResult;
}
private function getCodeInfo($iCodeId, $sInfoName)
{
return $this->asCodeInfos[$iCodeId][$sInfoName];
}
private function getUserInfo($iUserId, $sInfoName)
{
return $this->asUserInfos[$iUserId][$sInfoName];
}
private function setCodeInfo($iCodeId)
{
if(!array_key_exists($iCodeId, $this->asCodeInfos))
{
$this->asCodeInfos[$iCodeId] = $this->oMySql->selectRow
(
MySqlManager::CODE_TABLE,
$iCodeId,
array(MySqlManager::getId(MySqlManager::USER_TABLE), 'description', 'led')
);
}
/*
else
{
$this->asCodeInfos[$iCodeId]['code'] = array_unique(array_merge($this->asCodeInfos[$iCodeId]['code'], $asInfos['code']));
}
*/
}
private function setUserInfo($iUserId)
{
if(!array_key_exists($iUserId, $this->asUserInfos))
{
$sCompanyIdCol = MySqlManager::getId(MySqlManager::COMP_TABLE);
$this->asUserInfos[$iUserId] = $this->oMySql->selectRow
(
MySqlManager::USER_TABLE,
$iUserId,
array('first_name', 'last_name', $sCompanyIdCol)
);
$this->asUserInfos[$iUserId]['company'] = $this->oMySql->selectValue(MySqlManager::COMP_TABLE, MySqlManager::getText(MySqlManager::COMP_TABLE), $this->asUserInfos[$iUserId][$sCompanyIdCol]);
unset($this->asUserInfos[$iUserId][$sCompanyIdCol]);
}
}
private function incItemRank($iItemId, $iRank)
{
if(array_key_exists($iItemId, $this->asItemRanks))
{
$this->asItemRanks[$iItemId] += $iRank;
}
else
{
$this->asItemRanks[$iItemId] = $iRank;
}
}
private function formatCode($sCode, $sPattern)
{
preg_match_all('/\n(.*)\n(.*)'.$sPattern.'(.*)\n(.*)\n/i', $sCode, $asMatches);
if(!array_key_exists(0, $asMatches) || !is_array($asMatches[0]) || count($asMatches[0])==0)
{
$asResult = array(implode("\n", array_slice(explode("\n", $sCode), 0, 3))."\n[...]");
}
else
{
$asResult = $asMatches[0];
}
return $asResult;
}
private function getParsedWords($sSearchWords)
{
return array_unique(array_filter(explode(' ', $sSearchWords), array($this, 'checkSearchedWords')));
}
private function checkSearchedWords($sWord)
{
return (strlen($sWord) >= 2);
}
}
/**
* Abap Reader
* @author franzz
*/
class Reader
{
//objects
//private $oMask;
//general
private $sCode;
private $bImprovedColoring;
//Special Wors / Chars
private $asAbap;
//constants
const CASE_SENSITIVE = false;
const NOT_FOUND = '* Code introuvable...';
function __construct($sCode, $bImprovedColoring = false)
{
//settings
$this->bImprovedColoring = $bImprovedColoring;
//get code in db
$this->sCode = $sCode;
if($this->sCode=='')
{
$this->sCode = self::NOT_FOUND;
}
//ABAP key words and chars
$this->asAbap = array
(
'word'=>array
(
'wCore'=>array( /*'&lt;icon&gt;','&lt;itab&gt;',*/'ABBREVIATED','ABSTRACT','ABSTRACTFINAL','ACCEPT','ACCEPTING','ACCORDING','ACTUAL','ADD',
'ADD-CORRESPONDING','ADDITIONS','ADJACENT','ALIASES','ALL','ALLOCATE','ANALYZER', 'AND','APPEND','APPENDING','AS',
'ASCENDING','ASCENDINGDESCENDING','AT','ATTRIBUTE','AUTHORITY-CHECK','BACKGOUND','BEFORE','BEGIN','BETWEEN',
'BIGLITTLE','BINARY','BIT','BLANK','BLOCK','BREAK-POINT','BY','BYPASSING','BYTE','BYTECHARACTER','CASE',
'CASERESPECTING','CASTING','CENTERED','CHAIN','CHANGE','CHANGING','CHARACTER','CHECK','CHECKBOX',
'CHECKBOXSYMBOLICONLINE','CLASS','CLASS-DATA','CLASS-EVENTS','CLASS-METHODS','CLEANUP','CLEAR','CLIENT','CLOCK',
'CODE','COL_BACKGROUND','COL_HEADING','COL_NORMAL','COL_TOTAL','COLLECT','COLOR','COLUMN','COMMENT','COMMIT',
'COMMON','COMMUNICATION','COMPARING','COMPONENTS','COMPUTE','CONCATENATE','CONDENSE','CONSTANTS','CONTEXT',
'CONTEXTS','CONTINUE','CONTROL','CONTROLS','CONVERSION','CONVERT','COUNTRY','COUNTY','CURRENT','CURSOR',
'CUSTOMER-FUNCTION','DATA','DATABASE','DATASET','DATE','DEALLOCATE','DECIMALS','DEFAULT','DEFAULTUTF-8NON-UNICODE',
'DEFERRED','DEFINE','DEFINING','DEFINITION','DELETE','DELETING','DEMAND','DESCENDING','DESCRIBE','DESTINATION',
'DIALOG','DIRECTORY','DISTANCE','DISTINCT','DIVIDE-CORRESPONDING','DO','DUPLICATE','DUPLICATES','DURING','DYNAMIC',
'EDIT','EDITOR-CALL','ELSE','ELSEIF','ENCODING','END','ENDAT','ENDCASE','ENDCATCH','ENDCHAIN','ENDCLASS','ENDDO',
'ENDEXEC','ENDFORM','ENDFUNCTION','ENDIAN','ENDIF','ENDING','ENDINTERFACE','ENDLOOP','ENDMETHOD','ENDMODULE',
'ENDON','ENDPROVIDE','ENDSELECT','ENDTRY','ENDWHILE','END-OF_FILE','END-OF-DEFINITION','END-OF-PAGE',
'END-OF-SELECTION','ENTRIES','EQ','ERRORS','EVENT','EVENTS','EXCEPTION','EXCEPTIONS','EXCEPTION-TABLE','EXCLUDE',
'EXCLUDING','EXEC','EXIT','EXIT-COMMAND','EXPORT','EXPORTING','EXTENDED','EXTRACT','FETCH','FIELD','FIELD-GROUPS',
'FIELDSNO','FIELD-SYMBOLS','FILTER','FINAL','FIND','FIRST','FOR','FORM','FORMAT','FORWARDBACKWARD','FOUND','FRAME',
'FREE','FRIENDS','FROM','FUNCTION','FUNCTION-POOL','GE','GET','GIVING','GROUP','GT','HANDLER','HASHED','HAVING',
'HEADER','HEADING','HELP-ID','HIDE','HIGHLOW','HOLD','HOTSPOT','ID','IF','IGNORING','IMMEDIATELY','IMPLEMENTATION',
'IMPORT','IMPORTING','IN','INCREMENT','INDEX','INDEX-LINE','INHERITING','INIT','INITIAL','INITIALIZATION','INNER',
'INNERLEFT','INSERT','INSTANCES','INTENSIFIED','INTERFACE','INTERFACES','INTERVALS','INTO','INTOAPPENDING',
'INVERTED-DATE','IS','ITAB','JOIN','KEEPING','KEY','KEYS','KIND','LANGUAGE','LAST','LE','LEAVE','LEFT',
'LEFT-JUSTIFIED','LEFTRIGHT','LEFTRIGHTCIRCULAR','LEGACY','LENGTH','LIKE','LINE','LINE-COUNT','LINES','LINES',
'LINE-SELECTION','LINE-SIZE','LIST','LIST-PROCESSING','LOAD','LOAD-OF-PROGRAM','LOCAL','LOCALE','LOOP','LT',
'MARGIN','MARK','MASK','MATCH','MAXIMUM','MEMORY','MESSAGE','MESSAGE-ID','MESSAGES','METHOD','METHODS','MOD','MODE',
'MODEIN','MODIF','MODIFIER','MODIFY','MODULE','MOVE','MOVE-CORRESPONDING','MULTIPLY-CORRESPONDING','NE','NEW',
'NEW-LINE','NEW-PAGE','NEXT','NODES','NODETABLE','NO-DISPLAY','NO-EXTENSION','NO-GAP','NO-GAPS',
'NO-HEADINGWITH-HEADING','NON','NO-SCROLLING','NO-SCROLLINGSCROLLING','NOT','NO-TITLEWITH-TITLE','NO-ZERO','NUMBER',
'OBJECT','OBLIGATORY','OCCURENCE','OCCURENCES','OCCURS','OF','OFF','OFFSET','ON','ONLY','ONOFF','OPEN','OPTION',
'OPTIONAL','OR','ORDER','OTHERS','OUTPUT-LENGTH','OVERLAY','PACK','PACKAGE','PAGE','PAGELAST','PAGEOF','PAGEPAGE',
'PAGES','PARAMETER','PARAMETERS','PARAMETER-TABLE','PART','PERFORM','PERFORMING','PFN','PF-STATUS','PLACES',
'POS_HIGH','POS_LOW','POSITION','POSITIONS','PRIMARY','PRINT','PRINT-CONTROL','PRIVATE','PROCESS','PROGRAM',
'PROPERTY','PROTECTED','PROVIDE','PUBLIC','PUBLICPROTECTEDPRIVATE','PUSHBUTTON','PUT','QUICKINFO','RADIOBUTTON',
'RAISE','RAISING','RANGE','RANGES','READ','RECEIVE','RECEIVING','REDEFINITION','REFERENCE','REFRESH','REJECT',
'RENAMING','REPLACE','REPLACEMENT','REPORT','RESERVE','RESET','RESOLUTION','RESULTS','RETURN','RETURNING','RIGHT',
'RIGHT-JUSTIFIED','ROLLBACK','ROWS','RUN','SCAN','SCREEN','SCREEN-GROUP1','SCREEN-GROUP2','SCREEN-GROUP3',
'SCREEN-GROUP4','SCREEN-GROUP5','SCREEN-INPUT','SCREEN-INTENSIFIED','SCROLL','SCROLL-BOUNDARY','SEARCH','SECTION',
'SELECT','SELECTION','SELECTIONS','SELECTION-SCREEN','SELECTION-SET','SELECTION-TABLE','SELECT-OPTIONS','SEND',
'SEPARATED','SET','SHARED','SHIFT','SIGN','SINGLE','SINGLEDISTINCT','SIZE','SKIP','SORT','SORTABLE','SPACE',
'SPECIFIED','SPLIT','SQL','STABLE','STAMP','STANDARD','START','STARTING','START-OF-SELECTION','STATICS','STEP-LOOP',
'STOP','STRLEN','STRUCTURE','SUBMIT','SUBTRACT','SUBTRACT-CORRESPONDING','SUFFIX','SUPPLY','SUPPRESS','SYMBOLS',
'SYSTEM-EXCEPTIONS','TABLE','TABLES','TABLEVIEW','TASK','TEXT','THEN','TIME','TIMES','TITLE','TITLEBAR','TO',
'TOPIC','TOP-OF-PAGE','TRAILING','TRANSACTION','TRANSFER','TRANSLATE','TRY','TYPE','TYPELIKE','TYPE-POOL',
'TYPE-POOLS','TYPES','ULINE','UNION','UNIQUE','UNTIL','UP','UPDATE','UPPERLOWER','USER-COMMAND','USING','VALUE',
'VALUES','VARY','VARYING','VERSION','VIA','WAIT','WHEN','WHERE','WHILE','WINDOW','WITH','WORK','WRITE','ZONE','ADD',
'ADD-CORRESPONDING','APPEND','BREAK-POINT','CORRESPONDING','FIELDS','ASSIGN','AVG','BACK','CALL','CATCH','CHANGE',
'CHECK','CLEAR','CLOSE','COMMIT','COMPUTE','COUNT','CREATE','DATASET','DELETE','DESCRIBE','DIVIDE','DO','ELSE',
'ELSEIF','EXIT','FIND','FOR','FORMAT','GET','IF','INCLUDE','LOOP','MAX','MESSAGE','METHOD','MIN','MODIFY','MOVE',
'MULTIPLY','NEW-PAGE','OBJECT','OPEN','ORDER','READ','SORT','SUM','TRANSLATE','ULINE','WORK','WRITE','XSTRLEN',
'ABS','ACOS','AFTER','ALL','AND','AS','ASIN','ASSIGNING','AT','ATAN','BEGIN','BUFFER','BY','CA','CEIL','CENTERED',
'CN','CO','COLOR','COMPARING','COMPONENT','COS','COSH','CP','CS','DEFAULT','END','EQ','EXP','FLOOR','FRAC','GE',
'GROUP','GT','ICON','IN','INDEX','INNER','INTENSIFIED','INTO','IS','JOIN','LE','LEADING','LEAVE','LEFT','LIKE',
'LOG','LOG10','LOWER','LT','M','MOD','NA','NE','NOT','NP','NS','O','OF','OFF','ON','OR','OTHERS','OUTER','REF',
'RIGHT','SIGN','SIN','SINH','SQRT','TABLE','TABLENAME','TAN','TANH','TITLE','TO','TRAILING','TRUNC','TYPE','UPPER',
'USING','VALUE','WITH', 'TRANSPORTING', 'TYPE-POOLS'),
'wBwCore'=>array('SOURCE_PACKAGE', 'RESULT_PACKAGE', '<SOURCE_FIELDS>', '<RESULT_FIELDS>'),
'cOperator'=>array('(', ')', ',', '.', ':', '-', '~', '[', ']', '&lt;', '&gt;'),
'cCalculation'=>array('+', '-', '*', '/', '=', '(', ')'),
'cComment'=>array('*'),
'cPartComment'=>array('&quot;'),
'cString'=>array('&quot;', '&#039;'),
'iNumber'=>array('1', '2', '3', '4', '5', '6', '7', '8', '9', '0'),
'wExpand'=>array('loop'=>'endloop', 'if'=>'endif'),
'wGlobal'=>array('SY'),
'wCodePart'=>array('main', 'global', 'global2')
),
'color'=>array
(
'wCore'=>'core',
'wBwCore'=>'core',
'cOperator'=>'operator',
'cCalculation'=>'operator',
'cComment'=>'comment',
'cPartComment'=>'comment',
'cString'=>'string',
'iNumber'=>'number',
'wExpand'=>'expand',
'wGlobal'=>'glogal',
'wCodePart'=>'code_part'
)
);
}
private function getWords($sKey)
{
return $this->asAbap['word'][$sKey];
}
private function getColor($sKey)
{
return $this->asAbap['color'][$sKey];
}
private function addColoring()
{
//Safe characters
$sCode = $this->convText2Html($this->sCode);
$sServName = $_GET['serv_name'];
$sSafeRexExServName = preg_quote(str_replace('http://', '', $sServName), '/');
$asLines = explode("\n", $sCode);
$asLineClasses = array();
$iOffSet = 0;
//building lines
foreach($asLines as $iLineNb=>$sLine)
{
/* Code ref:
* <li id="#line_nb#" class="#li_class#">
* <span class="expand_line">
* <span id="#expand_id#" class="#expand_class#">-</span>
* </span>
* <span class="#code_class#">#line#</span>
* </li>
*/
$sLiClass = $sExpandSign = $sCodeClass = $sExpandHtml = $sExpandButton = '';
$sFirstWord = $this->getFirstWord($sLine);
$sFirstChar = $this->getFirstChar($sLine);
//Apply current classes
$sLiClass = implode(' ', $asLineClasses);
//Expanding starting/ending point
if(in_array($sFirstWord, array_keys($this->getWords('wExpand')))) //start
{
$iLoopId = count($asLineClasses)+$iOffSet;
$asLineClasses[] = 'loop'.$iLoopId;
$sExpandButton = '<input type="button" id="expand_loop'.$iLoopId.'" class="minus" value="" />';
}
elseif(in_array($sFirstWord, $this->getWords('wExpand'))) //end
{
array_pop($asLineClasses);
$iOffSet++;
$sExpandButton = '<span></span>';
}
//Enlarge line
if(strpos($sLine, $sServName) !== false)
{
$sLiClass .= ' bigline';
}
//comments (entire line)
$sCodeClass = (in_array($sFirstChar, $this->getWords('cComment')))?'comment':'code';
$asColoredLines[] = '<li id="'.($iLineNb+1).'" class="round_right '.$sLiClass.'"><span class="expand_line">'.$sExpandButton.'</span><span class="'.$sCodeClass.'">'.$sLine.'</span></li>';
}
$sCode = implode('', $asColoredLines);
//Strings
foreach($this->getWords('cString') as $sStringWord)
{
$sPattern = '/>([^<]*?)'.$sStringWord.'([^<]*?)'.$sStringWord.'/';
$sCode = preg_replace($sPattern, '>$1<span class="string">'.$sStringWord.'$2'.$sStringWord.'</span>', $sCode);
}
//Part comment
$sPattern = '/>([^<]*)\&quot\;([^<]*)\<\/span\>\<\/li\>/';
$sCode = preg_replace($sPattern, '>$1<span class="comment">&quot;$2</span>', $sCode);
//Internal Url
//$sPattern = '/>([^<]*)'.preg_quote($_GET['serv_name'], '/').'\/r\-([^<]*)/';
$sPattern = '/>([^<\/]*)(http:\/\/'.$sSafeRexExServName.'|'.$sSafeRexExServName.')(c|code|p|proc|procedure)\-([^<]*)/';
$sCode = preg_replace($sPattern, '>$1<a class="share internal_link" href="'.$sServName.'$3-$4" target="_blank">$3 $4</a>', $sCode);
//Global / Main
$sPattern = '/>\*\ \[('.implode('|', $this->getWords('wCodePart')).')\]/';
$sCode = preg_replace($sPattern, '><span class="code_part">&#62; $1</span>', $sCode);
//Core Words
foreach($this->getWords('wCore') as $sCoreWord)
{
$sCoreWord = strtolower($sCoreWord);
$sPattern = '/>(([^<]*)([^\w&<]{1})|.{0})('.$sCoreWord.')([\W])/';
$sCode = preg_replace($sPattern, '>$1<span class="core">$4</span>$5', $sCode);
}
//$sCoreWords = str_replace(' ', '\ ', implode('|', array_map('strtolower', $this->getWords('wCore'))));
//$sPattern = '/>(([^<]*)([^\w<]{1})|.{0})('.$sCoreWords.')(?=[\W])/U';
//$sCode = preg_replace($sPattern, '>$1<span class="core">$4</span>', $sCode);
//Operators
//TODO distinguer operator / calculation
$asOperators = array_unique(array_merge($this->getWords('cOperator'), $this->getWords('cCalculation')));
foreach($asOperators as $sOpWord)
{
$sPattern = '/>([^<]*)\\'.$sOpWord.'/';
$sCode = preg_replace($sPattern, '>$1<span class="operator">'.$sOpWord.'</span>', $sCode);
}
//$sPattern = '/>([^<]*)['.implode(array_map('strtolower', ($this->getWords('cOperator')))).']/';
//echo $sPattern;
//$sCode = preg_replace($sPattern, '>$1<span class="operator">$2$3</span>', $sCode);
//Numbers
$sPreChar = '\\'.implode('\\', $this->getWords('cCalculation')).'\s';
$sPattern = '/>((([^<]*)['.$sPreChar.']{1})|.{0})([0-9]+)([\W])/';
$sCode = preg_replace($sPattern, '>$1<span class="number">$4</span>$5', $sCode);
return $sCode;
}
private static function getFirstWord($sText)
{
return strstr(str_replace('.', ' ', trim($sText)), ' ', true);
}
private static function getFirstChar($sText)
{
return substr(str_replace('.', ' ', trim($sText)), 0, 1);
}
private function addColor(&$sText, $sWord, $sClassColor)
{
$sText = str_replace($sWord, '<span class="'.$sClassColor.'">'.$sWord.'</span>', $sText);
}
private static function getColoredWord($sWord, $sClass)
{
return '<span class="'.$sClass.'">'.$sWord.'</span>';
}
public static function convText2Html($sCode)
{
return htmlspecialchars(strtolower($sCode), ENT_QUOTES);
}
public function getColoredCode()
{
return $this->addColoring();
}
}
/**
* Mask Reader
* @author franzz
*
*/
class Mask extends PhpObject
{
public $sMaskName;
public $sFilePath;
private $sMask;
private $asTags;
private $asPartsSource;
private $aoInstances;
const MASK_FOLDER = 'masks/';
const START_TAG = 'START';
const END_TAG = 'END';
const TAG_MARK = '#';
public function __construct($sFileName='')
{
//init
parent::__construct();
$this->sMaskName = '';
$this->sFilePath = '';
$this->sMask = '';
$this->asTags = array();
$this->asPartsSource = array();
$this->aoInstances = array();
$this->sFilePath = '';
//load file
if($sFileName!='')
{
$this->initFile($sFileName);
}
}
public function initFile($sFileName)
{
$sFilePath = self::MASK_FOLDER.basename($sFileName).'.html';
if(file_exists($sFilePath))
{
$this->sFilePath = $sFilePath;
$sSource = file_get_contents($this->sFilePath);
$this->initMask($sFileName, $sSource);
}
else
{
$this->addError('Fichier introuvable &agrave; l\'adresse : '.$sFilePath);
}
}
public function initFileFromString($sSource, $sPartName='', $iInstanceNb=0)
{
$this->initMask($sPartName.' (from row) '.$iInstanceNb, $sSource);
}
private function initMask($sMaskName, $sSource)
{
$this->sMaskName = $sMaskName;
$this->sMask = $sSource;
$this->setParts();
}
private function setParts()
{
while(preg_match('/\<\!-- \[PART\] (?P<part>\S+) \[START\] --\>/', $this->sMask, $asMatch))
{
$sPartName = $asMatch['part'];
$this->asPartsSource[$sPartName] = $this->getCleanPart($sPartName);
$this->aoInstances[$sPartName] = array();
}
}
private function getCleanPart($sPartName)
{
$iStartPos = $this->getPartStartPos($sPartName);
$iEndPos = $this->getPartEndPos($sPartName);
$sPart = substr($this->sMask, $iStartPos, $iEndPos-$iStartPos);
$sExtendedPart = $this->getPartPattern($sPartName, self::START_TAG).$sPart. $this->getPartPattern($sPartName, self::END_TAG);
$this->sMask = str_replace($sExtendedPart, $this->getPartTagPattern($sPartName), $this->sMask);
return $sPart;
}
private function getPartStartPos($sPartName)
{
$sPartStartPattern = $this->getPartPattern($sPartName, self::START_TAG);
return strpos($this->sMask, $sPartStartPattern) + strlen($sPartStartPattern);
}
private function getPartEndPos($sPartName)
{
$sPartEndPattern = $this->getPartPattern($sPartName, self::END_TAG);
return strpos($this->sMask, $sPartEndPattern);
}
private function getPartPattern($sPartName, $sAction)
{
return '<!-- [PART] '.$sPartName.' ['.$sAction.'] -->';
}
private function getPartTagPattern($sPartName, $bMark=true)
{
$sPartTag = 'PART '.$sPartName;
return $bMark?$this->addTagMark($sPartTag):$sPartTag;
}
public function addInstance($sPartName, $asTags)
{
$this->newInstance($sPartName);
foreach($asTags as $sTagName=>$sTagValue)
{
$this->setInstanceTag($sPartName, $sTagName, $sTagValue);
}
}
public function newInstance($sPartName)
{
//Finding the part
$oMask = &$this->findPart($this, $sPartName);
//Retrieving source html
$sPartSource = $oMask->asPartsSource[$sPartName];
//Creating new instance
$oInstance = new Mask();
$oInstance->initFileFromString($sPartSource, $sPartName);
$oMask->aoInstances[$sPartName][] = $oInstance;
}
public function setInstanceTag($sPartName, $sTagName, $sTagValue)
{
$oMask = &$this->findPart($this, $sPartName);
$oMask->getCurrentInstance($sPartName)->setTag($sTagName, $sTagValue);
}
private function &findPart($oMask, $sPartName)
{
if(array_key_exists($sPartName, $oMask->aoInstances))
{
return $oMask;
}
else //not tested
{
foreach($oMask->aoInstances as $sLevelPartName=>$aoInstances)
{
if(!empty($aoInstances))
{
//take last instances
return $this->findPart($oMask->getCurrentInstance($sLevelPartName), $sPartName);
}
}
}
$this->addError('No part found : '.$sPartName);
}
private function getCurrentInstance($sPartName)
{
if(!empty($this->aoInstances[$sPartName]))
{
return end($this->aoInstances[$sPartName]);
}
else
{
return false;
}
}
public function setTag($sTagName, $sTagValue)
{
$this->asTags[$sTagName] = $sTagValue;
}
public function getMask()
{
$sCompletedMask = $this->sMask;
//build parts
foreach($this->aoInstances as $sPart=>$aoParts)
{
$sTagValue = '';
foreach($aoParts as $oInstance)
{
$sTagValue .= $oInstance->getMask();
}
$this->setTag($this->getPartTagPattern($sPart, false), $sTagValue);
}
//replace tags
if(!empty($this->asTags))
{
$asTags = $this->addTagMark(array_keys($this->asTags));
$sCompletedMask = str_replace($asTags, $this->asTags, $sCompletedMask);
}
return $sCompletedMask;
}
private function addTagMark($oData)
{
return ToolBox::array_map_encapsulate($oData, self::TAG_MARK);
}
}
class fileUploader
{
const GET_NAME = 'qqfile';
private $asAllowedExtensions;
private $iSizeLimit;
private $sFolderPath;
function __construct($sFolderPath, $asAllowedExtensions = array()/*, $sizeLimit = 10485760*/)
{
$this->sFolderPath = $sFolderPath;
$this->asAllowedExtensions = array_map("strtolower", $asAllowedExtensions);
//$this->iSizeLimit = $sizeLimit;
//$this->checkServerSettings();
$this->iSizeLimit = Databap::getMaxSize();
/*
if(isset($_GET[self::GET_NAME]))
{
//$this->file = new qqUploadedFileXhr();
}
elseif(isset($_FILES[self::GET_NAME])) {
$this->file = new qqUploadedFileForm();
}
else
{
$this->file = false;
}
*/
}
/*
private function checkServerSettings()
{
$postSize = $this->toBytes(ini_get('post_max_size'));
$uploadSize = $this->toBytes(ini_get('upload_max_filesize'));
if($postSize < $this->iSizeLimit || $uploadSize < $this->iSizeLimit){
$size = max(1, $this->iSizeLimit / 1024 / 1024) . 'M';
die("{'error':'increase post_max_size and upload_max_filesize to $size'}");
}
}
private function toBytes($str)
{
$val = trim($str);
$last = strtolower($str[strlen($str)-1]);
switch($last) {
case 'g': $val *= 1024;
case 'm': $val *= 1024;
case 'k': $val *= 1024;
}
return $val;
}
*/
function save($sFileName)
{
$oInput = fopen("php://input", "r");
$sTemp = tmpfile();
$iRealSize = stream_copy_to_stream($oInput, $sTemp);
fclose($oInput);
if($iRealSize != $this->getSize())
{
return false;
}
$sPath = $this->sFolderPath.$sFileName;
$oTarget = fopen($sPath, "w");
fseek($sTemp, 0, SEEK_SET);
stream_copy_to_stream($sTemp, $oTarget);
fclose($oTarget);
return true;
}
function getName()
{
return isset($_GET[self::GET_NAME])?$_GET[self::GET_NAME]:false;
}
function getSize()
{
if(isset($_SERVER["CONTENT_LENGTH"]))
{
return (int)$_SERVER["CONTENT_LENGTH"];
}
else
{
throw new Exception('Getting content length is not supported.');
}
}
//Returns array('success'=>true) or array('error'=>'error message')
function handleUpload(/*$sUploadDir, $replaceOldFile = false*/)
{
if(!is_writable($this->sFolderPath))
{
return array('error' => "Erreur serveur. Le dossier est prot&eacute;g&eacute; en &eacute;criture");
}
if(!$this->getName())
{
return array('error' => 'Aucun fichier t&eacute;l&eacute;charg&eacute;');
}
$iSize = $this->getSize();
if($iSize == 0)
{
return array('error' => 'Fichier vide');
}
if($iSize > $this->iSizeLimit)
{
return array('error' => 'Fichier trop volumineux');
}
$asPathInfo = pathinfo($this->getName());
$sExt = strtolower($asPathInfo['extension']);
$sExt = ($sExt=='jpg')?'jpeg':$sExt;
if($this->asAllowedExtensions && !in_array($sExt, $this->asAllowedExtensions))
{
$sAuthorizedExts = implode(', ', $this->asAllowedExtensions);
return array('error' => 'Le fichier a une extension invalide, les extensions autoris&eacute;es sont : '.$sAuthorizedExts);
}
//
//$sFileName = $asPathInfo['filename'];
$sFileName = md5(uniqid());
/*
if(!$replaceOldFile){
// don't overwrite previous files that were uploaded
//while (file_exists($sUploadDir . $sFileName . '.' . $sExt)) {
// $sFileName .= rand(10, 99);
//}
if(file_exists($sUploadDir . $sFileName . '.' . $sExt))
{
$sFileName .= date(Databap::DATE_COMPACT_FORMAT);
}
}
*/
if($this->save($sFileName.'.'.$sExt))
{
return array('success'=>true, 'file_name'=>$sFileName.'.'.$sExt);
}
else
{
return array('error'=> 'Erreur server. Impossible de sauvegarder le fichier.');
}
}
}
/**
* MySql query manager and generator
* @author franzz
*/
class MySqlManager extends PhpObject
{
const DB_SERVER = Settings::DB_SERVER;
const DB_LOGIN = Settings::DB_LOGIN;
const DB_PASS = Settings::DB_PASS;
const DB_NAME = Settings::DB_NAME;
const DB_NO_CONN = 'ERR_1';
const DB_NO_DATA = 'ERR_2';
const ID_TAG = 'id_';
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';
public $sDbState;
private $oConnection;
private $bTrace;
public function __construct()
{
parent::__construct();
$this->oConnection = mysql_connect(self::DB_SERVER, self::DB_LOGIN, self::DB_PASS);
$this->setTrace(false);
if(!$this->oConnection)
{
$this->addError('bug connection');
$this->sDbState = self::DB_NO_CONN;
}
else
{
if(!mysql_select_db(self::DB_NAME, $this->oConnection))
{
$this->addError('bug selecting database. Installing...');
$this->sDbState = self::DB_NO_DATA;
}
}
}
public function __destruct()
{
parent::__destruct();
mysql_close($this->oConnection);
}
public function setTrace($bAction)
{
$this->bTrace = $bAction;
}
public static function getTables()
{
$oReflect = new ReflectionClass(__CLASS__);
$asConstants = $oReflect->getConstants();
$sTableTag = '_TABLE';
$asTables = array();
foreach($asConstants as $sConstant=>$sConstantValue)
{
if(strpos($sConstant, $sTableTag)!==false && strpos($sConstant, $sTableTag)==(strlen($sConstant) - strlen($sTableTag)))
{
$asTables[] = $sConstantValue;
}
}
return $asTables;
}
public function install()
{
//Create Database
$this->setQuery("DROP DATABASE IF EXISTS ".self::DB_NAME);
$this->setQuery("CREATE DATABASE ".self::DB_NAME);
mysql_select_db(self::DB_NAME, $this->oConnection);
//Create tables
@array_walk($this->getInstallQueries(), array($this, 'setQuery'));
}
//For debug purposes
public function getFullInstallQuery()
{
$asInstallQueries = $this->getInstallQueries();
return str_replace("\n", "<br />", implode(";\n\n", $asInstallQueries))."\n\n<!-- \n".implode(";\n\n", $asInstallQueries)."\n -->";
}
private function getInstallQueries()
{
$asTables = $this->getTables();
$asInstallQueries = array_map(array($this, 'getInstallQuery'), $asTables);
$asAlterQueries = $this->getForeignKeyQueries($asTables);
return array_merge($asInstallQueries, $asAlterQueries);
}
private function getInstallQuery($sTableName)
{
$asTableColumns = $this->getTableColumns($sTableName);
$sQuery = "\n".$this->implodeAll($asTableColumns, "` ", "\n", "`", ",")."\n".implode(", \n", $this->getTableConstraints($sTableName));
return "CREATE TABLE `{$sTableName}` ({$sQuery})";
}
private function getForeignKeyQueries($asTableNames)
{
$asForeignKeyQueries = array();
foreach($asTableNames as $sTableName)
{
$asTableColumns = array_keys(self::getTablecolumns($sTableName));
foreach($asTableColumns as $sColumnName)
{
if(self::isId($sColumnName) && $sColumnName!=self::getId($sTableName))
{
$asForeignKeyQueries[] = "ALTER TABLE ".$sTableName." ADD INDEX(`".$sColumnName."`)";
$asForeignKeyQueries[] = "ALTER TABLE ".$sTableName." ADD FOREIGN KEY (`".$sColumnName."`) REFERENCES ".self::getTable($sColumnName)."(`".$sColumnName."`)";
}
}
}
return $asForeignKeyQueries;
}
private function setQuery($sQuery, $sTypeQuery=__FUNCTION__)
{
$this->getQuery($sQuery, $sTypeQuery);
return (mysql_affected_rows()!=0);
}
private function getQuery($sQuery, $sTypeQuery=__FUNCTION__)
{
$sQuery = str_replace(array("\n", "\t"), array(" ", ""), $sQuery);
$oResult = mysql_query($sQuery, $this->oConnection);
if($this->bTrace)
{
$this->setDebug(true);
$this->addNotice($sQuery);
}
if(!$oResult)
{
$this->addError("\nErreur SQL : \n".str_replace("\t", "", $sQuery)."\n\n".str_replace(array("\t", "\n"), "", mysql_error()));
}
return $oResult;
}
public function getArrayQuery($sQuery, $bStringOnly=false, $sGroupBy='', $sTypeQuery=__FUNCTION__)
{
$iIndex = 0;
$iColumnCount = 0;
$asResult = array();
$oResult = $this->getQuery($sQuery, true, $sTypeQuery);
if($oResult!==false)
{
while($asCurrentRow = mysql_fetch_array($oResult))
{
if($bStringOnly)
{
$asCurrentRow = $this->arrayKeyFilter($asCurrentRow, 'is_string');
}
//Add table reel keys
if($sGroupBy!='' && array_key_exists($sGroupBy, $asCurrentRow))
{
$iRowKey = $asCurrentRow[$sGroupBy];
unset($asCurrentRow[$sGroupBy]);
}
else
{
$iRowKey = $iIndex;
}
//For first loop, check table width
if($iIndex==0)
{
$iColumnCount = count($asCurrentRow);
}
//One column case : collapse a level
if($iColumnCount==1)
{
$asCurrentRow = array_shift($asCurrentRow);
}
$asResult[$iRowKey] = $asCurrentRow;
$iIndex++;
}
}
return $asResult;
}
private function getMaxIncrementedValue($sTable)
{
return $this->selectValue($sTable, "MAX(".$this->getId($sTable).")");
}
public static function getId($sTableName, $bFull=false)
{
$sColumnName = self::ID_TAG.self::getText($sTableName);
return $bFull?self::getFullColumnName($sTableName, $sColumnName):$sColumnName;
}
public static function getText($sTableName, $bFull=false)
{
$sColumnName = substr(str_replace('`', '', $sTableName), 0, -1);
$sColumnName = substr($sColumnName, -2)=='ie'?substr($sColumnName, 0, -2).'y':$sColumnName;
return $bFull?self::getFullColumnName($sTableName, $sColumnName):$sColumnName;
}
public static function getFullColumnName($sTableName, $sColumnName)
{
return $sTableName.".".$sColumnName;
}
private static function isId($sColumnName, $sTableName='')
{
$asTables = ($sTableName=='')?self::getTables():array($sTableName);
$asTableIds = array_map(array('self', 'getId'), $asTables);
return in_array($sColumnName, $asTableIds);
}
private static function getTable($sTableId)
{
$asTables = self::getTables();
$asTableIds = array_map(array('self', 'getId'), $asTables);
if(in_array($sTableId, $asTableIds)) return $asTables[array_search($sTableId, $asTableIds)];
else
{
$this->addError('Id '.$sTableId.' pr&eacute;sent dans aucune table');
return false;
}
}
public static function getTablecolumns($sTableName)
{
$asTableColumns = array(self::getId($sTableName));
switch($sTableName)
{
case self::USER_TABLE:
$asTableColumns[] = 'first_name';
$asTableColumns[] = 'last_name';
$asTableColumns[] = 'email';
$asTableColumns[] = self::getId(self::COMP_TABLE);
$asTableColumns[] = 'pass';
$asTableColumns[] = 'clearance';
break;
case self::COMP_TABLE:
$asTableColumns[] = self::getText(self::COMP_TABLE);
$asTableColumns[] = 'logo';
break;
case self::CODE_TABLE:
$asTableColumns[] = self::getText(self::CODE_TABLE);
$asTableColumns[] = 'description';
$asTableColumns[] = self::getId(self::USER_TABLE);
$asTableColumns[] = 'refer_id';
break;
case self::URL_TABLE:
$asTableColumns[] = self::getId(self::CODE_TABLE);;
$asTableColumns[] = 'phrase';
break;
case self::MSG_TABLE:
$asTableColumns[] = self::getId(self::USER_TABLE);
$asTableColumns[] = 'nickname';
$asTableColumns[] = self::getId(self::CHAN_TABLE);
$asTableColumns[] = self::getText(self::MSG_TABLE);
$asTableColumns[] = 'type';
$asTableColumns[] = 'date';
break;
case self::CHAN_TABLE:
$asTableColumns[] = 'safe_name';
$asTableColumns[] = self::getText(self::CHAN_TABLE);
break;
case self::CONN_TABLE:
$asTableColumns[] = self::getId(self::USER_TABLE);
$asTableColumns[] = self::getId(self::CHAN_TABLE);
break;
case self::OPT_TABLE:
$asTableColumns[] = self::getId(self::USER_TABLE);
$asTableColumns[] = self::getId(self::OPTNAME_TABLE);
$asTableColumns[] = self::getId(self::OPTVAL_TABLE);
$asTableColumns[] = self::getText(self::OPT_TABLE);
break;
case self::OPTNAME_TABLE:
$asTableColumns[] = self::getText(self::OPTNAME_TABLE);
$asTableColumns[] = 'type';
$asTableColumns[] = 'language';
break;
case self::OPTVAL_TABLE:
$asTableColumns[] = self::getId(self::OPTNAME_TABLE);
$asTableColumns[] = self::getText(self::OPTVAL_TABLE);
$asTableColumns[] = 'language';
break;
case self::PROC_TABLE:
$asTableColumns[] = self::getId(self::USER_TABLE);
$asTableColumns[] = 'title';
$asTableColumns[] = 'description';
$asTableColumns[] = 'refer_id';
break;
case self::STEP_TABLE:
$asTableColumns[] = self::getId(self::PROC_TABLE);
$asTableColumns[] = 'description';
break;
case self::IMG_TABLE:
$asTableColumns[] = self::getId(self::PROC_TABLE);
$asTableColumns[] = self::getId(self::STEP_TABLE);
$asTableColumns[] = 'description';
$asTableColumns[] = 'file_name';
break;
case self::DOC_TABLE:
$asTableColumns[] = self::getId(self::USER_TABLE);
$asTableColumns[] = 'title';
$asTableColumns[] = 'description';
$asTableColumns[] = 'refer_id';
break;
case self::FILE_TABLE:
$asTableColumns[] = self::getId(self::DOC_TABLE);
$asTableColumns[] = 'description';
$asTableColumns[] = 'file_name';
break;
case self::SEARCH_TABLE:
$asTableColumns[] = 'id_item';
$asTableColumns[] = 'refer_id';
$asTableColumns[] = 'type';
$asTableColumns[] = 'keywords';
break;
case self::ART_TABLE:
$asTableColumns[] = 'title';
$asTableColumns[] = 'link';
$asTableColumns[] = 'date';
$asTableColumns[] = 'first_name';
$asTableColumns[] = 'last_name';
$asTableColumns[] = 'email';
break;
default:
return false;
}
$asTableColumns[] = 'led';
$asTableName = array_fill(0, count($asTableColumns), $sTableName);
return array_combine($asTableColumns, array_map(array('self', 'getColumnType'), $asTableColumns, $asTableName));
}
private static function getColumnType($sColumnName, $sTableName)
{
$sColumnType = '';
switch($sColumnName)
{
case self::getText(self::USER_TABLE): //TODO delete use and field
$sColumnType = "varchar(50) NOT NULL";
break;
case 'first_name':
$sColumnType = "varchar(20) NOT NULL";
break;
case 'last_name':
$sColumnType = "varchar(20) NOT NULL";
break;
case 'nickname':
$sColumnType = "varchar(50) NOT NULL";
break;
case 'email':
$sColumnType = "varchar(100) NOT NULL";
break;
case 'pass':
$sColumnType = "varchar(128) NOT NULL";
break;
case 'clearance':
$sColumnType = "int(1) NOT NULL";
break;
case self::getText(self::CODE_TABLE):
$sColumnType = "longtext NOT NULL";
break;
case 'title':
$sColumnType = "varchar(200) NOT NULL";
break;
case 'description':
$sColumnType = "varchar(500) NOT NULL";
break;
case 'link':
$sColumnType = "varchar(200) NOT NULL";
break;
case 'refer_id':
$sColumnType = "int(10) UNSIGNED NOT NULL";
break;
case 'phrase':
$sColumnType = "varchar(50) NOT NULL";
break;
case self::getText(self::MSG_TABLE):
$sColumnType = "varchar(500) NOT NULL";
break;
case 'type':
$sColumnType = "varchar(2) NOT NULL";
break;
case 'safe_name':
$sColumnType = "varchar(50) NOT NULL";
break;
case self::getText(self::CHAN_TABLE):
$sColumnType = "varchar(50) NOT NULL";
break;
case self::getText(self::OPT_TABLE):
$sColumnType = "varchar(100) NOT NULL";
break;
case self::getText(self::OPTNAME_TABLE):
$sColumnType = "varchar(100) NOT NULL";
break;
case self::getText(self::OPTVAL_TABLE):
$sColumnType = "varchar(50) NOT NULL";
break;
case 'language':
$sColumnType = "varchar(2) NOT NULL";
break;
case 'file_name':
$sColumnType = "varchar(40) NOT NULL";
break;
case 'preview_name':
$sColumnType = "varchar(40) NOT NULL";
break;
case 'id_item':
$sColumnType = "int(10) UNSIGNED NOT NULL";
break;
case 'keywords':
$sColumnType = "longtext NOT NULL";
break;
case self::getText(self::COMP_TABLE):
$sColumnType = "varchar(30) NOT NULL";
break;
case 'logo':
$sColumnType = "varchar(20) NOT NULL";
break;
case 'date':
$sColumnType = "date NOT NULL";
break;
case 'led':
$sColumnType = "TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP";
break;
case self::isId($sColumnName, $sTableName):
$sColumnType = "int(10) UNSIGNED auto_increment";
break;
case self::isId($sColumnName):
$sColumnType = "int(10) UNSIGNED";
break;
}
return $sColumnType;
}
private static function getTableConstraints($sTableName)
{
//Primary key
$asTableConstraints = array('PRIMARY' => "PRIMARY KEY (`".self::getId($sTableName)."`)");
//Foreign keys
//Foreign keys applied using ALTER TABLE syntax at the end to prevent scheduling CREATE TABLE queries
//Other constraints
switch($sTableName)
{
case self::USER_TABLE :
$asTableConstraints[] = "UNIQUE KEY `user_first_and_last_name` (`first_name`, `last_name`)";
break;
case self::URL_TABLE :
$asTableConstraints[] = "UNIQUE KEY `uni_phrase` (`phrase`)";
break;
case self::MSG_TABLE :
$asTableConstraints[] = "INDEX(`date`)";
break;
case self::ART_TABLE:
$asTableConstraints[] = "INDEX(`title`)";
break;
}
return $asTableConstraints;
}
private function addQuotes($oData)
{
//TODO remake
$asTrustedFunc = array('CURDATE()', 'NOW()');
$sChar = "'";
if(is_array($oData))
{
$asChar = array_fill(1, count($oData), $sChar);
return array_combine(array_keys($oData), array_map(array($this, 'addQuotes'), $oData, $asChar));
}
else
{
if(in_array($oData, $asTrustedFunc)) return $oData;
else return $sChar.$oData.$sChar;
}
}
private function getLastId()
{
return mysql_insert_id();
}
public function insertRow($sTableName, $asData)
{
$this->cleanSql($sTableName);
$this->cleanSql($asData);
$asQueryValues = $this->addQuotes($asData);
$sQuery = "INSERT INTO ".$sTableName." (`".implode("`, `", array_keys($asQueryValues))."`) VALUES (".implode(", ", $asQueryValues).")";
return $this->setQuery($sQuery)?$this->getLastId():0;
}
public function updateRow($sTableName, $asConstraints, $asData)
{
return $this->updateRows($sTableName, $asConstraints, $asData, 1);
}
public function updateRows($sTableName, $asConstraints, $asData, $iLimit=0)
{
if(!is_array($asConstraints))
{
$asConstraints = array($this->getId($sTableName)=>$asConstraints);
}
$this->cleanSql($sTableName);
$this->cleanSql($iTableId);
$this->cleanSql($asData);
$this->cleanSql($asConstraints);
$asQueryValues = $this->addQuotes($asData);
$asConstraintsValues = $this->addQuotes($asConstraints);
$this->addColumnSelectors($asQueryValues);
$this->addColumnSelectors($asConstraintsValues);
$sLimit = $iLimit>0?" LIMIT $iLimit":"";
$sQuery = "UPDATE {$sTableName} ".
"SET ".$this->implodeAll($asQueryValues, " = ", ", ")." ".
"WHERE ".$this->implodeAll($asConstraintsValues, " = ", " AND ").$sLimit;
$iResult = false;
if($this->setQuery($sQuery))
{
$iResult = ($iLimit==1)?$this->selectValue($sTableName, $this->getId($sTableName), $asConstraints):true;
}
return $iResult;
}
public function insertUpdateRow($sTableName, $asData, $asKeys=array(), $bUpdate=true)
{
$sTableIdName = self::getId($sTableName);
//check for data in the db
if($asKeys==array())
{
$asKeys[] = $sTableIdName;
}
$asValues = array_intersect_key($asData, array_flip($asKeys));
$iTableId = $this->selectValue($sTableName, $sTableIdName, $asValues);
//insert
if(!$iTableId)
{
$iTableId = $this->insertRow($sTableName, $asData);
}
//Update
elseif($bUpdate)
{
if(array_key_exists($sTableIdName, $asData))
{
unset($asData[$sTableIdName]);
}
$iTableId = $this->updateRow($sTableName, $iTableId, $asData);
}
return $iTableId;
}
public function selectInsert($sTableName, $asData, $asKeys=array())
{
return $this->insertUpdateRow($sTableName, $asData, $asKeys, false);
}
public function deleteRow($sTableName, $iTableId)
{
$this->cleanSql($sTableName);
$this->cleanSql($iTableId);
//linked tables
switch($sTableName)
{
case self::CODE_TABLE :
$asTables = array($sTableName, self::URL_TABLE);
break;
case self::PROC_TABLE :
$asTables = array($sTableName, self::STEP_TABLE, self::IMG_TABLE);
break;
case is_string($sTableName) :
$asTables = array($sTableName);
break;
case is_array($sTableName):
$asTables = $sTableName;
break;
default:
$asTables = array();
}
foreach($asTables as $sTable)
{
$this->setQuery("DELETE FROM ".$sTable." WHERE ".$this->getId($sTableName)." = ".$iTableId);
}
}
public function selectRows($asInfo, $bStringOnly=true, $sGroupBy='')
{
$asAttributes = array('select'=>"SELECT", 'from'=>"FROM", 'join'=>"LEFT JOIN", 'joinOn'=>"LEFT JOIN", 'constraint'=>"WHERE", 'groupBy'=>"GROUP BY", 'orderBy'=>"ORDER BY", 'limit'=>'LIMIT');
$asRowSeparators = array('select'=>", ", 'from'=>"", 'join'=>" LEFT JOIN ", 'joinOn'=>" LEFT JOIN ", 'constraint'=>" AND ", 'groupBy'=>", ", 'orderBy'=>", ", 'limit'=>"");
$asOperators = array('constraint'=>" = ", 'orderBy'=>" ", 'join'=>" USING(", 'joinOn'=>" ON ");
$asEndOfStatement = array('constraint'=>"", 'orderBy'=>"", 'join'=>")", 'joinOn'=>"");
//$sQuery = "/* ".str_replace(array("\n", "\t"), '', print_r($asInfo, true))." */";
$sQuery = "";
foreach($asAttributes as $sStatement => $sKeyWord)
{
$asSelection = array_key_exists($sStatement, $asInfo)?$asInfo[$sStatement]:array();
if(!is_array($asSelection))
{
$asSelection = array($asSelection);
}
//if provided values
if(!empty($asSelection))
{
$this->cleanSql($asSelection);
if($sStatement=='constraint' && !array_key_exists('constVar', $asInfo))
{
$asSelection = $this->addQuotes($asSelection);
}
$this->addColumnSelectors($asSelection);
$sQuery .= " ".$sKeyWord." ";
//in case of double value input
if(array_key_exists($sStatement, $asOperators))
{
if($sStatement=='constraint' && array_key_exists('constOpe', $asInfo))
{
$asOperators[$sStatement] = $asInfo['constOpe'];
}
$sQuery .= $this->implodeAll($asSelection, $asOperators[$sStatement], $asRowSeparators[$sStatement], "", $asEndOfStatement[$sStatement]);
}
else
{
$sQuery .= implode($asRowSeparators[$sStatement], $asSelection);
}
}
//default value for select
elseif($sStatement=='select')
{
$sQuery .= " ".$sKeyWord." * ";
}
}
return $this->getArrayQuery($sQuery, $bStringOnly, $sGroupBy);
}
private function addColumnSelectors(&$asSelection)
{
//TODO get rid of this
$sSqlWord = 'option';
$sKey = array_search($sSqlWord, $asSelection);
if($sKey!==false)
{
$asSelection[$sKey] = "`".$asSelection[$sKey]."`";
}
elseif(array_key_exists($sSqlWord, $asSelection))
{
$asSelection["`".$sSqlWord."`"] = $asSelection[$sSqlWord];
unset($asSelection[$sSqlWord]);
}
}
public function selectRow($sTableName, $asConstraints=array(), $sColumnName='*')
{
if(!is_array($asConstraints))
{
$asConstraints = array($this->getId($sTableName)=>$asConstraints);
}
$asResult = $this->selectRows(array('select'=>$sColumnName, 'from'=>$sTableName, 'constraint'=>$asConstraints));
$iCountNb = count($asResult);
switch($iCountNb)
{
case 0 :
return false;
case $iCountNb > 1 :
$this->addError('Trop de r&eacute;sultats pour un selectRow() : '.$iCountNb.' lignes. Table: '.$sTableName.', contrainte: '.self::implodeAll($asConstraints, '=', ' ').', colonne: '.$sColumnName);
break;
}
return array_shift($asResult);
}
public function selectValue($sTableName, $sColumnName, $oConstraints=array())
{
if(!is_array($oConstraints))
{
$oConstraints = array($this->getId($sTableName)=>$oConstraints);
}
return $this->selectRow($sTableName, $oConstraints, $sColumnName);
}
public function pingValue($sTableName, $oConstraints)
{
return $this->selectValue($sTableName, 'COUNT(1)', $oConstraints);
}
public static function cleanSql(&$oData)
{
self::cleanData($oData, 'mysql_real_escape_string');
$oData = self::cleanData($oData, 'mysql_real_escape_string');
}
public static function implodeAll($asText, $asKeyValueSeparator='', $sRowSeparator='', $sKeyPre='', $sValuePost=false)
{
if($sValuePost===false)
{
$sValuePost = $sKeyPre;
}
$asCombinedText = array();
//if unique value for key value separator
if(!is_array($asKeyValueSeparator) && !empty($asText))
{
$asKeyValueSeparator = array_combine(array_keys($asText), array_fill(0, count($asText), $asKeyValueSeparator));
}
foreach($asText as $sKey=>$sValue)
{
$asCombinedText[] = $sKeyPre.$sKey.$asKeyValueSeparator[$sKey].(is_array($sValue)?implode($sValue):$sValue).$sValuePost;
}
return implode($sRowSeparator, $asCombinedText);
}
public static function arrayKeyFilter($asArray, $sCallBack)
{
$asValidKeys = array_flip(array_filter(array_keys($asArray), $sCallBack));
return array_intersect_key($asArray, $asValidKeys);
}
public static function cleanData($oData, $sCleaningFunc)
{
if(!is_array($oData))
{
$test = call_user_func($sCleaningFunc, $oData);
return $test;
}
elseif(count($oData)>0)
{
$asCleaningFunc = array_fill(1, count($oData), $sCleaningFunc);
$asKeys = array_map(array('self', 'cleanData'), array_keys($oData), $asCleaningFunc);
$asValues = array_map(array('self', 'cleanData'), $oData, $asCleaningFunc);
return array_combine($asKeys, $asValues);
}
}
}
/**
* ToolBox - Only static functions missing from php librairy
* @author franzz
*/
class ToolBox
{
function __construct(){}
public function toString($sSep, $asData)
{
if(is_array($asData) && count($asData)>0)
{
$sData = $sSep;
foreach($asData as $oData)
{
$sData .= self::toString($oData).$sSep;
}
return $sData;
}
else return $asData;
}
public static function cleanPost(&$asData)
{
//get rid of magic quotes
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
{
$asData = MySqlManager::cleanData($asData, 'stripslashes');
}
}
public static function fixGlobalVars($argv)
{
//Add CLI arguments
if(defined('STDIN')) parse_str(implode('&', array_slice($argv, 1)), $_GET);
//Add Server Name
$sServerName = array_key_exists('SERVER_NAME', $_SERVER)?$_SERVER['SERVER_NAME']:$_SERVER['PWD'];
$sAppPath = 'http://'.str_replace('http://', '', $sServerName.dirname($_SERVER['SCRIPT_NAME']));
$_GET['serv_name'] = $sAppPath.(substr($sAppPath, -1)!='/'?'/':'');
}
public static function array_map_encapsulate($oData, $sChar)
{
if(is_array($oData))
{
$asChar = array_fill(1, count($oData), $sChar);
return array_combine(array_keys($oData), array_map(array('self', 'array_map_encapsulate'), $oData, $asChar));
}
else
{
return $sChar.$oData.$sChar;
}
}
public static function capitalizeWords($acText, $sCharList = '')
{
// Use ucwords if no delimiters are given
if($sCharList=='') {
return ucwords($acText);
}
// Go through all characters
$capitalizeNext = true;
$max = strlen($acText);
for ($i = 0; $i < $max; $i++)
{
if(strpos($sCharList, $acText[$i]) !== false)
{
$capitalizeNext = true;
}
elseif($capitalizeNext)
{
$capitalizeNext = false;
$acText[$i] = strtoupper($acText[$i]);
}
}
return $acText;
}
public static function sendMail($sFrom, $sTo, $sReplyTo, $sSubject, $sMessage)
{
$sResult = '';
if($sFrom!='' && $sTo!='' && $sReplyTo!='' && $sSubject!='' && $sMessage!='')
{
$sHtmlMessage = str_replace("\n", '<br />', $sMessage);
$sPlainMessage = strip_tags(str_replace('<br />', "\n", $sHtmlMessage));
$iBoundary = uniqid('HTMLEMAIL');
$sHeaders = 'From: '.$sFrom."\r\n".
'Reply-To: '.$sReplyTo."\r\n".
'MIME-Version: 1.0'."\r\n".
'Content-Type: multipart/alternative;'.
'boundary = '.$iBoundary."\r\n\r\n".
'MIME encoded Message'.
'--'.$iBoundary."\r\n".
'Content-Type: text/plain; charset=UTF-8'."\r\n".
'Content-Transfer-Encoding: base64'."\r\n\r\n".
chunk_split(base64_encode($sPlainMessage)).
'--'.$iBoundary."\r\n".
'Content-Type: text/html; charset=UTF-8'."\r\n".
'Content-Transfer-Encoding: base64'."\r\n\r\n".
chunk_split(base64_encode($sHtmlMessage));
if(!mail($sTo, $sSubject, '', $sHeaders))
{
$sResult = 'Email: An unknown error occured';
}
}
else
{
$sResult = 'Email: Some fields were empty';
}
}
public static function createThumbnail($sInPath, $iMaxWidth, $iMaxHeight, $sOutPath='', $bDeleteIn=false)
{
$asResult = array('error'=>'');
//Look up the extension to choose the image creator
//TODO use MIME types
$sInInfo = pathinfo($sInPath);
$sInName = strtolower($sInInfo['basename']);
$sImageExt = strtolower($sInInfo['extension']);
$sImageExt = ($sImageExt=='jpg')?'jpeg':$sImageExt;
//New Destination folder
if($sOutPath=='') $sOutPath = $sInPath;
elseif(substr($sOutPath, -1)=='/') $sOutPath .= $sInName;
//New sizes
if(in_array($sImageExt, Databap::$UPLOAD_IMG_EXTS))
{
list($iWidth, $iHeight) = getimagesize($sInPath);
if($iWidth > $iMaxWidth || $iHeight > $iMaxHeight)
{
if($iWidth > $iHeight)
{
$iResizedWidth = $iMaxWidth;
$iResizedHeight = ($iResizedWidth / $iWidth) * $iHeight;
}
else
{
$iResizedHeight = $iMaxHeight;
$iResizedWidth = ($iResizedHeight / $iHeight) * $iWidth;
}
//create image from source
$oSource = call_user_func('imagecreatefrom'.$sImageExt, $sInPath);
//Resize
$oThumb = imagecreatetruecolor($iResizedWidth, $iResizedHeight);
imagecopyresized($oThumb, $oSource, 0, 0, 0, 0, $iResizedWidth, $iResizedHeight, $iWidth, $iHeight);
//Save
if(file_exists($sOutPath)) unlink($sOutPath);
if(!call_user_func_array('image'.$sImageExt, array($oThumb, $sOutPath)))
{
$asResult['error'] = 'Unable to create thumbnail : '.$sOutPath;
}
}
elseif($sInPath != $sOutPath)
{
$iResizedWidth = $iWidth;
$iResizedHeight = $iHeight;
if(!copy($sInPath, $sOutPath)) $asResult['error'] = 'Copy failed from '.$sInPath.' to '.$sOutPath;
}
$asResult['width'] = $iResizedWidth;
$asResult['height'] = $iResizedHeight;
$asResult['out'] = $sOutPath;
}
else $asResult['error'] = 'Wrong file type';
if($bDeleteIn && $asResult['error']=='' && $sInPath != $sOutPath) unlink($sInPath);
return $asResult;
}
}
/* Debug */
function pre($sText, $sMode='return', $bDie=false, $sTitle='Test')
{
$sLog = '<fieldset class="rounded">
<legend class="rounded">'.$sTitle.'</legend>
<pre>'.print_r($sText, true).'</pre>
</fieldset>';
switch($sMode)
{
case 'echo':
echo $sLog;
break;
case 'return':
if($bDie) echo $sLog;
break;
case 'log':
file_put_contents('log.html', ($sTitle!=''?$sTitle." :\n":'').print_r($sText, true)."\n\n", FILE_APPEND);
break;
default:
break;
}
if($bDie)
{
die('[die() called by the test function '.__FUNCTION__.'()]');
}
return $sLog;
}
function dlog($sText, $sTitle='Test')
{
pre($sText, 'log', false, date('d/m/Y H:m:i').' - '.$sTitle, false);
}
?>