This commit is contained in:
2014-12-03 20:27:47 +01:00
commit 49a500fafb
19 changed files with 2638 additions and 0 deletions

226
config.php Executable file
View File

@@ -0,0 +1,226 @@
<?php
/**
* Manage includes
* @author franzz
*/
class ClassManagement extends PhpObject
{
const INC_FOLDER = 'inc/';
const INC_EXT = '.php';
const SETTINGS_FILE = 'settings.php';
const TOOLBOX_CLASS = 'toolbox';
private $asIncFiles;
function __construct($sMainClass)
{
parent::__construct();
$this->asIncFiles = array();
//try to include default files
$this->incFile(self::SETTINGS_FILE);
$this->incClass(self::TOOLBOX_CLASS);
//Include main class
$this->incClass($sMainClass);
}
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;
}
}
/**
* PhpObject
* @author franzz
* @version 1.0
*/
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;
protected $bDebug;
function __construct($iExtractMode=self::MODE_FILE)
{
$this->resetMessageStack();
$this->iExtractMode = $iExtractMode;
$this->bDebug = false;
}
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->addMessage(self::NOTICE_TAB, $sNotice);
}
protected function addWarning($sWarning)
{
$this->addMessage(self::WARNING_TAB, $sWarning);
}
protected function addError($sError)
{
$this->addMessage(self::ERROR_TAB, $sError);
}
private function addMessage($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;
}
}
}
}
?>

131
inc/main.php Executable file
View File

@@ -0,0 +1,131 @@
<?php
/**
* Main Class
* @author franzz
* @version 1.0
*/
class Main extends PhpObject
{
//Constants
//...
//Objects
private $oClassManagement;
private $oMySql;
private $oTranslator;
//...
//Variables
private $sLang;
private $asMasks;
//...
/**
* Main constructor [to be called from index.php]
* @param ClassManagement $oClassManagement
* @param string $sLang
*/
public function __construct($oClassManagement, $sLang='')
{
parent::__construct(__CLASS__, Settings::DEBUG);
$this->oClassManagement = $oClassManagement;
//Browser <> PHP <> MySql synchronization
date_default_timezone_set(Settings::TIMEZONE);
ini_set('default_charset', Settings::TEXT_ENC);
header('Content-Type: text/html; charset='.Settings::TEXT_ENC);
mb_internal_encoding(Settings::TEXT_ENC);
mb_http_output(Settings::TEXT_ENC);
mb_http_input(Settings::TEXT_ENC);
mb_language('uni');
mb_regex_encoding(Settings::TEXT_ENC);
//Load classes
$this->oClassManagement->incClass('mask');
$this->oClassManagement->incClass('translator');
$this->oClassManagement->incClass('mysqlmanager');
//...
//Init objects
$this->setLanguage($sLang);
$this->setMasks();
$this->oTranslator = new Translator($this->getLanguage());
$this->oMySql = new MySqlManager(Settings::DB_SERVER, Settings::DB_LOGIN, Settings::DB_PASS, Settings::DB_NAME, self::getSqlOptions() , Settings::DB_ENC);
if($this->oMySql->sDbState == MySqlManager::DB_NO_DATA) $this->install();
//...
}
/**
* DB structure. See MySqlManager::__construct
*/
private static function getSqlOptions()
{
return array
(
'tables' => array
(
self::USER_TABLE=>array( 'first_name', 'last_name', 'nickname', 'email', 'pass')
//...
),
'types' => array
(
'first_name'=>"varchar(20) NOT NULL",
'last_name'=>"varchar(20) NOT NULL",
'nickname'=>"varchar(50) NOT NULL",
'email'=>"varchar(100) NOT NULL",
'pass'=>"varchar(128) NOT NULL"
//...
),
'constraints' => array
(
self::USER_TABLE=>"UNIQUE KEY `firstname_lastname_nickname` (`first_name`, `last_name`, `nickname`)"
//...
),
'cascading_delete' => array
(
self::USER_TABLE=>array(self::DON_TABLE)
//...
)
);
}
private function getLanguage()
{
return $this->sLang;
}
private function setLanguage($sLang='')
{
if($sLang!='') $this->sLang = $sLang;
else
{
//$_SERVER['REMOTE_ADDR'] = '193.106.178.41'; //Spain
//$_SERVER['REMOTE_ADDR'] = '160.92.167.193'; //France
//$_SERVER['REMOTE_ADDR'] = '74.125.230.216'; //US
$asIpInfo = json_decode(file_get_contents('http://api.ipinfodb.com/v3/ip-country/?key='.self::LOC_API_KEY.'&format=json&ip='.$_SERVER['REMOTE_ADDR']), true);
if($asIpInfo['statusCode'] == 'OK') $this->sLang = $asIpInfo['countryCode'];
}
}
private function setMasks()
{
//List all available masks
$asMaskPaths = glob(Mask::getMaskFile('*'));
$this->asMasks = array_map('basename', $asMaskPaths, array_fill(1, count($asMaskPaths), Mask::MASK_EXT));
}
private static function jsonExport($asData)
{
header('Content-type: application/json');
//return htmlspecialchars(json_encode($asData), ENT_NOQUOTES);
return self::jsonConvert($asData);
}
private static function jsonConvert($asData)
{
return json_encode($asData);
}
}
?>

231
inc/mask.php Executable file
View File

@@ -0,0 +1,231 @@
<?php
/**
* Mask Reader
* @author franzz
* @version 1.0
*/
class Mask extends PhpObject
{
public $sMaskName;
public $sFilePath;
private $sMask;
private $asTags;
private $asPartsSource;
private $aoInstances;
const MASK_FOLDER = 'masks/';
const MASK_EXT = '.html';
const START_TAG = 'START';
const END_TAG = 'END';
const TAG_MARK = '[#]';
public function __construct($sFileName='')
{
//init
parent::__construct(__CLASS__, Settings::DEBUG);
$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 static function getMaskFile($sFileName)
{
return self::MASK_FOLDER.$sFileName.self::MASK_EXT;
}
public function initFile($sFileName)
{
$sFilePath = self::getMaskFile(basename($sFileName));
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\] --\>/u', $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 = mb_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 mb_strpos($this->sMask, $sPartStartPattern) + strlen($sPartStartPattern);
}
private function getPartEndPos($sPartName)
{
$sPartEndPattern = $this->getPartPattern($sPartName, self::END_TAG);
return mb_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 is a pointer)
$oMask = $this->findPart($this, $sPartName);
if(!$oMask) $this->addError('No part found : '.$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);
if(!$oMask) $this->addError('No part found : '.$sPartName);
$oMask->getCurrentInstance($sPartName)->setTag($sTagName, $sTagValue);
}
private function findPart($oMask, $sPartName)
{
if(array_key_exists($sPartName, $oMask->aoInstances))
{
return $oMask;
}
else //going deeper to find the part
{
foreach($oMask->aoInstances as $sLevelPartName=>$aoInstances)
{
if(!empty($aoInstances))
{
//take last instances
$oTmpMask = $this->findPart($oMask->getCurrentInstance($sLevelPartName), $sPartName);
if($oTmpMask) return $oTmpMask;
}
}
}
return false;
}
private function getCurrentInstance($sPartName)
{
if(!empty($this->aoInstances[$sPartName]))
{
return end($this->aoInstances[$sPartName]);
}
else
{
return false;
}
}
public function getTags()
{
$sSafeTagMark = preg_quote(self::TAG_MARK);
$sPattern = '/'.$sSafeTagMark.'(?P<tag>\w+)'.$sSafeTagMark.'/u';
preg_match_all($sPattern, $this->sMask, $asMatches);
return array_unique(array_filter($asMatches['tag']));
}
public function setTag($sTagName, $sTagValue)
{
$this->asTags[$sTagName] = $sTagValue;
}
public function setTags($asTags)
{
foreach($asTags as $sTagName=>$sTagValue) $this->setTag($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);
}
}
?>

