* @since Version 1.0.1 */ class cINI { private $_read_only = true; private $_nLine = "\r\n"; private $_ini_data; private $_ini_file; const key_clone = '%CLONE%'; const key_empty = '%E%'; const key_comment = '%C%'; /** * Class constructor * * @author Mareks Keišs * @category LIB INI * @param string|bool $sFileName - ini file name * @param string|bool $readOnly - readonly mode */ public function __construct($sFileName = false, $readOnly = true) { $this->_ini_data = []; if ($sFileName) $this->loadIni($sFileName, $readOnly); $this->_read_only = $readOnly; if ( isset($_SERVER['HTTP_USER_AGENT']) && strpos(strtolower($_SERVER['HTTP_USER_AGENT']), "windows", 0) === false ) { $this->_nLine = "\n"; } } /** * Function to read INI into array * * @author Mareks Keišs * @category LIB INI * @param string|bool $sFileName - ini file name * @param bool $readOnly - readonly mode * @return bool - status if load successful */ public function loadIni($sFileName = false, $readOnly = true){ // Load data from ini if(file_exists($sFileName) && is_readable($sFileName)){ $this->_ini_file = $sFileName; $this->_read_only = $readOnly; if($readOnly){ $this->_ini_data = parse_ini_file($sFileName, true); }else{ $this->customINIRead($sFileName); } } } /** * Function to read INI into array * * @author Mareks Keišs * @category LIB INI * @param string|bool $sFileName - ini file name * @return bool - status if load successful */ private function customINIRead($sFileName){ $sSection = ""; $this->_ini_data = array(); // Open file $oFile = @fopen($sFileName, "r"); while(!feof($oFile)){ // Read each line $sLine = trim(@fgets($oFile)); $len = strlen($sLine); if($len == 0){ // Save blank spaces if($sSection) $this->_ini_data[$sSection]['d'][] = self::key_empty; else $this->_ini_data[] = self::key_empty; }else{ if($sLine[0] == ';'){ // Save full row comments if($sSection) $this->_ini_data[$sSection]['d'][$sLine] = self::key_comment; else $this->_ini_data[$sLine] = self::key_comment; }else{ $sComment = ''; // Check if row has comments $pos = strpos($sLine,';'); if($pos != false){ // Remove comment from line $sComment = trim(substr($sLine, $pos)); $sLine = trim(substr($sLine, 0, $pos-1)); $len = strlen($sLine); } // Check for section if(($sLine[0] == '[') && ($sLine[$len-1] == ']')){ $sSection = substr($sLine,1,$len-2); if(!isset($this->_ini_data[$sSection])) $this->_ini_data[$sSection] = array( 'd' => array(), 'c' => $sComment, ); continue; } // Separate var name from value $t = explode("=", $sLine); if(!!$t && count($t) > 1){ $sVar = trim($t[0]); $sVal = trim(trim($t[1]), "'\""); // Check for multidimensional subs $pos = strpos($sVar, '['); if($pos != false){ $sSubsection = trim(substr($sVar, 0, $pos)); $sVar = trim(substr($sVar, $pos+1, strlen($sVar)-$pos-2)); // Add values if($sSection) if($sVar) $this->_ini_data[$sSection]['d'][$sSubsection][$sVar] = array( 'v' => $sVal, 'c' => $sComment, ); else $this->_ini_data[$sSection]['d'][$sSubsection][] = array( 'v' => $sVal, 'c' => $sComment, ); else $this->_ini_data[$sSubsection] = array( $sVar => array( 'v' => $sVal, 'c' => $sComment, ) ); // No subsection found }else{ if($sSection) $this->_ini_data[$sSection]['d'][$sVar] = array( 'v' => $sVal, 'c' => $sComment, ); else $this->_ini_data[$sVar] = array( 'v' => $sVal, 'c' => $sComment, ); } } } } } // Close file @fclose($oFile); } /** * Function to get section variable * * @author Mareks Keišs * @category LIB INI * @param string $sSection - section name * @param string $sKey - variable key name * @param bool $bJSONDecode - decode via JOSN decode * @return mixed - found value/s */ public function getV($sSection, $sKey, $bJSONDecode = false){ if($sSection && $sKey && !!$this->_ini_data){ if($this->_read_only){ if(!empty($this->_ini_data[$sSection][$sKey])){ if(!$bJSONDecode) return $this->_ini_data[$sSection][$sKey]; else return cJSON::decode($this->_ini_data[$sSection][$sKey], true); } }else{ if(!empty($this->_ini_data[$sSection]['d'][$sKey])){ // Check if key found if(isset($this->_ini_data[$sSection]['d'][$sKey]['v'])){ if(!$bJSONDecode) return $this->_ini_data[$sSection]['d'][$sKey]['v']; else return cJSON::decode($this->_ini_data[$sSection]['d'][$sKey]['v'], true); }else{ $data = array(); foreach($this->_ini_data[$sSection]['d'][$sKey] as $k=>$v) $data[$k] = $v['v']; } } } } return false; } /** * Function to set section variable * * @author Mareks Keišs * @category LIB INI * @param string $sKey - variable key name * @param string $sVal - variable value * @param string|bool $sSection - section name * @param string|bool $sComment - comment * @return mixed - found value/s */ public function setV($sKey, $sVal, $sSection = false, $sComment = false){ $bBefore = true; if($sKey && $sVal){ if(!$this->_read_only){ $dataArray = &$this->_ini_data; if($sSection){ $bBefore = false; if(!isset($this->_ini_data[$sSection]['d'])) $this->_ini_data[$sSection]['d'] = array(); $dataArray = &$this->_ini_data[$sSection]['d']; // Subsection support to be added } if($bBefore) $dataArray = array($sKey => array('v' => $sVal)) + $dataArray; else $dataArray[$sKey]['v'] = $sVal; if($sComment) $dataArray[$sKey]['c'] = "; {$sComment}"; } } return false; } /** * Function to get section variable * * @author Mareks Keišs * @category LIB INI * @param array $sSectionDirectLoad - section to direct setup ar constants * @param array $sDomains - domain name constant setup * @return void */ public function loadSystemConstants($sSectionDirectLoad = array('system', 'version_control'), $sDomains = array('domain_cfg', 'domain_cfg_json')){ if($this->_read_only){ if(!!$sDomains){ foreach($sDomains as $v){ if(!empty($this->_ini_data[$v])){ $domain_cfg = &$this->_ini_data[$v]; // use default in case no HOST found - cron for example $sHostKey = (!empty($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'default'); if(!empty($domain_cfg[$sHostKey])){ $connection_cfg = &$domain_cfg[$sHostKey]; if(substr($v, -5) == '_json') { if(substr($connection_cfg,0,6) == 'clone:'){ $sHostKeyClone = substr($connection_cfg, 6); if(!empty($domain_cfg[$sHostKeyClone])) $domain_cfg[$sHostKey] = $domain_cfg[$sHostKeyClone]; } if(!empty($domain_cfg[$sHostKey])) $domain_cfg[$sHostKey] = cJSON::decode($domain_cfg[$sHostKey], true); } foreach($domain_cfg[$sHostKey] as $k => $vv) if(!defined($k)) define($k, $vv); } } } } if(!!$sSectionDirectLoad){ foreach($sSectionDirectLoad as $v){ if(!empty($this->_ini_data[$v])) foreach($this->_ini_data[$v] as $k=>$vv) if(!defined($k)) define($k, $vv); } } } } /** * Function to write ini data to file * * @author Mareks Keišs * @category LIB INI * @param string|bool $newFile - new file path * @return mixed */ public function writeDataToFile($newFile = false){ if($this->_read_only) return false; $spLen = 45; $spSecLen = 45; $sFileContent = ""; $num_regex = "/^[\-\+]?[\d\,]*\.?[\d]*$/"; if(!!$this->_ini_data){ foreach($this->_ini_data as $k=>$v){ // Comment found if($v == self::key_comment){ $sFileContent .= "{$k}{$this->_nLine}"; continue; } // Empty line found if($v == self::key_empty){ $sFileContent .= "{$this->_nLine}"; continue; } // New section found if(!!$v && !empty($v['d'])){ // Add section $sLine = "[{$k}]"; if(isset($v['c']) && $v['c']) $sLine = str_pad($sLine, $spSecLen) . $v['c']; $sFileContent .= "{$sLine}{$this->_nLine}"; foreach($v['d'] as $kk=>$vv){ // Comment found if($vv == self::key_comment){ $sFileContent .= "{$kk}{$this->_nLine}"; continue; } // Empty line found if($vv == self::key_empty){ $sFileContent .= "{$this->_nLine}"; continue; } // Write each section variable if(isset($vv['v'])){ $sLine = "{$kk} = " . (!preg_match($num_regex, $vv['v']) ? "'{$vv['v']}'" : $vv['v']); if(isset($vv['c']) && $vv['c']) $sLine = str_pad($sLine, $spLen) . $vv['c']; $sFileContent .= "{$sLine}{$this->_nLine}"; // Write each subsection variable }elseif(is_array($vv)){ foreach($vv as $kkk=>$vvv){ $sLine = "{$kk}[{$kkk}] = " . (!preg_match($num_regex, $vvv['v']) ? "'{$vvv['v']}'" : $vvv['v']); if($vvv['c']) $sLine = str_pad($sLine, $spLen) . $vvv['c']; $sFileContent .= "{$sLine}{$this->_nLine}"; } } } }else{ $sFileContent .= "{$k} = " . (!preg_match($num_regex, $v['v']) ? "'{$v['v']}'" : $v['v']) . "{$v['c']}{$this->_nLine}"; } } } if(!$newFile) $newFile = $this->_ini_file; // Replace all ending empty new lines $sFileContent = preg_replace('/[\r\n]*$/','', $sFileContent) . $this->_nLine; if(file_exists($newFile) && is_writable($newFile) || !file_exists($newFile)){ $oFile = @fopen($newFile, "w+"); @fwrite($oFile, $sFileContent); @fclose($oFile); return true; } return false; } }