From cc58284478025f628e89ce17809521ddf08315bc Mon Sep 17 00:00:00 2001 From: Franzz Date: Mon, 24 May 2021 21:47:32 +0200 Subject: [PATCH] Minor fixes --- inc/db.php | 80 ++++++++++++++--------------- inc/rss.php | 68 ++++++++++++------------- inc/toolbox.php | 130 ++++++++++++++++++++++++------------------------ 3 files changed, 138 insertions(+), 140 deletions(-) diff --git a/inc/db.php b/inc/db.php index 71ca973..3c1a97a 100644 --- a/inc/db.php +++ b/inc/db.php @@ -12,7 +12,7 @@ class Db extends PhpObject const DB_NO_DATA = 'ERR_2'; const DB_NO_TABLE = 'ERR_3'; const ID_TAG = 'id_'; - + //Database formats const MONTH_FORMAT = 'Ym'; const DATE_FORMAT = 'Y-m-d'; @@ -20,7 +20,7 @@ class Db extends PhpObject public $sDbState; private $bTrace; - + /** * SQL connection Handle * @var mysqli @@ -28,7 +28,7 @@ class Db extends PhpObject private $oConnection; private $sDatabase; private $asOptions; - + /** * Tables & fields descriptions * array( 'tables'=>array('table_name1'=>array('table_field1', 'table_field2', ...), 'table_name2'=>array(...)), @@ -93,7 +93,7 @@ class Db extends PhpObject $this->bTrace = $bTrace; //if($bTrace) $this->setDebug(true); } - + public function getTrace() { return $this->bTrace; @@ -114,10 +114,10 @@ class Db extends PhpObject //Create tables @array_walk($this->getInstallQueries(), array($this, 'setQuery')); } - + public function getBackup() { $sBackupFile = uniqid('backup_').'.sql'; - + $sAppPath = ''; if(strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') $sAppPath = 'C:\ProgramData\xampp\mysql\bin\\'; exec($sAppPath.'mysqldump --user='.Settings::DB_LOGIN.' --password='.Settings::DB_PASS.' '.Settings::DB_NAME.' --add-drop-table --result-file='.$sBackupFile); @@ -128,7 +128,7 @@ class Db extends PhpObject } else return false; } - + public function restoreBackup($sBackupFile) { $sAppPath = ''; if(file_exists($sBackupFile)) { @@ -137,11 +137,11 @@ class Db extends PhpObject } else return false; } - + public function loadFile($sFilePath) { set_time_limit(0); $bResult = false; - + if(file_exists($sFilePath)) { $sContent = file_get_contents($sFilePath); @@ -162,7 +162,7 @@ class Db extends PhpObject $bResult = false; break; } - + $bResult = true; $sSql = ''; } @@ -172,7 +172,7 @@ class Db extends PhpObject else $this->addError('File is empty: '.basename($sFilePath)); } else $this->addError('File not found: '.$sFilePath); - + return $bResult; } @@ -234,7 +234,7 @@ class Db extends PhpObject } return $oResult; } - + public function getLastError() { return $this->oConnection->error; @@ -302,12 +302,12 @@ class Db extends PhpObject $asTableIds = array_map(array('self', 'getId'), $asTables); return in_array($sColumnName, $asTableIds); } - + private function isField($sTableFieldName) { $asPath = explode('.', str_replace('`', '', $sTableFieldName)); return ( - is_array($asPath) + is_array($asPath) && count($asPath)==2 && $this->isColumnInTable($asPath[0], $asPath[1]) ); @@ -328,17 +328,17 @@ class Db extends PhpObject public function getTablecolumns($sTableName, $bTypes=true) { 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'; - + if(!$bTypes) return $asTableColumns; - + $asTableName = array_fill(0, count($asTableColumns), $sTableName); return array_combine($asTableColumns, array_map(array('self', 'getColumnType'), $asTableColumns, $asTableName)); } - + public function isColumnInTable($sTableName, $sColName) { $asCols = $this->getTablecolumns($sTableName, false); return ($asCols && in_array($sColName, $asCols)); @@ -383,7 +383,7 @@ class Db extends PhpObject private function addQuotes($oData) { //TODO remake - $asTrustedFunc = array('CURDATE()', 'NOW()'); + $asTrustedFunc = array('CURDATE()', 'NOW()', 'NULL'); $sChar = "'"; if(is_array($oData)) { @@ -401,7 +401,7 @@ class Db extends PhpObject { return $this->oConnection->insert_id; } - + private function getLastImpact() { return ($this->oConnection->affected_rows > 0); @@ -428,7 +428,7 @@ class Db extends PhpObject { $asConstraints = array($this->getId($sTableName)=>$asConstraints); } - + //Cleaning values $this->cleanSql($sTableName); $this->cleanSql($asData); @@ -437,7 +437,7 @@ class Db extends PhpObject $asConstraintsValues = $this->addQuotes($asConstraints); $this->addColumnSelectors($asQueryValues); $this->addColumnSelectors($asConstraintsValues); - + //Building query if(!$bLedUpdate) $asQueryValues['led'] = 'led'; $sLimit = $iLimit>0?" LIMIT $iLimit":""; @@ -494,7 +494,7 @@ class Db extends PhpObject $this->cleanSql($iTableId); $bSuccess = true; - + //linked tables switch($sTableName) { @@ -516,13 +516,13 @@ class Db extends PhpObject } return $bSuccess; } - + public function emptyTable($sTableName) { $this->cleanSql($sTableName); return $this->setQuery("TRUNCATE ".$sTableName); } - + public function selectList($sTableName, $sColumnName='', $asConstraints=array()) { $sColumnName = $sColumnName==''?self::getText($sTableName):$sColumnName; @@ -533,7 +533,7 @@ class Db extends PhpObject true, $sIdColumnName); } - + public function selectRows($asInfo, $sGroupBy='', $bStringOnly=true) { $asAttributes = array('select'=>"SELECT", 'from'=>"FROM", 'join'=>"LEFT JOIN", 'joinOn'=>"LEFT JOIN", 'constraint'=>"WHERE", 'groupBy'=>"GROUP BY", 'orderBy'=>"ORDER BY", 'limit'=>'LIMIT'); @@ -543,16 +543,16 @@ class Db extends PhpObject //Simple selectRows if(!is_array($asInfo)) $asInfo = array('from'=>$asInfo); - + //Get table by key if($sGroupBy===true) { $sGroupBy = self::getId($asInfo['from']); - + //Add id to selection if(isset($asInfo['select']) && $asInfo['select'][0]!="*") $asInfo['select'][] = $sGroupBy; } - + $sQuery = ""; foreach($asAttributes as $sStatement => $sKeyWord) { @@ -574,12 +574,12 @@ class Db extends PhpObject { if(is_array($asConstraints)) { - if(array_key_exists($sField, $asInfo['constOpe']) && $asInfo['constOpe'][$sField]=='BETWEEN') { + if(array_key_exists('constOpe', $asInfo) && array_key_exists($sField, $asInfo['constOpe']) && $asInfo['constOpe'][$sField]=='BETWEEN') { //Between $asSelection[$sField] = $asConstraints['from'].' AND '.$asConstraints['to']; $asInfo['constOpe'][$sField] = " BETWEEN "; } - else { + else { //Multiple values (IN) $asSelection[$sField] = "(".implode(', ', $asConstraints).")"; $asInfo['constOpe'][$sField] = " IN "; @@ -622,7 +622,7 @@ class Db extends PhpObject $sQuery .= " ".$sKeyWord." * "; } } - + return $this->getArrayQuery(trim($sQuery), $bStringOnly, $sGroupBy); } @@ -646,7 +646,7 @@ class Db extends PhpObject { //Table ID directly if(!is_array($asConstraints)) $asConstraints = array($this->getId($sTableName)=>$asConstraints); - + $asRows = $this->selectRows(array('select'=>$sColumnName, 'from'=>$sTableName, 'constraint'=>$asConstraints)); $iCountNb = count($asRows); switch($iCountNb) @@ -661,13 +661,13 @@ class Db extends PhpObject } return $asResult; } - + public function selectColumn($sTableName, $asColumnNames, $asConstraints) { $sGroupBy = ''; if(!is_array($asColumnNames)) $asColumnNames = array($asColumnNames); else $sGroupBy = $asColumnNames[0]; - + return $this->selectRows( array( 'select' => $asColumnNames, @@ -687,7 +687,7 @@ class Db extends PhpObject $oResult = $this->selectRow($sTableName, $oConstraints, $sColumnName); return empty($oResult)?false:$oResult; } - + public function selectId($sTableName, $oConstraints) { return $this->selectValue($sTableName, self::getId($sTableName), $oConstraints); @@ -750,23 +750,23 @@ class Db extends PhpObject return array_combine($asKeys, $asValues); } } - + /* public function select($asFields='*') { $oSql = new Sql($this, array('select'=>$asFields)); return $oSql; } - + public function from($sTable) { $oSql = new Sql($this, array('from'=>$sTable)); return $oSql; } - + public function getConnection() { return $this->oConnection; } */ -} \ No newline at end of file +} diff --git a/inc/rss.php b/inc/rss.php index 2ad7dd0..e01ecb9 100755 --- a/inc/rss.php +++ b/inc/rss.php @@ -9,10 +9,10 @@ class Feed extends PhpObject { const CHANNEL_TAGS = array('title', 'link', 'copyright', 'description', 'language', 'lastBuildDate', 'generator', 'webMaster'); const ITEM_TAGS = array('title', 'author', 'link', 'category', 'description', 'pubDate', 'guid'); - + private $asChannel; private $asItems; - + /** * Constructor * @param array $asChannel Description of the feed: fields 'title', 'link' (optional), 'copyright', 'description', 'language', 'webMaster' @@ -26,12 +26,12 @@ class Feed extends PhpObject $asChannel['link'] = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['SERVER_NAME'].$_SERVER['SCRIPT_NAME'].'/rss'; } $this->asChannel = $asChannel; - + //Items $this->asItems = array(); array_walk($asItems, array($this, 'addItem')); } - + public function loadRss($sUrl) { $oCurl = curl_init(); @@ -46,10 +46,10 @@ class Feed extends PhpObject //curl_setopt($oCurl, CURLOPT_ENCODING, 'gzip'); $sRssContent = curl_exec($oCurl); curl_close($oCurl); - + //Parse document encoding (useless) $sEncoding = $this->getPregMatch("'encoding=[\'\"](.*?)[\'\"]'si", $sRssContent); - + //Parse Channel info if(preg_match("'(.*?)'si", $sRssContent, $sChannelContent)) { foreach(self::CHANNEL_TAGS as $sChannelTag) @@ -66,7 +66,7 @@ class Feed extends PhpObject if ($temp != '') $result['textinput_'.$textinputtag] = $temp; // Set only if not empty } }*/ - + //Parse Image info /*preg_match("'(.*?)'si", $sRssContent, $out_imageinfo); if (isset($out_imageinfo[1])) { @@ -75,7 +75,7 @@ class Feed extends PhpObject if ($temp != '') $result['image_'.$imagetag] = $temp; // Set only if not empty } }*/ - + //Parse Items preg_match_all("'(.*?)'si", $sRssContent, $asItems); //$i = 0; @@ -91,43 +91,43 @@ class Feed extends PhpObject //if($this->stripHTML && $this->asItems[$i]['description']) $this->asItems[$i]['description'] = strip_tags($this->unhtmlentities(strip_tags($this->asItems[$i]['description']))); //Strip HTML tags and other bullshit from TITLE //if($this->stripHTML && $this->asItems[$i]['title']) $this->asItems[$i]['title'] = strip_tags($this->unhtmlentities(strip_tags($this->asItems[$i]['title']))); - + //Fix for author if(!array_key_exists('author', $asItemTags)) { $sTagContent = $this->getPregMatch("'(.*?)'si", $asItem); if($sTagContent != '') $asItemTags['author'] = $sTagContent; } - + $this->addItem($asItemTags); } } - + 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; } - + public function filterItems($sField, $sRegex) { $this->asItems = array_filter($this->asItems, function($asItem) use ($sField, $sRegex) { return preg_match($sRegex, $asItem[$sField]); }); } - + public function getItems() { return $this->asItems; } - + private function getGlobalPubDate() { $iGlobalPubDate = 0; @@ -141,7 +141,7 @@ class Feed extends PhpObject } return self::cleanRss(self::getDate($iGlobalPubDate)); } - + public function getFeed($bSetMime=true) { //Feed Channel @@ -154,20 +154,20 @@ class Feed extends PhpObject $sRssChannel .= self::getHtml($this->getGlobalPubDate(), 'lastBuildDate'); $sRssChannel .= self::getHtml('Lutran.fr RSS Feed Generator', 'generator'); $sRssChannel .= array_key_exists('webMaster', $this->asChannel)?self::getHtml($this->asChannel['webMaster'].' (Webmaster)', 'webMaster'):''; - + //Feed Items $asSortedItems = $this->rSortTimeMatrix($this->asItems, 'pubDate'); $sItems = implode("\n", array_map(array($this, 'buildItem'), $asSortedItems)); - + //Global Feed $sFeed = ''; $sFeed .= self::getHtml(self::getHtml($sRssChannel.$sItems, 'channel'), 'rss', '', '', array('version'=>'2.0', 'xmlns:atom'=>'http://www.w3.org/2005/Atom')); - + if($bSetMime) header('Content-type: application/rss+xml'); - + return $sFeed; } - + private static function getDate($sDate) { if(!is_numeric($sDate)) @@ -176,7 +176,7 @@ class Feed extends PhpObject } return date('r', $sDate); } - + private function buildItem($asItem) { $sRssItem = self::getHtml(self::cleanRss($asItem['title']), 'title'); @@ -188,22 +188,22 @@ class Feed extends PhpObject $sRssItem .= array_key_exists('guid', $asItem)?self::getHtml($asItem['guid'], 'guid', '', '', array('isPermaLink'=>'true')):''; return self::getHtml($sRssItem, 'item'); } - + private function getPregMatch($pattern, $subject) { preg_match($pattern, $subject, $out); - + //if there is some result... process it and return it if(isset($out[1])) { //If code page is set convert character encoding to required //if ($this->cp != '') $out[1] = iconv($this->rsscp, $this->cp.'//TRANSLIT', $out[1]); - + return str_replace(array(''), '', trim($out[1])); } else return ''; } - + private static function getHtml($oText, $sTag, $sClass='', $sStyle='', $asExtraAttr=array(), $bAutoClose=false, $sInter='') { $sHtmlAttr = ''; @@ -229,19 +229,17 @@ class Feed extends PhpObject } return $sHtml; } - + private static function cleanRss($oText) { - $asForbiddenChars = array('&', '<', '>', '"', "'"); - $asReplacementCode = array('&', '<', '>', '"', '''); if(!is_array($oText)) { - return str_replace($asForbiddenChars, $asReplacementCode, $oText); + return htmlspecialchars($oText, ENT_QUOTES); } elseif(count($oText)>0) { - $oTextKeys = array_map(array($this, 'cleanRss'), array_keys($oText)); - $oTextValues = array_map(array($this, 'cleanRss'), array_values($oText)); + $oTextKeys = array_map(array(self, 'cleanRss'), array_keys($oText)); + $oTextValues = array_map(array(self, 'cleanRss'), array_values($oText)); return array_combine($oTextKeys, $oTextValues); } else @@ -249,7 +247,7 @@ class Feed extends PhpObject return $oText; } } - + private static function encapsulate($oText, $sPre='', $sPost=false, $sInter='') { if($sPost===false) @@ -262,7 +260,7 @@ class Feed extends PhpObject } return $sPre.$oText.$sPost; } - + private static function rSortTimeMatrix($asMatrix, $sTimeCol) { $asResult = array(); @@ -271,4 +269,4 @@ class Feed extends PhpObject foreach($asKeys as $iRowId=>$iTimeStamp) $asResult[$iRowId] = $asMatrix[$iRowId]; return $asResult; } -} \ No newline at end of file +} diff --git a/inc/toolbox.php b/inc/toolbox.php index 4737446..2c79516 100755 --- a/inc/toolbox.php +++ b/inc/toolbox.php @@ -9,7 +9,7 @@ class ToolBox { const FILE_EOL = "\n"; const MAIL_SUCCESS = 2; - + public static function cleanPost(&$asData) { //get rid of magic quotes @@ -18,7 +18,7 @@ class ToolBox $asData = self::cleanData($asData, 'stripslashes'); } } - + public static function cleanData($oData, $sCleaningFunc) { if(!is_array($oData)) @@ -40,7 +40,7 @@ class ToolBox if(defined('STDIN')) mb_parse_str(implode('&', array_slice($argv, 1)), $_GET); $_REQUEST = array_merge($_GET, $_REQUEST); } - + public static function array_map_encapsulate($oData, $sChar) { if(is_array($oData)) @@ -80,9 +80,9 @@ class ToolBox return $acText; } - + /** - * + * * @param String $sFromName * @param String $sSubject * @param String $sMessage @@ -101,7 +101,7 @@ class ToolBox '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); @@ -110,40 +110,40 @@ class ToolBox 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 curl($sUrl, $bHeader=false, $asPostData=array(), $sReturnType='text', $sCookie='', $sCreds='') { $oCurl = curl_init(); curl_setopt($oCurl, CURLOPT_URL, $sUrl); curl_setopt($oCurl, CURLOPT_VERBOSE, false); curl_setopt($oCurl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($oCurl, CURLOPT_SSL_VERIFYHOST, false); - + curl_setopt($oCurl, CURLOPT_HEADER, $bHeader); if($bHeader) curl_setopt($oCurl, CURLOPT_FOLLOWLOCATION, true); - + if(!empty($asPostData)) { curl_setopt($oCurl, CURLOPT_POST, 1); curl_setopt($oCurl, CURLOPT_POSTFIELDS, $asPostData); } - + curl_setopt($oCurl, CURLOPT_RETURNTRANSFER, true); curl_setopt($oCurl, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); - + if($sCookie!='') curl_setopt($oCurl, CURLOPT_COOKIE, $sCookie); if($sCreds!='') curl_setopt($oCurl, CURLOPT_USERPWD, $sCreds); @@ -155,15 +155,15 @@ class ToolBox $sDesc = ''; if(!$bSuccess) $sDesc = ($sCurlErrorId==0)?('HTTP Error Code '.$sHttpCode):($sCurlErrorId.': '.curl_strerror($sCurlErrorId)); curl_close($oCurl); - + switch($sReturnType) { case 'json': $oContent = json_decode($sContent, true); break; default: $oContent = $sContent; } - + return array('result'=>$bSuccess, 'desc'=>$sDesc, 'content'=>$oContent); } - + public static function getMimeType($sPath, $bSubTypeOnly=false) { $sMimetype = ''; @@ -187,7 +187,7 @@ class ToolBox $sMimetype = curl_getinfo($oCurl, CURLINFO_CONTENT_TYPE); curl_close($oCurl); } - + //Only sub type (after /) if($bSubTypeOnly) { @@ -196,38 +196,38 @@ class ToolBox } return $sMimetype; } - + public static function isAnimatedGif($sFilePath) { if(!($oFile = @fopen($sFilePath, 'rb'))) return false; - + $iCount = 0; while (!feof($oFile) && $iCount < 2) { - + $sChunk = fread($oFile, 1024 * 100); //read 100kb at a time $iCount += preg_match_all('#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s', $sChunk, $asMatches); } fclose($oFile); - + return $iCount > 1; } - + public static function createThumbnail($sInPath, $iMaxWidth, $iMaxHeight=0, $sOutPath='', $bDeleteIn=false, $asImageExts=array('jpg', 'jpeg', 'gif', 'png'), $bCrop=false, $bCopyExif=false) { $asResult = array('error'=>''); - + //Look up the file type to choose the image creator $sImageExt = self::getMimeType($sInPath, true); $sImageExt = ($sImageExt=='jpg')?'jpeg':$sImageExt; - + //New Destination folder $asInInfo = pathinfo($sInPath); $asOutInfo = pathinfo($sOutPath); if($sOutPath=='') $sOutPath = $sInPath; elseif(mb_substr($sOutPath, -1)=='/') $sOutPath .= mb_strtolower($asInInfo['basename']); //folder only, keep original name elseif(!array_key_exists('extension', $asOutInfo)) $sOutPath .= '.'.$sImageExt; //folder + filename, but getting ext from file info - + //New sizes if(!in_array($sImageExt, $asImageExts) && !empty($asImageExts)) $asResult['error'] = 'Wrong file type: '.$sImageExt; elseif($iMaxWidth==0 && $iMaxHeight==0) $asResult['error'] = 'At least one dimension must be resized (width and/or height)'; @@ -244,18 +244,18 @@ class ToolBox case 8: $sRotate = 90; break; //Trigo } } - + list($iWidth, $iHeight) = getimagesize($sInPath); if(abs($sRotate) == 90) { $iTempWidth = $iWidth; $iWidth = $iHeight; $iHeight = $iTempWidth; } - + //Limit on only 1 parameter if($iMaxWidth==0) $iMaxWidth = $iWidth * $iMaxHeight / $iHeight; elseif($iMaxHeight==0) $iMaxHeight = $iHeight * $iMaxWidth / $iWidth; - + if($iWidth > $iMaxWidth || $iHeight > $iMaxHeight) { $dResizeDeltaWidth = $iWidth - $iMaxWidth; @@ -263,7 +263,7 @@ class ToolBox $iPosLeft = $iPosTop = 0; $iThumbWidth = $iMaxWidth; $iThumbHeight = $iMaxHeight; - + //Max up the lowest value between height and width and crop the other if($bCrop) { @@ -295,13 +295,13 @@ class ToolBox $iThumbWidth = $iResizedWidth; $iThumbHeight = $iResizedHeight; } - + if($sImageExt=='gif' && self::isAnimatedGif($sInPath)) { $sContent = file_get_contents($sInPath); $sBigGifPath = uniqid().$sOutPath.'.big'; $sCoalescePath = uniqid().$sOutPath.'.coalesce'; - + if(file_put_contents($sBigGifPath, $sContent)===false) $asResult['error'] = 'Unable to create temporary thumbnail : '.$sBigGifPath; system('convert '.$sBigGifPath.' -coalesce '.$sCoalescePath); system('convert -size '.$iWidth.'x'.$iHeight.' '.$sCoalescePath.' -resize '.$iResizedWidth.'x'.$iResizedHeight.' '.$sOutPath); @@ -312,14 +312,14 @@ class ToolBox { //create image from source $oSource = call_user_func('imagecreatefrom'.$sImageExt, $sInPath); - + //Fix rotation - if($sRotate) $oSource = imagerotate($oSource, $sRotate, 0); - + if($sRotate) $oSource = imagerotate($oSource, $sRotate, 0); + //Resize $oThumb = imagecreatetruecolor($iThumbWidth, $iThumbHeight); imagecopyresampled($oThumb, $oSource, $iPosLeft, $iPosTop, 0, 0, $iResizedWidth, $iResizedHeight, $iWidth, $iHeight); - + //Save if(file_exists($sOutPath)) unlink($sOutPath); if(!call_user_func_array('image'.$sImageExt, array($oThumb, $sOutPath))) @@ -342,17 +342,17 @@ class ToolBox if($bCopyExif && $asResult['error'] == '') self::copyExif($sInPath, $sOutPath); if($bDeleteIn && $asResult['error'] == '' && $sInPath != $sOutPath) unlink($sInPath); - + return $asResult; } - + public function copyExif($srcfile, $destfile) { // Function transfers EXIF (APP1) and IPTC (APP13) from $srcfile and adds it to $destfile // JPEG file has format 0xFFD8 + [APP0] + [APP1] + ... [APP15] + where [APPi] are optional // Segment APPi (where i=0x0 to 0xF) has format 0xFFEi + 0xMM + 0xLL + (where 0xMM is // most significant 8 bits of (strlen() + 2) and 0xLL is the least significant 8 bits // of (strlen() + 2) - + if (file_exists($srcfile) && file_exists($destfile)) { $srcsize = @getimagesize($srcfile, $imageinfo); // Prepare EXIF data bytes from source file @@ -378,7 +378,7 @@ class ToolBox $portiontoadd = chr(0xFF) . chr(0xD8); // Variable accumulates new & original IPTC application segments $exifadded = !$exifdata; $iptcadded = !$iptcdata; - + while ((substr($destfilecontent, 0, 2) & 0xFFF0) === 0xFFE0) { $segmentlen = (substr($destfilecontent, 2, 2) & 0xFFFF); $iptcsegmentnumber = (substr($destfilecontent, 1, 1) & 0x0F); // Last 4 bits of second byte is IPTC segment # @@ -408,18 +408,18 @@ class ToolBox return false; } } - + 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 mb_ucfirst($sText) { $sLength = mb_strlen($sText); @@ -427,54 +427,54 @@ class ToolBox $sThen = mb_substr($sText, 1, $sLength - 1); return mb_strtoupper($sFirstChar).$sThen; } - + 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); } - + public static function fixEOL($sText) { //Normalize line endings //Convert all line-endings to UNIX format $sText = str_replace("\r\n", "\n", $sText); //Windows $sText = str_replace("\r", "\n", $sText); //Mac - + // Don't allow out-of-control blank lines $sText = preg_replace("/\n{2,}/", "\n\n", $sText); return $sText; } - + public static function getUserLanguage($available_languages, $sDefaultLang='') { $http_accept_language = isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])?$_SERVER['HTTP_ACCEPT_LANGUAGE']:''; - + //Format: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4 preg_match_all("/([[:alpha:]]{1,8})(-([[:alpha:]|-]{1,8}))?(\s*;\s*q\s*=\s*(1\.0{0,3}|0\.\d{0,3}))?\s*(,|$)/i", $http_accept_language, $hits, PREG_SET_ORDER); - + $bestlang = $sDefaultLang; $bestqval = 0; - + foreach($hits as $arr) { $langprefix = strtolower($arr[1]); if(!empty($arr[3])) { @@ -482,11 +482,11 @@ class ToolBox $language = $langprefix.'-'.$langrange; } else $language = $langprefix; - + //Q Value $qvalue = 1.0; if(!empty($arr[5])) $qvalue = floatval($arr[5]); - + //find q-maximal language if(in_array($language, $available_languages) && $qvalue > $bestqval) { $bestlang = $language; @@ -500,7 +500,7 @@ class ToolBox } return $bestlang; } - + /** * Return relative time description * FIXME shitty implementation of i18n @@ -512,7 +512,7 @@ class ToolBox { $iTimeStamp = is_numeric($oTime)?$oTime:strtotime($oTime); $sCurTimeStamp = time(); - + switch ($sLang) { case 'en': $asWeekDays = array('monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'satursday', 'sunday'); @@ -523,12 +523,12 @@ class ToolBox $asMonths = array('janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'); break; } - + $sSep = '|'; $sFormat = 'Y'.$sSep.'n'.$sSep.'W'.$sSep.'N'.$sSep.'j'.$sSep.'G'; list($sYear, $sMonth, $sWeek, $sWeekDay, $sDay, $sHour) = explode($sSep, date($sFormat, $iTimeStamp)); list($sCurYear, $sCurMonth, $sCurWeek, $sCurWeekDay, $sCurDay, $sCurHour) = explode($sSep, date($sFormat, $sCurTimeStamp)); - + $sDesc = ''; switch ($sLang) { case 'en': @@ -538,7 +538,7 @@ class ToolBox elseif($sCurTimeStamp-$iTimeStamp<60*20) $sDesc = '15 minutes ago'; elseif($sCurTimeStamp-$iTimeStamp<60*50) $sDesc = 'half an hour ago'; elseif($sCurTimeStamp-$iTimeStamp<60*60*2) $sDesc = 'an hour ago'; - elseif($sCurTimeStamp-$iTimeStamp<60*60*24 && $sDay==$sCurDay) $sDesc = 'at '.$sHour.' o\'clock'; + elseif($sCurTimeStamp-$iTimeStamp<60*60*24 && $sDay==$sCurDay) $sDesc = 'at '.date('gA', $iTimeStamp); elseif($sCurTimeStamp-$iTimeStamp<60*60*24) $sDesc = 'yesterday'; elseif($sCurTimeStamp-$iTimeStamp<60*60*24*7 && $sWeek==$sCurWeek) $sDesc = $asWeekDays[$sWeekDay-1]; elseif($sCurTimeStamp-$iTimeStamp<60*60*24*7) $sDesc = 'last '.$asWeekDays[$sWeekDay-1]; @@ -576,7 +576,7 @@ class ToolBox else $sDesc = 'en '.$sYear; break; } - + //return self::mb_ucfirst($sDesc); return $sDesc; } @@ -590,7 +590,7 @@ class ToolBox public static function remove_accents($string) { if(!preg_match('/[\x80-\xff]/', $string)) return $string; - + if (true || seems_utf8($string)) { $chars = array( // Decompositions for Latin-1 Supplement @@ -817,4 +817,4 @@ class ToolBox } } -?> \ No newline at end of file +?>