600
inc/mysqlmanager.php Executable file
View File

@@ -0,0 +1,600 @@
<?php
/**
* MySql query manager and generator
* @author franzz
* @version 1.0
*/
class MySqlManager extends PhpObject
{
const DB_NO_CONN = 'ERR_1';
const DB_NO_DATA = 'ERR_2';
const ID_TAG = 'id_';
public $sDbState;
private $bTrace;
private $asOptions;
/**
* SQL connection Handle
* @var mysqli
*/
private $oConnection;
private $sDatabase;
/**
* Constructor MySqlManager
* @param String $sDbServer
* @param String $sLogin
* @param String $sPass
* @param String $sDatabase
* @param Array $asOptions
* array( 'tables'=>array('table_name1'=>array('table_field1', 'table_field2', ...), 'table_name2'=>array(...)),
* 'types'=>array('field1'=>'field_type1', 'field2'=>'field_type2', ...)
* 'constraints'=>array('table_name1'=>'table_contraint1', 'table_name2'=>'table_contraint2', ...),
* 'cascading_delete'=>array('table_name1'=>array('linked_table1', 'linked_table2', ...), 'table_name2'=>...))
* @param string $sEncoding
*/
public function __construct($sDbServer, $sLogin, $sPass, $sDatabase, $asOptions, $sEncoding='utf8mb4')
{
parent::__construct(__CLASS__, Settings::DEBUG);
$this->sDatabase = $sDatabase;
$this->asOptions = $asOptions;
//$this->oConnection = mysql_connect(self::DB_SERVER, self::DB_LOGIN, self::DB_PASS);
$this->oConnection = new mysqli($sDbServer, $sLogin, $sPass);
$this->syncPhpParams($sEncoding);
/*
$dsn = 'mysql:dbname='.$this->sDatabase.';host='.self::DB_SERVER;
try {$dbh = new PDO($dsn, self::DB_LOGIN, self::DB_PASS);}
catch (PDOException $e) {$this->addError('Connexion échouée : ' . $e->getMessage());}
*/
$this->setTrace(false);
//if(!$this->oConnection)
if($this->oConnection->connect_error)
{
//$this->addError('bug connection');
$this->addError('bug connection : '.$this->oConnection->connect_error);
$this->sDbState = self::DB_NO_CONN;
}
else
{
//if(!mysql_select_db($this->sDatabase, $this->oConnection))
if(!$this->oConnection->select_db($this->sDatabase))
{
$this->addError('bug selecting database. Installing...');
$this->sDbState = self::DB_NO_DATA;
}
}
}
private function syncPhpParams($sEncoding)
{
//Characters encoding
$this->oConnection->set_charset($sEncoding); //SET NAMES
//Time zone
$oNow = new DateTime();
$iMins = $oNow->getOffset() / 60;
$iSign = ($iMins < 0)?-1:1;
$iMins = abs($iMins);
$iHours = floor($iMins / 60);
$iMins -= $iHours * 60;
$sOffset = sprintf('%+d:%02d', $iHours*$iSign, $iMins);
$this->setQuery("SET time_zone='{$sOffset}';");
}
public function __destruct()
{
parent::__destruct();
//mysql_close($this->oConnection);
$this->oConnection->close();
}
public function setTrace($bAction)
{
$this->bTrace = $bAction;
}
public function getTables()
{
/*
$oReflect = new ReflectionClass(__CLASS__);
$asConstants = $oReflect->getConstants();
$sTableTag = '_TABLE';
$asTables = array();
foreach($asConstants as $sConstant=>$sConstantValue)
{
if(mb_strpos($sConstant, $sTableTag)!==false && mb_strpos($sConstant, $sTableTag)==(mb_strlen($sConstant) - mb_strlen($sTableTag)))
{
$asTables[] = $sConstantValue;
}
}
return $asTables;
*/
return array_keys($this->asOptions['tables']);
}
public function install()
{
//Create Database
$this->setQuery("DROP DATABASE IF EXISTS ".$this->sDatabase);
$this->setQuery("CREATE DATABASE ".$this->sDatabase." DEFAULT CHARACTER SET ".Settings::DB_ENC." DEFAULT COLLATE ".Settings::DB_ENC."_general_ci");
//mysql_select_db($this->sDatabase, $this->oConnection);
$this->oConnection->select_db($this->sDatabase);
//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($this->getTablecolumns($sTableName));
foreach($asTableColumns as $sColumnName)
{
if($this->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);
return ($this->oConnection->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->oConnection->query($sQuery)))
{
$this->addError("\nErreur SQL : \n".str_replace("\t", "", $sQuery)."\n\n".str_replace(array("\t", "\n"), "", $this->oConnection->error));
}
return $oResult;
}
public function getLastError()
{
}
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))
while($asCurrentRow = $oResult->fetch_array())
{
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 = mb_substr(str_replace('`', '', $sTableName), 0, -1);
$sColumnName = mb_substr($sColumnName, -2)=='ie'?mb_substr($sColumnName, 0, -2).'y':$sColumnName;
return $bFull?self::getFullColumnName($sTableName, $sColumnName):$sColumnName;
}
public static function getFullColumnName($sTableName, $sColumnName)
{
return $sTableName.".".$sColumnName;
}
private function isId($sColumnName, $sTableName='')
{
$asTables = ($sTableName=='')?$this->getTables():array($sTableName);
$asTableIds = array_map(array('self', 'getId'), $asTables);
return in_array($sColumnName, $asTableIds);
}
private function getTable($sTableId)
{
$asTables = $this->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 function getTablecolumns($sTableName)
{
if(!array_key_exists($sTableName, $this->asOptions['tables'])) return false;
$asTableColumns = array(self::getId($sTableName));
foreach($this->asOptions['tables'][$sTableName] as $sFieldName) $asTableColumns[] = $sFieldName;
$asTableColumns[] = 'led';
$asTableName = array_fill(0, count($asTableColumns), $sTableName);
return array_combine($asTableColumns, array_map(array('self', 'getColumnType'), $asTableColumns, $asTableName));
}
private function getColumnType($sColumnName, $sTableName)
{
$sColumnType = '';
switch($sColumnName)
{
case array_key_exists($sColumnName, $this->asOptions['types']):
$sColumnType = $this->asOptions['types'][$sColumnName];
break;
case 'led':
$sColumnType = "TIMESTAMP NOT NULL ON UPDATE CURRENT_TIMESTAMP DEFAULT CURRENT_TIMESTAMP";
break;
case $this->isId($sColumnName, $sTableName):
$sColumnType = "int(10) UNSIGNED auto_increment";
break;
case $this->isId($sColumnName):
$sColumnType = "int(10) UNSIGNED";
break;
}
return $sColumnType;
}
private function getTableConstraints($sTableName)
{
//Primary key
$asTableConstraints = array('PRIMARY' => "PRIMARY KEY (`".self::getId($sTableName)."`)");
//Foreign keys: applied using ALTER TABLE syntax at the end to prevent scheduling CREATE TABLE queries
//Other constraints
if(array_key_exists($sTableName, $this->asOptions['constraints'])) $asTableConstraints[] = $this->asOptions['constraints'][$sTableName];
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 $this->oConnection->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 array_key_exists($sTableName, $this->asOptions['cascading_delete']) :
$asTables = array_filter(is_array($sTableName)?$sTableName:array($sTableName) + $this->asOptions['cascading_delete'][$sTableName]);
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 function cleanSql(&$oData)
{
//self::cleanData($oData, 'mysql_real_escape_string');
//$oData = self::cleanData($oData, 'mysql_real_escape_string');
$this->cleanData($oData);
$oData = $this->cleanData($oData);
}
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 function cleanData($oData)
{
if(!is_array($oData))
{
return $this->oConnection->real_escape_string($oData);
}
elseif(count($oData)>0)
{
$asKeys = array_map(array($this, 'cleanData'), array_keys($oData));
$asValues = array_map(array($this, 'cleanData'), $oData);
return array_combine($asKeys, $asValues);
}
}
}
?>

169
inc/rss.php Executable file
View File

@@ -0,0 +1,169 @@
<?php
/**
* RSS Feed Class
* @author franzz
* @version 1.1
*
* Input:
* - $asDesc: Array. Description of the feed: fields 'title', 'link' (optional), 'copyright', 'description', 'language', 'webmaster_mail'
* - $asItems: Array. Feed item data: fields 'title', 'description', 'author', 'link', 'pub_date', 'guid'
*/
class Feed extends PhpObject {
private $asDesc;
private $asItems;
public function __construct($asDesc, $asItems=array())
{
parent::__construct(__CLASS__, Settings::DEBUG);
if(!array_key_exists('link', $asDesc))
{
$asDesc['link'] = 'http://'.$_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME'].'/rss';
}
$this->asDesc = $asDesc;
array_walk($asItems, array($this, 'addItem'));
}
public function addItem($asItem)
{
$this->asItems[] = $asItem;
return count($this->asItems) - 1;
}
public function removeItem($iItemId)
{
$bExist = array_key_exists($iItemId, $this->asItems);
if($bExist) unset($this->asItems[$iItemId]);
return $bExist;
}
private function getGlobalPubDate()
{
$iGlobalPubDate = 0;
foreach($this->asItems as $asItem)
{
$iItemPubDate = strtotime($asItem['pub_date']);
if($iItemPubDate>$iGlobalPubDate)
{
$iGlobalPubDate = $iItemPubDate;
}
}
return self::cleanRss(self::getDate($iGlobalPubDate));
}
public function getFeed()
{
//feed header
$sRssFeedHeader = self::getHtml($this->asDesc['title'], 'title');
$sRssFeedHeader .= self::getHtml($this->asDesc['link'], 'link');
$sRssFeedHeader .= self::getHtml($this->asDesc['copyright'], 'copyright');
$sRssFeedHeader .= self::getHtml($this->asDesc['description'], 'description');
$sRssFeedHeader .= self::getHtml('', 'atom:link', '', '', array('href'=>$this->asDesc['link'], 'rel'=>'self', 'type'=>'application/atom+xml'), true);
$sRssFeedHeader .= self::getHtml($this->asDesc['language'], 'language');
$sRssFeedHeader .= self::getHtml($this->getGlobalPubDate(), 'pubDate');
$sRssFeedHeader .= self::getHtml('Lutran.fr RSS Feed Generator', 'generator');
$sRssFeedHeader .= self::getHtml($this->asDesc['webmaster_mail'].' (Webmaster)', 'webMaster');
//feed items
$asSortedItems = $this->rSortTimeMatrix($this->asItems, 'pub_date');
$sItems = implode("\n", array_map(array($this, 'buildItem'), $asSortedItems));
//Global Feed
$sFeed = '<?xml version="1.0" encoding="'.Settings::TEXT_ENC.'" ?>';
$sFeed .= self::getHtml(self::getHtml($sRssFeedHeader.$sItems, 'channel'), 'rss', '', '', array('version'=>'2.0', 'xmlns:atom'=>'http://www.w3.org/2005/Atom'));
return $sFeed;
}
private static function getDate($sDate)
{
if(!is_numeric($sDate))
{
$sDate = strtotime($sDate);
}
return date('r', $sDate);
}
private function buildItem($asItem)
{
$sRssItem = self::getHtml(self::cleanRss($asItem['title']), 'title');
$sRssItem .= self::getHtml(self::cleanRss($asItem['author']), 'author');
$sRssItem .= self::getHtml($asItem['link'], 'link');
$sRssItem .= self::getHtml($asItem['category'], 'category');
$sRssItem .= self::getHtml(self::cleanRss($asItem['description'].'.'), 'description');
$sRssItem .= self::getHtml(self::getDate($asItem['pub_date']), 'pubDate');
$sRssItem .= self::getHtml($asItem['guid'], 'guid', '', '', array('isPermaLink'=>'true'));
return self::getHtml($sRssItem, 'item');
}
private static function getHtml($oText, $sTag, $sClass='', $sStyle='', $asExtraAttr=array(), $bAutoClose=false, $sInter='')
{
$sHtmlAttr = '';
if($sClass!='')
{
$asExtraAttr['class'] = $sClass;
}
if($sStyle!='')
{
$asExtraAttr['style'] = $sStyle;
}
foreach($asExtraAttr as $sAttrName=>$sAttrValue)
{
$sHtmlAttr .= ' '.$sAttrName.'="'.$sAttrValue.'"';
}
if($bAutoClose)
{
$sHtml = self::encapsulate('', "\n".'<'.$sTag.$sHtmlAttr, ' />');
}
else
{
$sHtml = self::encapsulate($oText, "\n".'<'.$sTag.$sHtmlAttr.'>', '</'.$sTag.'>', $sInter);
}
return $sHtml;
}
private static function cleanRss($oText)
{
$asForbiddenChars = array('&', '<', '>', '"', "'");
$asReplacementCode = array('&amp;', '&lt;', '&gt;', '&quot;', '&apos;');
if(!is_array($oText))
{
return str_replace($asForbiddenChars, $asReplacementCode, $oText);
}
elseif(count($oText)>0)
{
$oTextKeys = array_map(array($this, 'cleanRss'), array_keys($oText));
$oTextValues = array_map(array($this, 'cleanRss'), array_values($oText));
return array_combine($oTextKeys, $oTextValues);
}
else
{
return $oText;
}
}
private static function encapsulate($oText, $sPre='', $sPost=false, $sInter='')
{
if($sPost===false)
{
$sPost = $sPre;
}
if(is_array($oText))
{
$oText = implode($sPost.$sInter.$sPre, $oText);
}
return $sPre.$oText.$sPost;
}
private static function rSortTimeMatrix($asMatrix, $sTimeCol)
{
$asResult = array();
foreach($asMatrix as $iRowId=>$asLine) $asKeys[$iRowId] = strtotime($asLine[$sTimeCol]);
arsort($asKeys);
foreach($asKeys as $iRowId=>$iTimeStamp) $asResult[$iRowId] = $asMatrix[$iRowId];
return $asResult;
}
}
?>

235
inc/toolbox.php Executable file
View File

@@ -0,0 +1,235 @@
<?php
/**
* ToolBox - Only static functions missing from php librairy
* @author franzz
* @version 1.1
*/
class ToolBox
{
const MAIL_SUCCESS = 2;
public static function cleanPost(&$asData)
{
//get rid of magic quotes
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
{
$asData = self::cleanData($asData, 'stripslashes');
}
}
public static function cleanData($oData, $sCleaningFunc)
{
if(!is_array($oData))
{
return call_user_func($sCleaningFunc, $oData);
}
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);
}
}
public static function fixGlobalVars($argv)
{
//Add CLI arguments
if(defined('STDIN')) mb_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.(mb_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 Toolbox::mb_ucwords($acText);
}
// Go through all characters
$capitalizeNext = true;
$max = mb_strlen($acText);
for ($i = 0; $i < $max; $i++)
{
if(mb_strpos($sCharList, $acText[$i]) !== false)
{
$capitalizeNext = true;
}
elseif($capitalizeNext)
{
$capitalizeNext = false;
$acText[$i] = mb_strtoupper($acText[$i]);
}
}
return $acText;
}
/**
*
* @param String $sFromName
* @param String $sSubject
* @param String $sMessage
* @param String $sTo
* @param Array $asCc array(name => email)
* @param Boolean $bSelfMail
* @return mixed
*/
public function sendMail($sFromName, $sSubject, $sMessage, $sTo, $asCc=array(), $bSelfMail=true)
{
$asForm = array('api_key'=>Settings::MAIL_API_KEY,
'app'=>'Wedding',
'from_name'=>$sFromName,
'subject'=>$sSubject,
'msg'=>$sMessage,
'to_email'=>$sTo,
'cc_email'=>self::jsonConvert($asCc),
'self'=>$bSelfMail);
$oCurl = curl_init();
curl_setopt($oCurl, CURLOPT_URL, Settings::MAIL_SCRIPT);
curl_setopt($oCurl, CURLOPT_POST, true);
curl_setopt($oCurl, CURLOPT_HEADER, false);
curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($oCurl, CURLOPT_POSTFIELDS, $asForm);
$iResult = curl_exec($oCurl);
curl_close($oCurl);
return $iResult;
}
public static function jsonExport($asData)
{
header('Content-type: application/json');
//return htmlspecialchars(json_encode($asData), ENT_NOQUOTES);
return self::jsonConvert($asData);
}
public static function jsonConvert($asData)
{
return json_encode($asData);
}
public static function createThumbnail($sInPath, $iMaxWidth, $iMaxHeight, $sOutPath='', $bDeleteIn=false, $asImageExts=array('jpg', 'jpeg', 'gif', 'png'))
{
$asResult = array('error'=>'');
//Look up the extension to choose the image creator
//TODO use MIME types
$sInInfo = pathinfo($sInPath);
$sInName = mb_strtolower($sInInfo['basename']);
$sImageExt = mb_strtolower($sInInfo['extension']);
$sImageExt = ($sImageExt=='jpg')?'jpeg':$sImageExt;
//New Destination folder
if($sOutPath=='') $sOutPath = $sInPath;
elseif(mb_substr($sOutPath, -1)=='/') $sOutPath .= $sInName;
//New sizes
if(in_array($sImageExt, $asImageExts))
{
list($iWidth, $iHeight) = getimagesize($sInPath);
if($iWidth > $iMaxWidth || $iHeight > $iMaxHeight)
{
$dResizeDeltaWidth = $iWidth - $iMaxWidth;
$dResizeDeltaHeight = $iHeight - $iMaxHeight;
if($dResizeDeltaWidth > $dResizeDeltaHeight)
{
$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;
}
public static function utf8_compliant($sText)
{
if(strlen($sText) == 0) return true;
return (preg_match('/^.{1}/us', $sText, $ar) == 1);
}
public static function mb_ucwords($sText)
{
return mb_convert_case($sText, MB_CASE_TITLE, "UTF-8");
}
public static function file_get_contents_utf8($oFile)
{
$sContent = file_get_contents($oFile);
return mb_convert_encoding($sContent, 'UTF-8', mb_detect_encoding($sContent, 'UTF-8, ISO-8859-1', true));
}
public static function rgbToHex($R, $G, $B)
{
$R = dechex($R);
if(strlen($R)<2) $R='0'.$R;
$G = dechex($G);
if(strlen($G)<2) $G='0'.$G;
$B = dechex($B);
if(strlen($B)<2) $B='0'.$B;
return $R.$G.$B;
}
public static function setCookie($sCookieName, $sCookieValue, $iDays)
{
$iTimeLimit = time()+60*60*24*$iDays;
setcookie($sCookieName, $sCookieValue, $iTimeLimit);
}
}
?>

117
inc/translator.php Executable file
View File

@@ -0,0 +1,117 @@
<?php
/**
* Translator Class
* @author franzz
* @version 1.0
*/
class Translator extends PhpObject
{
private $sLang;
private $asLanguages;
private $asTranslations; // [lang][key_word] = translation
const LANG_FOLDER = 'languages/';
const LANG_EXT = '.lang';
const LANG_SEP = '=';
const DEFAULT_LANG = 'FR';
public function __construct($sLang='')
{
parent::__construct(__CLASS__, Settings::DEBUG);
$this->asLanguages = array();
$this->asTranslations = array();
$this->loadLanguages();
$this->setLanguage($sLang);
}
public function setLanguage($sLang)
{
$this->sLang = in_array($sLang, $this->asLanguages)?$sLang:self::DEFAULT_LANG;
}
public function getTranslation($sTransKey, $sLang='')
{
$sTransText = false;
//Select language
if($sLang=='')
{
$sLang = $this->sLang;
}
//Look up in the selected language dictionary
if(in_array($sLang, $this->asLanguages) && array_key_exists($sTransKey, $this->asTranslations[$sLang]))
{
$sTransText = $this->asTranslations[$sLang][$sTransKey];
}
//Look up in the default language dictionary
elseif(array_key_exists($sTransKey, $this->asTranslations[self::DEFAULT_LANG]))
{
$this->addWarning('Missing translation in "'.$sLang.'" for the key "'.$sTransKey.'", falling back to "'.self::DEFAULT_LANG.'"');
$sTransText = $this->asTranslations[self::DEFAULT_LANG][$sTransKey];
}
else $this->addWarning('Missing translation in "'.$sLang.'" for the key "'.$sTransKey.'"');
return $sTransText;
}
public function getHashToPage($asMenuPages)
{
$asHashToPage = array();
foreach($asMenuPages as $sHash)
{
foreach($this->asLanguages as $sLang)
{
$asHashToPage[$this->getTranslation('menu_'.$sHash.'_key', $sLang)] = $sHash;
}
}
return $asHashToPage;
}
public function getPageToHash($asMenuPages)
{
$asPageToHash = array();
foreach($asMenuPages as $sHash)
{
$asPageToHash[$sHash] = $this->getTranslation('menu_'.$sHash.'_key');
}
return $asPageToHash;
}
private function loadLanguages()
{
//List all available languages
$asLangPaths = glob(self::getLangPath('*'));
$this->asLanguages = array_map('basename', $asLangPaths, array_fill(1, count($asLangPaths), self::LANG_EXT));
//Load languages
array_walk($this->asLanguages, array($this, 'loadLanguageFile'));
}
private function loadLanguageFile($sLang)
{
if(!in_array($sLang, $this->asTranslations))
{
$sData = file_get_contents(self::getLangPath($sLang));
$asData = explode("\n", $sData);
foreach($asData as $sTranslation)
{
$iSepPos = stripos($sTranslation, self::LANG_SEP);
if($iSepPos!==false)
{
$sTransKey = trim(substr($sTranslation, 0, $iSepPos));
$sTransText = /*htmlspecialchars(*/trim(substr($sTranslation, $iSepPos+1))/*, ENT_QUOTES)*/; //TODO when all entities have been removed
$this->asTranslations[$sLang][$sTransKey] = $sTransText;
}
}
}
}
private static function getLangPath($sLang)
{
return self::LANG_FOLDER.$sLang.self::LANG_EXT;
}
}
?>

39
index.php Executable file
View File

@@ -0,0 +1,39 @@
<?php
/* Requests Handler */
//Start buffering
ob_start();
require_once 'config.php';
$oClassManagement = new ClassManagement('main');
ToolBox::cleanPost($_POST);
ToolBox::cleanPost($_GET);
ToolBox::cleanPost($_REQUEST);
ToolBox::fixGlobalVars(isset($argv)?$argv:array());
//Available variables
$sAction = isset($_GET['a'])?$_GET['a']:'';
$sPage = isset($_GET['p'])?$_GET['p']:'index';
$sLang = isset($_GET['l'])?$_GET['l']:(isset($_COOKIE['l'])?$_COOKIE['l']:'');
//...
//Initiate class
$oWedding = new Main($oClassManagement, $sLang);
switch($sAction)
{
case 'action':
break;
//...
default:
$sResult = $oWedding->getPage($sPage);
break;
}
//Log and clean buffer
$sDebug = ob_get_clean();
if(Settings::DEBUG && $sDebug!='') dlog($sDebug, true);
echo $sResult;
?>

4
script/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

22
settings.php Executable file
View File

@@ -0,0 +1,22 @@
<?php
class Settings
{
const LOC_API_KEY = '1cfb97eb3c88913653f3d5bc0096e92c2e7edc523712d2bf1bcf49946571951a';
const MAIL_SCRIPT = 'http://francois.lutran.fr/send_mail.php';
const CONSUMER_KEY = 'JEZlzGK7x6Evg5ShlVHiA';
const CONSUMER_SECRET = 'khD9ljSQtJlluiemyAgbVISnb0Kl8d22Ir34ftfQX0';
const OAUTH_TOKEN = '1531614350-XnXaDmmj0qCiHh2ffDGtiwZR4RxOZ9SqXplaE8S';
const OAUTH_TOKEN_SECRET = 'otz0XQsWoSTywfHCI49QuVEOcZjvNGrgVwM7uDM';
const MAIL_API_KEY = '8D98B36BB558BC6771324AEFB9E37';
const DB_SERVER = 'localhost';
const DB_LOGIN = 'root';
const DB_PASS = '0nadmin';
const DB_NAME = '';
const DB_ENC = 'utf8mb4';
const TEXT_ENC = 'UTF-8';
const TIMEZONE = 'Europe/Paris';
const DEBUG = true;
}
?>

436
standalone/cerberus.php Executable file
View File

@@ -0,0 +1,436 @@
<?php
/* Main (Exemple) */
session_start();
//session_destroy();
pre($_COOKIE, 'Cookie');
pre($_SESSION, 'Session');
pre($_REQUEST, 'Request');
//default values of reserved POST keys
$sLogin = array_key_exists('login', $_POST)?$_POST['login']:'';
$sPass = array_key_exists('pass', $_POST)?$_POST['pass']:'';
$sPage = array_key_exists('p', $_REQUEST)?$_REQUEST['p']:'';
$sAction = array_key_exists('a', $_POST)?$_POST['a']:'';
$sPostToken = array_key_exists('post_token', $_POST)?$_POST['post_token']:'';
$oMySql = new MySqlManager();
$oCerberus = new Cerberus($oMySql, array(Cerberus::OPTION_AUTO_LOGON=>true, Cerberus::OPTION_RENEW_TOKEN=>true));
//logging In / Out
if($sAction=='logout')
{
$oCerberus->logMeOut();
}
else/*if(($sLogin=='' && $sPass=='') || $oCerberus->checkPostToken($sPostToken))*/
{
$oCerberus->logMeIn($sLogin, $sPass);
}
/*else
{
echo 'pouet';
}*/
$sLayout = $sMenu = '';
if($oCerberus->isLogguedIn())
{
$sMenu = '<form method="post"><input type="submit" name="a" value="logout">Log out</a><hr /></form>';
$sLayout = 'Loggued In. '.$oCerberus->getNewPostToken();
}
else
{
$sLayout = '<form name="login" method="post">
Login&nbsp;<input type="text" name="login" />
pass&nbsp;<input type="text" name="pass" />
<input type="hidden" name="post_token" value="'.$oCerberus->getNewPostToken().'" />
<input type="submit" value="ok" />
</form>';
}
$sErrors = $oCerberus->getCleanMessages();
echo '<html><head><title>Cerberus</title></head><body>'.$sMenu."\n".$sLayout.'<br />'.$sErrors.'</body></html>';
pre('new session post token : '.$_SESSION[Cerberus::SESSION_POST_TOKEN]);
/* Class */
/* Requirements */
require_once 'functions.php';
require_once 'php_object.php';
require_once 'mysql_manager.php';
/**
* Cerberus
* Access control class
* @author FranzZ
*
* Requirements:
* Database with DB_TABLE_USER table and fields:
* - DB_FIELD_ID_USER
* - DB_FIELD_LOGIN
* - DB_FIELD_PASS
* - DB_FIELD_TOKEN
*
* Setup:
* - Replace required tables and fields names with the mysql manager constants
* - Set options :
* - Cerberus::OPTION_AUTO_LOGON
* - Cerberus::OPTION_RENEW_TOKEN
*/
class Cerberus extends PhpObject
{
// Database
private $oMySql;
const DB_TABLE_USER = MySqlManager::USER_TABLE;
const DB_FIELD_ID_USER = 'id_user';
const DB_FIELD_LOGIN = 'user';
const DB_FIELD_PASS = 'pass';
const DB_FIELD_TOKEN = 'token';
//Session
const SESSION_ID_USER = self::DB_FIELD_ID_USER;
const SESSION_LOGIN = self::DB_FIELD_LOGIN;
const SESSION_TOKEN = self::DB_FIELD_TOKEN;
const SESSION_POST_TOKEN = 'post_token';
//Cookie
const COOKIE_ID_USER = self::DB_FIELD_ID_USER;
const COOKIE_TOKEN = self::DB_FIELD_TOKEN;
const COOKIE_POST_TOKEN = self::SESSION_POST_TOKEN;
//Options
const OPTION_AUTO_LOGON = 'auto_logon';
const OPTION_RENEW_TOKEN = 'renew_token';
public $abOptions;
//Session Variables
private $iUserId;
private $sLogin;
private $sToken;
private $sPostToken;
public function __construct(&$oMySql, $abOptions)
{
parent::__construct();
$this->iUserId = $this->sLogin = $this->sToken = $this->sPostToken = false;
$this->oMySql = $oMySql;
$this->setOptions($abOptions);
$this->syncSession();
}
private function setOptions($abOptions)
{
//default values
$this->abOptions = array(self::OPTION_AUTO_LOGON=>false, self::OPTION_RENEW_TOKEN=>true);
$this->abOptions = array_merge($this->abOptions, $abOptions);
}
private function getOption($sOptionName)
{
return $this->abOptions[$sOptionName];
}
public function getUserId()
{
return $this->iUserId;
}
private function syncSession()
{
if(isset($_SESSION[self::SESSION_ID_USER]))
{
$this->iUserId = $_SESSION[self::SESSION_ID_USER];
}
if(isset($_SESSION[self::SESSION_LOGIN]))
{
$this->sLogin = $_SESSION[self::SESSION_LOGIN];
}
if(isset($_SESSION[self::SESSION_TOKEN]))
{
$this->sToken = $_SESSION[self::SESSION_TOKEN];
}
if(isset($_SESSION[self::SESSION_POST_TOKEN]))
{
$this->sPostToken = $_SESSION[self::SESSION_POST_TOKEN];
}
}
public function register($asData)
{
//data to register
//TODO To be customized
$sLogin = strtolower(trim($asData[self::DB_FIELD_LOGIN]));
$sPass = $asData[self::DB_FIELD_PASS];
if($sLogin=='' || $sPass=='')
{
$this->addError('Empty mandatory fields (Nickname or password)');
}
elseif(htmlspecialchars($sLogin, ENT_QUOTES)!=$sLogin)
{
$this->addError('Nickname: HTML characters are forbidden');
}
elseif($this->checkAccount($sLogin))
{
$this->addError('Nickname: There is already a user called by that name, choose a different one');
}
else
{
$asData[self::DB_FIELD_LOGIN] = $sLogin;
$asData[self::DB_FIELD_PASS] = self::encryptPassword($sPass);
$this->oMySql->insertRow(self::DB_TABLE_USER, $asData);
return $this->logMeIn($sLogin, $sPass);
}
return false;
}
public function logMeIn($sLogin='', $sPass='')
{
$bResult = false;
$bFirstLogin = true;
if($sLogin=='' || $sPass=='')
{
$bFirstLogin = false;
if($this->iUserId && $this->sLogin && $this->sToken && $this->checkToken())
{
//log in with session variables
$iUserId = $this->iUserId;
$sLogin = $this->sLogin;
$sToken = $this->sToken;
$bResult = true;
}
elseif($this->getOption(self::OPTION_AUTO_LOGON) && $this->checkToken(true))
{
//log in with cookies
$iUserId = $_COOKIE[self::COOKIE_ID_USER];
$sLogin = $this->oMySql->selectValue(self::DB_TABLE_USER, self::DB_FIELD_LOGIN, $iUserId);
$sToken = $_COOKIE[self::COOKIE_TOKEN];
$bResult = true;
}
else
{
$this->addWarning('No login info (cookie / session)');
}
}
else
{
$asUser = $this->getUser($sLogin);
if(!$asUser)
{
$this->addError('Unknown user');
}
elseif(!$this->checkPassword($sPass, $asUser[self::DB_FIELD_PASS]))
{
$this->addError('Incorrect password');
}
else
{
$iUserId = $asUser[self::DB_FIELD_ID_USER];
$sToken = $asUser[self::DB_FIELD_TOKEN];
$bResult = true;
}
}
if($bResult)
{
//Class
$this->iUserId = $iUserId;
$this->sLogin = $sLogin;
$this->sToken = $sToken;
//Session
$_SESSION[self::SESSION_ID_USER] = $iUserId;
$_SESSION[self::SESSION_LOGIN] = $sLogin;
$_SESSION[self::SESSION_TOKEN] = $sToken;
//Cookie (doesn't leave any password nor login on user's computer)
self::setCookie(self::COOKIE_ID_USER, $iUserId);
self::setCookie(self::COOKIE_TOKEN, $sToken);
//reset pass
if($bFirstLogin || $this->getOption(self::OPTION_RENEW_TOKEN))
{
$this->resetToken();
}
}
else
{
$this->logMeOut();
}
return $bResult;
}
public function isLogguedIn()
{
$bLogguedIn = false;
if($this->iUserId && $this->sLogin && $this->sToken)
{
//check if token is set and valid
if($this->checkToken())
{
//Check if user got a actual account in the database
$bLogguedIn = $this->checkAccount($this->sLogin, $this->iUserId);
}
else
{
$this->addError('Authentication problem, please sign in again');
}
}
/*
echo "[TEST]<br />check token :
<br />db token ", $this->iUserId." - ".$this->getDbToken($this->iUserId),"
<br />session token ", $_SESSION[self::SESSION_TOKEN], "
<br />class token ", $this->sToken, "
<br />cookie token ", $_COOKIE[self::COOKIE_TOKEN], '<br />[/TEST]';
*/
return $bLogguedIn;
}
public function logMeOut()
{
//Database
if($this->iUserId)
{
$this->oMySql->updateRow(self::DB_TABLE_USER, $this->iUserId, array(self::DB_FIELD_TOKEN=>''));
}
//Class variables
$this->iUserId = $this->sLogin = $this->sToken = $this->sPostToken = false;
//Cookie
self::setCookie(self::COOKIE_TOKEN, '', -1);
self::setCookie(self::COOKIE_ID_USER, '', -1);
//Server session
$_SESSION = array();
return session_destroy();
}
private function checkAccount($sUserName, $iUserId=0)
{
$asConstraints = array(self::DB_FIELD_LOGIN=>$sUserName);
if($iUserId>0)
{
$asConstraints[self::DB_FIELD_ID_USER] = $iUserId;
}
return $this->oMySql->selectValue(self::DB_TABLE_USER, 'COUNT(1)', $asConstraints);
}
private function getUser($oUser)
{
$sField = is_numeric($oUser)?self::DB_FIELD_ID_USER:self::DB_FIELD_LOGIN;
return $this->oMySql->selectRow(self::DB_TABLE_USER, array($sField=>$oUser));
}
public static function encryptPassword($sPass)
{
$sRandomText = 'F_RA-1H"2{bvj)5f?0sd3r#fP,K]U|w}hGiN@(sZ.sDe!7*x/:Mq+&';
for($iIndex=0; $iIndex < strlen($sPass); $iIndex++)
{
$sPass[$iIndex] = $sRandomText[$iIndex%strlen($sRandomText)] ^ $sPass[$iIndex];
}
return md5($sPass);
}
private static function createToken()
{
return self::encryptPassword( $_SERVER['HTTP_USER_AGENT'].
$_SERVER['REMOTE_ADDR'].
$_SERVER['REQUEST_TIME'].
strstr(microtime(), ' ', true).
$_SERVER['SERVER_SIGNATURE'].
$_SERVER['SERVER_ADMIN']);
}
private function resetToken()
{
//new token
$sToken = $this->createToken();
//set database token
$this->oMySql->updateRow(self::DB_TABLE_USER, $this->iUserId, array(self::DB_FIELD_TOKEN=>$sToken));
//set session token
$_SESSION[self::SESSION_TOKEN] = $sToken;
$this->sToken = $sToken;
//set cookie token
self::setCookie(self::COOKIE_TOKEN, $sToken);
}
public static function setCookie($sCookieName, $oCookieValue, $iTime=1)
{
setcookie($sCookieName, $oCookieValue, time()+60*60*24*$iTime);
$_COOKIE[$sCookieName] = $oCookieValue;
}
private function checkToken($bCookieCheck=false)
{
$bTokenOk = $iUserId = $sToken = false;
//Cookie check
if($bCookieCheck && array_key_exists(self::COOKIE_ID_USER, $_COOKIE) && array_key_exists(self::COOKIE_TOKEN, $_COOKIE))
{
$iUserId = $_COOKIE[self::COOKIE_ID_USER];
$sToken = $_COOKIE[self::COOKIE_TOKEN];
}
//Session check
elseif(!$bCookieCheck && $this->iUserId && $this->sToken !== false)
{
$iUserId = $this->iUserId;
$sToken = $this->sToken;
}
if($iUserId && $sToken)
{
$sDbPass = $this->getDbToken($bCookieCheck?$_COOKIE[self::COOKIE_ID_USER]:$this->iUserId);
$bTokenOk = ($sDbPass == $_COOKIE[self::COOKIE_TOKEN] && ($sDbPass == $this->sToken || $bCookieCheck));
}
return $bTokenOk;
}
private function getDbToken($iUserId)
{
$sPass = false;
if($iUserId !== false)
{
$sPass = $this->oMySql->selectValue(self::DB_TABLE_USER, self::DB_FIELD_TOKEN, $iUserId);
}
return $sPass;
}
public function getNewPostToken()
{
$sToken = self::createToken();
$this->sPostToken = $sToken;
$_SESSION[self::SESSION_POST_TOKEN] = $sToken;
return $sToken;
}
public function checkPostToken($sPostToken)
{
pre(array('Posted'=>$sPostToken, 'Class'=>$this->sPostToken, 'Session'=>$_SESSION[self::SESSION_POST_TOKEN]), 'check posted token');
$bPostTokenOk = ($this->sPostToken && $sPostToken!='' && $sPostToken == $this->sPostToken);
$this->sPostToken = '';
$_SESSION[self::SESSION_POST_TOKEN] = '';
return $bPostTokenOk;
}
private static function checkPassword($sClearPass, $sEncodedPass)
{
return self::encryptPassword($sClearPass) == $sEncodedPass;
}
public function getCleanMessages($sType=parent::ALL_TAB)
{
return $this->getCleanMessageStacks(array($this->oMySql), $sType);
}
}
?>

21
standalone/colors.php Executable file
View File

@@ -0,0 +1,21 @@
<?php
$iMin = 0;
$iMax = 256;
$iStep = 20;
$iBoxWidth = 10;
echo '<html><head><title>Colors</title></head><body><table style="border:0;">';
for($i=$iMin;$i<$iMax;$i+=$iStep)
{
for($j=$iMin;$j<$iMax;$j+=$iStep)
{
echo '<tr>';
for($k=$iMin;$k<$iMax;$k+=$iStep)
{
echo '<td style="width:'.$iBoxWidth.'px;height:'.$iBoxWidth.'px;background:rgb('.$i.','.$j.','.$k.')"></td>';
}
echo '</tr>';
}
}
echo '</table><body></html>';

14
standalone/image.php Executable file
View File

@@ -0,0 +1,14 @@
<?php
header("Content-type: image/png");
$iHeight = 150;
$iWidth = 200;
$im = @imagecreate($iWidth, $iHeight) or die("Cannot Initialize new GD image stream");
$background_color = imagecolorallocate($im, 145, 145, 145);
$text_color = imagecolorallocate($im, 255, 255, 255);
imagestring($im, 4, 5, $iHeight-20, "Picture 12", $text_color);
imagepng($im);
imagedestroy($im);
?>

View File

View File

@@ -0,0 +1,3 @@
german
xxx
pr0n

View File

@@ -0,0 +1,119 @@
<?php
//Anti Spam List
$sMovieList = '';
if(file_exist('movie_list')) $sMovieList = file_get_contents('movie_list');
if(substr($sMovieList, 0, 8) != date('Ymd')) file_put_contents('movie_list', '');
$asMovieList = array_shift(explode("\n", $sMovieList));
//Black List
$sBlTitleContent = file_get_contents('bl_title');
$sBlDescContent = file_get_contents('bl_desc');
$asBlTitle = explode("\n", $sBlTitleContent);
$asBlDesc = explode("\n", $sBlTitleContent);
$asChannels = array('alt.binaries.hdtv.x264', 'alt.binaries.movies', 'alt.binaries.sleazemovies');
foreach($asChannels as $iChanKey=>$sChannel)
{
//Extract file
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://rss.binsearch.net/rss.php?max=300&g='.$sChannel);
curl_setopt($ch, CURLOPT_HEADER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_ENCODING , "gzip");
$sRssIn = curl_exec($ch);
curl_close($ch);
//Rss Feed Input
$sRssIn = str_replace("\n", '', $sRssIn);
//Rss Feed Output
$sRssOut = '';
//Slice Rss feed into items
preg_match_all("/\<item\>(.+)\<\/item\>/U", $sRssIn, $asItems);
//print_r($asItems);die();
foreach($asItems[1] as $iItemKey=>$sItem)
{
//Slice item into tags
preg_match_all("/\<(?P<tag>\w+)\>(?P<text>.+)\<\/(?P<tag_fin>\w+)\>/U", $sItem, $asTags);
//print_r($asTags);die();
/*
[0] => Array
(
[0] => <title>dc96773fb88f2f75d581194a4320fedc[76/79] - "15321568f277a26d326baddfb33d62621fe93693187c474f8cac0fb13a0d5b8f.0" yEnc (1/1)</title>
[1] => <description>&lt;table border width="75%" style="border: solid 1px"&gt;&lt;tr&gt;&lt;td width="25%"&gt;Group:&lt;td&gt;alt.binaries.hdtv.x264&lt;tr&gt;&lt;td&gt;Subject:&lt;td&gt;dc96773fb88f2f75d581194a4320fedc[76/79] - "15321568f277a26d326baddfb33d62621fe93693187c474f8cac0fb13a0d5b8f.0" yEnc (1/1)&lt;tr&gt;&lt;td&gt;Poster:&lt;td&gt;Yenc@power-post.org (Yenc-PP-A&amp;amp;A)&lt;tr&gt;&lt;td&gt;Details:&lt;td&gt;&lt;span class="d"&gt;&lt;br&gt;&lt;a href="http://www.binsearch.info/?b=15321568f277a26d326baddfb33d62621fe93693187c474f8cac0fb13a0d5b8f&amp;amp;g=alt.binaries.hdtv.x264&amp;amp;p=Yenc%40power-post.org+%28Yenc-PP-A%26A%29&amp;amp;max=250"&gt;collection&lt;/a&gt; size: 2.35&amp;nbsp;MB, parts available: 7 / 7&lt;br&gt;- 2 par2 files&lt;br&gt;- 1 split file&lt;br&gt;- 1 other file&lt;br&gt;&lt;/span&gt;&lt;/table&gt;</description>
[2] => <pubDate>Thu, 03 Jan 2013 15:31:53 GMT</pubDate>
[3] => <link>http://www.binsearch.info/?action=nzb&amp;97515747=1</link>
)
[tag] => Array
(
[0] => title
[1] => description
[2] => pubDate
[3] => link
)
[text] => Array
(
[0] => dc96773fb88f2f75d581194a4320fedc[76/79] - "15321568f277a26d326baddfb33d62621fe93693187c474f8cac0fb13a0d5b8f.0" yEnc (1/1)
[1] => &lt;table border width="75%" style="border: solid 1px"&gt;&lt;tr&gt;&lt;td width="25%"&gt;Group:&lt;td&gt;alt.binaries.hdtv.x264&lt;tr&gt;&lt;td&gt;Subject:&lt;td&gt;dc96773fb88f2f75d581194a4320fedc[76/79] - "15321568f277a26d326baddfb33d62621fe93693187c474f8cac0fb13a0d5b8f.0" yEnc (1/1)&lt;tr&gt;&lt;td&gt;Poster:&lt;td&gt;Yenc@power-post.org (Yenc-PP-A&amp;amp;A)&lt;tr&gt;&lt;td&gt;Details:&lt;td&gt;&lt;span class="d"&gt;&lt;br&gt;&lt;a href="http://www.binsearch.info/?b=15321568f277a26d326baddfb33d62621fe93693187c474f8cac0fb13a0d5b8f&amp;amp;g=alt.binaries.hdtv.x264&amp;amp;p=Yenc%40power-post.org+%28Yenc-PP-A%26A%29&amp;amp;max=250"&gt;collection&lt;/a&gt; size: 2.35&amp;nbsp;MB, parts available: 7 / 7&lt;br&gt;- 2 par2 files&lt;br&gt;- 1 split file&lt;br&gt;- 1 other file&lt;br&gt;&lt;/span&gt;&lt;/table&gt;
[2] => Thu, 03 Jan 2013 15:31:53 GMT
[3] => http://www.binsearch.info/?action=nzb&amp;97515747=1
*/
//Extract item's tag names
foreach($asTags['tag'] as $iTagKey=>$sTageName)
{
$asTagIndex[$sTageName] = $iTagKey;
}
$sTitle = $asTags['text'][$asTagIndex['title']];
$sDesc = $asTags['text'][$asTagIndex['description']];
//Validator
$bValid = true;
//Check Poster
//preg_match('/Poster\:\&lt\;td\&gt\;(?P<address>\S*)\ \((?P<user>\S*)\)/i', $sTitle, $as);
foreach($asBlTitle as $sBlWord)
{
preg_match('/'.preg_quote($sBlWord).'/i', $sTitle, $asFoundBlWord);
if(count($asFoundBlWord) != 0) $bValid = false;
}
foreach($asBlDesc as $sBlWord)
{
preg_match('/'.preg_quote($sBlWord).'/i', $sDesc, $asFoundBlWord);
if(count($asFoundBlWord) != 0) $bValid = false;
}
//Check movie quality
preg_match('/1080p/i', $sTitle, $asQuality);
if(count($asQuality) == 0) $bValid = false;
//Jul - Remove German movies
//preg_match('/german/i', $sTitle, $asLang);
//if(count($asLang) != 0) $bValid = false;
//Check Series
preg_match('/s([0-9]{1,2})e([0-9]{2})/i', $sTitle, $asSeries);
if(count($asSeries) != 0) $bValid = false;
if($bValid) $asValidItems[] = $asItems[0][$iItemKey];
}
}
//rebuild RSS feed
date_default_timezone_set('Europe/Paris');
echo '<?xml version="1.0" encoding="utf-8"?><rss version="2.0">'.
'<channel>'.
'<title>'.implode(', ', $asChannels).'</title>'.
'<link>http://www.binsearch.info/</link>'.
'<description>Latest newsgroup posts as indexed by BinSearch.info</description>'.
'<copyright>This RSS collection is copyright (c) BinSearch team. Commercial use prohibited. This collection is generated by an automated process based on the posts found in global Usenet newsgroups. The posters retain copyright over their individual posts.</copyright>'.
'<lastBuildDate>'.date('r').'</lastBuildDate>'.
implode("\n\t\t", $asValidItems).
'</channel>'.
'</rss>';
?>

110
standalone/send_mail.php Executable file
View File

@@ -0,0 +1,110 @@
<?php
ini_set('default_charset', 'UTF-8');
header('Content-Type: text/html; charset='.'UTF-8');
mb_internal_encoding('UTF-8');
mb_http_output('UTF-8');
mb_http_input('UTF-8');
mb_language('uni');
mb_regex_encoding('UTF-8');
//Main
$sApiKey = isset($_POST['api_key'])?$_POST['api_key']:'';
$sApp = isset($_POST['app'])?$_POST['app']:'lutran.fr';
$sFromName = isset($_POST['from_name'])?$_POST['from_name']:'';
$sFromEmail = isset($_POST['from_email'])?$_POST['from_email']:'www-data@lutran.fr';
$sSubject = isset($_POST['subject'])?$_POST['subject']:'';
$sMsg = isset($_POST['msg'])?$_POST['msg']:'';
$sToEmail = isset($_POST['to_email'])?$_POST['to_email']:'';
$asCc = isset($_POST['cc_email'])?json_decode($_POST['cc_email'], true):'';
$bSelfMail = isset($_POST['self'])?$_POST['self']:true;
$asAuthorizedApi = array('Wedding'=>'8D98B36BB558BC6771324AEFB9E37');
if(array_key_exists($sApp, $asAuthorizedApi) && $sApiKey = $asAuthorizedApi[$sApp])
{
$sResult = sendEmail($sApp, $sFromName, $sFromEmail, $sSubject, $sMsg, $sToEmail, $asCc, $bSelfMail);
}
else $sResult = 1;
echo $sResult;
//Functions
function sendEmail($sApp, $sFromName, $sFromEmail, $sSubject, $sMsg, $sToEmail, $asCc, $bSelfMail)
{
$sResult = 0;
if($sFromName!='' && $sFromEmail!='' && $sSubject!='' && $sMsg!='' && $sToEmail!='')
{
//Message
$sHtmlMessage = '';
if($bSelfMail)
{
$sHtmlMessage = 'From: '.$sFromName."<br />".
'Email: '.$sFromEmail."<br /><br />".
'Subject: '.$sSubject."<br />".
'Message: <br /><br />';
$sFromName = $sApp;
$sSubject = $sApp.' - Contact';
}
$sHtmlMessage .= str_replace("\n", '<br />', $sMsg);
$sPlainMessage = strip_tags(str_replace('<br />', "\n", $sHtmlMessage));
//Email
$iBoundary = uniqid("HTMLEMAIL");
$sCc = empty($asCc)?'':('Cc: '.implodeAll($asCc, ' <', "\r\n, ", '', '>')."\r\n");
$sHeaders = 'From: '.$sFromName.' <www-data@lutran.fr>'."\r\n".
'Reply-To: '.$sFromName.' <www-data@lutran.fr>'."\r\n".
$sCc.
'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));
//Store in case email fails
//@file_put_contents('log.html', '<br />----<br /><br />'.$sHtmlMessage, FILE_APPEND);
//Send
if(mail($sToEmail, $sSubject, '', $sHeaders))
{
$sResult = 2;
}
else
{
$sResult = 3;
}
}
else
{
$sResult = 4;
}
return $sResult;
}
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);
}
?>

78
standalone/test.php Executable file

File diff suppressed because one or more lines are too long

83
standalone/upload.php Normal file
View File

@@ -0,0 +1,83 @@
<?php
function combinedImplode($asPieces, $sKeyValGlue='', $sRowGlue='')
{
$asResult = array();
foreach($asPieces as $sKey=>$sValue)
{
$asResult[] = is_array($sValue)?combinedImplode($sValue, $sKeyValGlue, $sRowGlue):$sKey.$sKeyValGlue.$sValue;
}
return implode($sRowGlue, $asResult);
}
function getSabContent($sSabServer, $asParams)
{
$sQueueUrl = $sSabServer.'?'.combinedImplode($asParams, '=', '&');
return json_decode(file_get_contents($sQueueUrl), true);
}
$sUploadResult = $sQueueResult = $sHistoryResult = '';
if(isset($_GET['api']) && $_GET['api']=='123456')
{
$sSabServer = 'http://192.168.0.2:8085/sabnzbd/api';
$asCommonParams = array('output'=>'json', 'apikey'=>'d93d02d23510871b0252fe282a0f591c');
$asQueueParams = $asCommonParams + array('mode'=>'queue', 'start'=>0, 'limit'=>1);
$asHistoryParams = $asCommonParams + array('mode'=>'history', 'start'=>0, 'limit'=>3);
//Displaying current download
$asQueueResult = getSabContent($sSabServer, $asQueueParams);
if(count($asQueueResult['queue']['slots'])==0) $sQueueResult = 'Empty queue';
else
{
$asFile = $asQueueResult['queue']['slots'][0];
$sQueueResult = 'Downloading '.$asFile['filename'].' ('.$asFile['size'].') ';
$sQueueResult.= 'at '.$asQueueResult['queue']['speed'].'. File expected at ';
$sQueueResult.= $asFile['eta'].' ('.$asFile['sizeleft'].' / '.$asFile['timeleft'].' left)';
}
//Displaying history
$asHistoryResult = getSabContent($sSabServer, $asHistoryParams);
if(count($asHistoryResult['history']['slots'])==0) $asHistoryResult = 'Empty history';
else
{
foreach($asHistoryResult['history']['slots'] as $asFile)
{
$sHistoryResult .= '<li>'.$asFile['name'].' ('.$asFile['size'].') ';
if($asFile['status']=='Failed') $sHistoryResult.= 'failed to be downloaded ("'.$asFile['fail_message'].'")';
else $sHistoryResult.= 'has been downloaded with success';
$sHistoryResult .= '</li>';
}
}
//Uploading file
$sUploadResult = '';
if(array_key_exists('upload', $_FILES) && strtolower(substr($_FILES['upload']['name'], -4))=='.nzb')
{
$sWatchDir = "/tmp/downloads/watchdir/";
$sPath = $sWatchDir.basename($_FILES['upload']['name']);
$ok=1;
if(move_uploaded_file($_FILES['upload']['tmp_name'], $sPath))
{
$sUploadResult = "The file ". basename( $_FILES['upload']['name']). " has been uploaded";
}
else $sUploadResult = "Sorry, there was a problem copying your file.";
}
}
else $sUploadResult = 'Missing API key';
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Add to NZB</title>
</head>
<body>
<form enctype="multipart/form-data" action="upload.php" method="POST">
Add to NZB: <input name="upload" type="file" />&nbsp;<input type="submit" value="Upload" />
</form>
<p class="result"><?php echo $sUploadResult; ?></p>
<p class="queue"><?php echo $sQueueResult; ?></p>
<p class="history"><ul><?php echo $sHistoryResult; ?></ul></p>
</body>
</html>