eZ Publish  [4.0]
ezini.php
Go to the documentation of this file.
00001 <?php
00002 //
00003 // $Id$
00004 //
00005 // Definition of eZINI class
00006 //
00007 // Created on: <12-Feb-2002 14:06:45 bf>
00008 //
00009 // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00010 // SOFTWARE NAME: eZ Publish
00011 // SOFTWARE RELEASE: 4.0.x
00012 // COPYRIGHT NOTICE: Copyright (C) 1999-2008 eZ Systems AS
00013 // SOFTWARE LICENSE: GNU General Public License v2.0
00014 // NOTICE: >
00015 //   This program is free software; you can redistribute it and/or
00016 //   modify it under the terms of version 2.0  of the GNU General
00017 //   Public License as published by the Free Software Foundation.
00018 //
00019 //   This program is distributed in the hope that it will be useful,
00020 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 //   GNU General Public License for more details.
00023 //
00024 //   You should have received a copy of version 2.0 of the GNU General
00025 //   Public License along with this program; if not, write to the Free
00026 //   Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
00027 //   MA 02110-1301, USA.
00028 //
00029 //
00030 // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
00031 //
00032 
00033 /*!
00034   \class eZINI ezini.php
00035   \ingroup eZUtils
00036   \brief Reads and writes .ini style configuration files
00037 
00038   The most common way of using it is.
00039   \code
00040   // include the file
00041   //include_once( "classes/ezinifile.php" );
00042 
00043   $ini = eZINI::instance( "site.ini" );
00044 
00045   // get a variable from the file.
00046   $iniVar = $ini->variable( "BlockName", "Variable" );
00047 
00048   \endcode
00049 
00050   The default ini file is site.ini but others can be passed to the instance() function
00051   among with some others. It will create one unique instance for each ini file and rootdir,
00052   this means that the next time instance() is used with the same parameters the same
00053   object will be returned and no new parsing is required.
00054 
00055   The class will by default try to create a cache file in var/cache/ini, however to change
00056   this behaviour the static setIsCacheEnabled() function can be used, or use the $useCache
00057   parameter in instance() for setting this for one object only.
00058 
00059   The class will also handle charset conversion using eZTextCodec, to turn this behaviour
00060   off use the static setIsTextCodecEnabled() function or set the $useTextCodec parameter
00061   in instance() for a per object basis setting.
00062 
00063   Normally the eZINI class will not give out much information about what it's doing,
00064   it's only when errors occur that you'll see this. To enable internal debugging use
00065   the static setIsDebugEnabled() function. The class will then give information about
00066   which files are load, if cache files are used and when cache files are written.
00067 */
00068 
00069 include_once 'lib/ezutils/classes/ezdebug.php';
00070 //include_once( 'lib/ezfile/classes/ezdir.php' );
00071 
00072 /*!
00073  Has the date of the current cache code implementation as a timestamp,
00074  if this changes(increases) the cache files will need to be recreated.
00075 */
00076 
00077 class eZINI
00078 {
00079     const CACHE_CODE_DATE = 1043407542;
00080     const DEBUG_INTERNALS = false;
00081 
00082     // set EZP_INI_FILE_PERMISSION constant to the permissions you want saved
00083     // ini and cache files to have.
00084     static protected $filePermission = 0666;
00085 
00086     /*!
00087       Initialization of object;
00088     */
00089     function eZINI( $fileName, $rootDir = "", $useTextCodec = null, $useCache = null, $useLocalOverrides = null, $directAccess = false, $addArrayDefinition = false )
00090     {
00091         $this->Charset = "utf8";
00092         if ( $fileName == "" )
00093             $fileName = "site.ini";
00094         if ( $rootDir !== false && $rootDir == "" )
00095             $rootDir = "settings";
00096         if ( $useCache === null )
00097             $useCache = eZINI::isCacheEnabled();
00098         if ( eZINI::isNoCacheAdviced() )
00099         {
00100             $useCache = false;
00101         }
00102         if ( $useTextCodec === null )
00103             $useTextCodec = eZINI::isTextCodecEnabled();
00104 
00105         $this->UseTextCodec = $useTextCodec;
00106         $this->Codec = null;
00107         $this->FileName = $fileName;
00108         $this->RootDir = $rootDir;
00109         $this->UseCache = $useCache;
00110         $this->DirectAccess = $directAccess;
00111         $this->UseLocalOverrides = $useLocalOverrides;
00112         $this->AddArrayDefinition = $addArrayDefinition;
00113 
00114         if ( $this->UseLocalOverrides == true )
00115         {
00116             $this->LocalOverrideDirArray = $GLOBALS["eZINIOverrideDirList"];
00117         }
00118 
00119         if ( defined( 'EZP_INI_FILE_PERMISSION' ) )
00120             self::$filePermission = EZP_INI_FILE_PERMISSION;
00121 
00122         $this->load();
00123     }
00124 
00125     /*!
00126      \return the filename.
00127     */
00128     function filename()
00129     {
00130         return $this->FileName;
00131     }
00132 
00133     /*!
00134      \static
00135      \return true if INI cache is enabled globally, the default value is true.
00136      Change this setting with setIsCacheEnabled.
00137     */
00138     static function isCacheEnabled()
00139     {
00140         if ( !isset( $GLOBALS['eZINICacheEnabled'] ) )
00141              $GLOBALS['eZINICacheEnabled'] = true;
00142          return $GLOBALS['eZINICacheEnabled'];
00143     }
00144 
00145     /*!
00146      \return true if cache is not adviced to be used.
00147      \note The no-cache-adviced flag might not be modified in time for site.ini and some other important files to be affected.
00148     */
00149     function isNoCacheAdviced()
00150     {
00151         if ( !isset( $GLOBALS['eZSiteBasics'] ) )
00152             return false;
00153         $siteBasics = $GLOBALS['eZSiteBasics'];
00154         if ( !isset( $siteBasics['no-cache-adviced'] ) )
00155             return false;
00156         return $siteBasics['no-cache-adviced'];
00157     }
00158 
00159     /*!
00160      \static
00161      Sets whether caching is enabled for INI files or not. This setting is global
00162      and can be overriden in the instance() function.
00163     */
00164     static function setIsCacheEnabled( $cache )
00165     {
00166         $GLOBALS['eZINICacheEnabled'] = $cache;
00167     }
00168 
00169     /*!
00170      \static
00171      \return true if debugging of internals is enabled, this will display
00172      which files are loaded and when cache files are created.
00173       Set the option with setIsDebugEnabled().
00174     */
00175     static function isDebugEnabled()
00176     {
00177         if ( !isset( $GLOBALS['eZINIDebugInternalsEnabled'] ) )
00178              $GLOBALS['eZINIDebugInternalsEnabled'] = eZINI::DEBUG_INTERNALS;
00179         return $GLOBALS['eZINIDebugInternalsEnabled'];
00180     }
00181 
00182     /*!
00183      \static
00184      Sets whether internal debugging is enabled or not.
00185     */
00186     static function setIsDebugEnabled( $debug )
00187     {
00188         $GLOBALS['eZINIDebugInternalsEnabled'] = $debug;
00189     }
00190 
00191     /*!
00192      \static
00193      \return true if textcodecs is to be used, this will use the eZTextCodec class
00194              in the eZI18N library for text conversion.
00195       Set the option with setIsTextCodecEnabled().
00196     */
00197     static function isTextCodecEnabled()
00198     {
00199         if ( !isset( $GLOBALS['eZINITextCodecEnabled'] ) )
00200              $GLOBALS['eZINITextCodecEnabled'] = true;
00201         return $GLOBALS['eZINITextCodecEnabled'];
00202     }
00203 
00204     /*!
00205      \static
00206      Sets whether textcodec conversion is enabled or not.
00207     */
00208     static function setIsTextCodecEnabled( $codec )
00209     {
00210         $GLOBALS['eZINITextCodecEnabled'] = $codec;
00211     }
00212 
00213     /*!
00214      \static
00215      Check wether a specified parameter in a specified section is set in a specified file
00216      \param filename (optional)
00217      \param directory (optional)
00218      \param section name
00219      \param parameter name
00220      \return true if the the parameter is set.
00221     */
00222     static function parameterSet( $fileName = 'site.ini', $rootDir = 'settings', &$section, &$parameter )
00223     {
00224         if ( !eZINI::exists( $fileName, $rootDir ) )
00225             return false;
00226 
00227         $iniInstance = eZINI::instance( $fileName, $rootDir, null, null, null, true );
00228         return $iniInstance->hasVariable( $section, $parameter );
00229     }
00230 
00231     /*!
00232      \static
00233      \return true if the INI file \a $fileName exists in the root dir \a $rootDir.
00234      $fileName defaults to site.ini and rootDir to settings.
00235     */
00236     static function exists( $fileName = "site.ini", $rootDir = "settings" )
00237     {
00238         if ( $fileName == "" )
00239             $fileName = "site.ini";
00240         if ( $rootDir == "" )
00241             $rootDir = "settings";
00242         if ( file_exists( $rootDir . '/' . $fileName ) )
00243             return true;
00244         else if ( file_exists( $rootDir . '/' . $fileName . '.append' ) )
00245             return true;
00246         else if ( file_exists( $rootDir . '/' . $fileName . '.append.php' ) )
00247             return true;
00248         return false;
00249     }
00250 
00251     /*!
00252      Tries to load the ini file specified in the constructor or instance() function.
00253      If cache files should be used and a cache file is found it loads that instead.
00254      Set \a $reset to false if you don't want to reset internal data.
00255     */
00256     function load( $reset = true )
00257     {
00258         if ( $this->UseCache )
00259         {
00260             $this->loadCache( $reset );
00261         }
00262         else
00263         {
00264             $this->parse( false, false, $reset );
00265         }
00266     }
00267 
00268     /*!
00269      Tries to load the ini file placement specified in the constructor or instance() function.
00270      If cache files should be used and a cache file is found it loads that instead.
00271      Set \a $reset to false if you don't want to reset internal data.
00272     */
00273     function loadPlacement( $reset = true )
00274     {
00275         if ( $this->UseCache )
00276         {
00277             $this->loadCache( $reset, true );
00278         }
00279         else
00280         {
00281             $this->parse( false, false, $reset, true );
00282         }
00283     }
00284 
00285     /*!
00286      \private
00287      Looks trough all known settings and override folders to find relevant INI files.
00288      The result is a list with expanded paths to the files.
00289      \return the expanded file list.
00290     */
00291     function findInputFiles( &$inputFiles, &$iniFile )
00292     {
00293         if ( $this->RootDir !== false )
00294             $iniFile = eZDir::path( array( $this->RootDir, $this->FileName ) );
00295         else
00296             $iniFile = eZDir::path( array( $this->FileName ) );
00297 
00298         $inputFiles = array();
00299 
00300         if ( $this->FileName == 'override.ini' )
00301         {
00302             eZExtension::prependExtensionSiteAccesses( false, $this, true, false, false );
00303         }
00304 
00305         if ( file_exists( $iniFile ) )
00306             $inputFiles[] = $iniFile;
00307 
00308         // try the same file name with '.append.php' replace with '.append'
00309         if ( preg_match('/^(.+.append).php$/i', $iniFile, $matches ) && file_exists( $matches[1] ) )
00310             $inputFiles[] = $matches[1];
00311 
00312         if ( file_exists ( $iniFile . '.php' ) )
00313             $inputFiles[] = $iniFile . '.php';
00314 
00315         if ( $this->DirectAccess )
00316         {
00317             if ( file_exists ( $iniFile . '.append' ) )
00318                 $inputFiles[] = $iniFile . '.append';
00319 
00320             if ( file_exists ( $iniFile . '.append.php' ) )
00321                 $inputFiles[] = $iniFile . '.append.php';
00322         }
00323         else
00324         {
00325             $overrideDirs = $this->overrideDirs();
00326             foreach ( $overrideDirs as $overrideDirItem )
00327             {
00328                 $overrideDir = $overrideDirItem[0];
00329                 $isGlobal = $overrideDirItem[1];
00330                 if ( $isGlobal )
00331                     $overrideFile = eZDir::path( array( $overrideDir, $this->FileName ) );
00332                 else
00333                     $overrideFile = eZDir::path( array( $this->RootDir, $overrideDir, $this->FileName ) );
00334                 if ( file_exists( $overrideFile . '.php' ) )
00335                 {
00336                     $inputFiles[] = $overrideFile . '.php';
00337                 }
00338                 if ( file_exists( $overrideFile ) )
00339                     $inputFiles[] = $overrideFile;
00340 
00341                 if ( $isGlobal )
00342                     $overrideFile = eZDir::path( array( $overrideDir, $this->FileName . '.append' ) );
00343                 else
00344                     $overrideFile = eZDir::path( array( $this->RootDir, $overrideDir, $this->FileName . '.append' ) );
00345                 if ( file_exists( $overrideFile . '.php' ) )
00346                 {
00347                     $inputFiles[] = $overrideFile . '.php';
00348                 }
00349                 if ( file_exists( $overrideFile ) )
00350                     $inputFiles[] = $overrideFile;
00351             }
00352         }
00353     }
00354 
00355     /*!
00356       \private
00357       Will load a cached version of the ini file if it exists,
00358       if not it will parse the original file and create the cache file.
00359     */
00360     function loadCache( $reset = true, $placement = false )
00361     {
00362         eZDebug::accumulatorStart( 'ini', 'ini_load', 'Load cache' );
00363         if ( $reset )
00364             $this->reset();
00365         $cachedDir = "var/cache/ini/";
00366 
00367         eZDebug::accumulatorStart( 'ini_find_files', 'ini_load', 'FindInputFiles' );
00368         $this->findInputFiles( $inputFiles, $iniFile );
00369         eZDebug::accumulatorStop( 'ini_find_files' );
00370         if ( count( $inputFiles ) == 0 )
00371         {
00372             eZDebug::accumulatorStop( 'ini' );
00373             return false;
00374         }
00375 
00376 /*        if ( strstr( end( $inputFiles ), 'settings/override/' ) )
00377         {
00378             $overrideINIFile = array_pop( $inputFiles );
00379         }*/
00380 
00381         $md5_input = '';
00382         foreach ( $inputFiles as $inputFile )
00383         {
00384             $md5_input .= $inputFile. "\n";
00385         }
00386         if ( $this->UseTextCodec )
00387         {
00388             //include_once( "lib/ezi18n/classes/eztextcodec.php" );
00389             $md5_input .= '-' . eZTextCodec::internalCharset();
00390         }
00391         if ( $placement )
00392         {
00393             $md5_input .= '-placement';
00394         }
00395         $fileName = md5( $md5_input ) . ".php";
00396         $cachedFile = $cachedDir . $fileName;
00397         if ( $placement )
00398         {
00399             $this->PlacementCacheFile = $cachedFile;
00400         }
00401         else
00402         {
00403             $this->CacheFile = $cachedFile;
00404         }
00405 
00406         $inputTime = false;
00407         $currentTime = time();
00408         // check for modifications
00409         foreach ( $inputFiles as $inputFile )
00410         {
00411             $fileTime = filemtime( $inputFile );
00412             if ( $currentTime < $fileTime )
00413                 eZDebug::writeError( 'Input file "' . $inputFile . '" has a timestamp higher then current time, ignoring timestamp to avoid infinite recursion!', 'eZINI::loadCache' );
00414             else if ( $inputTime === false or
00415                  $fileTime > $inputTime )
00416                 $inputTime = $fileTime;
00417         }
00418 
00419         $loadCache = false;
00420         $cacheTime = false;
00421         if ( file_exists( $cachedFile ) )
00422         {
00423             $fileInfo = @stat( $cachedFile );
00424             if ( $fileInfo )
00425             {
00426                 $cacheTime = $fileInfo['mtime'];
00427                 $loadCache = true;
00428                 if ( $cacheTime < $inputTime )
00429                 {
00430                     $loadCache = false;
00431                 }
00432             }
00433         }
00434 
00435         $useCache = false;
00436         if ( $loadCache )
00437         {
00438             $useCache = true;
00439             if ( eZINI::isDebugEnabled() )
00440                 eZDebug::writeNotice( "Loading cache '$cachedFile' for file '" . $this->FileName . "'", "eZINI" );
00441             $charset = null;
00442             $blockValues = array();
00443             include( $cachedFile );
00444             if ( !isset( $val ) or
00445                  !isset( $eZIniCacheCodeDate ) or
00446                  $eZIniCacheCodeDate != eZINI::CACHE_CODE_DATE )
00447             {
00448                 if ( eZINI::isDebugEnabled() )
00449                     eZDebug::writeNotice( "Old structure in cache file used, recreating '$cachedFile' to new structure", "eZINI" );
00450                 $this->reset();
00451                 $useCache = false;
00452             }
00453             else
00454             {
00455                 $this->Charset = $charset;
00456                 $this->ModifiedBlockValues = array();
00457                 if ( $placement )
00458                 {
00459                     $this->BlockValuesPlacement = $val;
00460                 }
00461                 else
00462                 {
00463                     $this->BlockValues = $val;
00464                 }
00465                 unset( $val );
00466             }
00467         }
00468         if ( !$useCache )
00469         {
00470             eZDebug::accumulatorStart( 'ini_files_1', 'ini_load', 'Parse' );
00471             $this->parse( $inputFiles, $iniFile, false, $placement );
00472             eZDebug::accumulatorStop( 'ini_files_1' );
00473             eZDebug::accumulatorStart( 'ini_files_2', 'ini_load', 'Save Cache' );
00474             $cacheSaved = $this->saveCache( $cachedDir, $cachedFile, $placement ? $this->BlockValuesPlacement : $this->BlockValues );
00475             eZDebug::accumulatorStop( 'ini_files_2' );
00476 
00477             if ( $cacheSaved )
00478             {
00479                 // Write log message to storage.log
00480                 //include_once( 'lib/ezfile/classes/ezlog.php' );
00481                 eZLog::writeStorageLog( $fileName, $cachedDir );
00482             }
00483         }
00484 
00485         eZDebug::accumulatorStop( 'ini' );
00486     }
00487 
00488     /*!
00489      \private
00490      Stores the content of the INI object to the cache file \a $cachedFile.
00491     */
00492     function saveCache( $cachedDir, $cachedFile, $data )
00493     {
00494         if ( !file_exists( $cachedDir ) )
00495         {
00496             //include_once( 'lib/ezfile/classes/ezdir.php' );
00497             if ( !eZDir::mkdir( $cachedDir, 0777, true ) )
00498             {
00499                 eZDebug::writeError( "Couldn't create cache directory $cachedDir, perhaps wrong permissions", "eZINI" );
00500                 return false;
00501             }
00502         }
00503         $tmpCacheFile = $cachedFile . '_' . substr( md5( mt_rand() ), 0, 8 );
00504         // save the data to a cached file
00505         $fp = @fopen( $tmpCacheFile, "w" );
00506         if ( $fp === false )
00507         {
00508             eZDebug::writeError( "Couldn't create cache file '$cachedFile', perhaps wrong permissions", "eZINI" );
00509             return false;
00510         }
00511         fwrite( $fp, "<?php\n\$eZIniCacheCodeDate = " . eZINI::CACHE_CODE_DATE . ";\n" );
00512 
00513         if ( $this->Codec )
00514             fwrite( $fp, "\$charset = \"".$this->Codec->RequestedOutputCharsetCode."\";\n" );
00515         else
00516             fwrite( $fp, "\$charset = \"$this->Charset\";\n" );
00517 
00518         fwrite( $fp, "\$val = " . preg_replace( "@\n[\s]+@", '', var_export( $data, true ) ) . ";" );
00519         fwrite( $fp, "\n?>" );
00520         fclose( $fp );
00521         //include_once( 'lib/ezfile/classes/ezfile.php' );
00522         eZFile::rename( $tmpCacheFile, $cachedFile );
00523 
00524         chmod( $cachedFile, self::$filePermission );
00525 
00526         if ( eZINI::isDebugEnabled() )
00527             eZDebug::writeNotice( "Wrote cache file '$cachedFile'", "eZINI" );
00528 
00529         return true;
00530     }
00531 
00532     /*!
00533       \private
00534       Parses either the override ini file or the standard file and then the append
00535       override file if it exists.
00536      */
00537     function parse( $inputFiles = false, $iniFile = false, $reset = true, $placement = false )
00538     {
00539         if ( $reset )
00540             $this->reset();
00541         if ( $inputFiles === false or
00542              $iniFile === false )
00543             $this->findInputFiles( $inputFiles, $iniFile );
00544 
00545         foreach ( $inputFiles as $inputFile )
00546         {
00547             if ( file_exists( $inputFile ) )
00548             {
00549                 $this->parseFile( $inputFile, $placement );
00550             }
00551         }
00552     }
00553 
00554     /*!
00555       \private
00556       Will parse the INI file and store the variables in the variable $this->BlockValues
00557      */
00558     function parseFile( $file, $placement = false )
00559     {
00560         if ( eZINI::isDebugEnabled() )
00561             eZDebug::writeNotice( "Parsing file '$file'", 'eZINI' );
00562 
00563         //include_once( "lib/ezfile/classes/ezfile.php" );
00564         $contents = eZFile::getContents( $file );
00565         if ( $contents === false )
00566         {
00567             eZDebug::writeError( "Failed opening file '$file' for reading", "eZINI" );
00568             return false;
00569         }
00570 
00571         $contents = str_replace( "\r", '', $contents );
00572         $endOfLine = strpos( $contents, "\n" );
00573         $line = substr( $contents, 0, $endOfLine );
00574 
00575         $currentBlock = "";
00576         if ( $line )
00577         {
00578             // check for charset
00579             if ( preg_match( "/#\?ini(.+)\?/", $line, $ini_arr ) )
00580             {
00581                 $args = explode( " ", trim( $ini_arr[1] ) );
00582                 foreach ( $args as $arg )
00583                 {
00584                     $vars = explode( '=', trim( $arg ) );
00585                     if ( $vars[0] == "charset" )
00586                     {
00587                         $val = $vars[1];
00588                         if ( $val[0] == '"' and
00589                              strlen( $val ) > 0 and
00590                              $val[strlen($val)-1] == '"' )
00591                             $val = substr( $val, 1, strlen($val) - 2 );
00592                         $this->Charset = $val;
00593                     }
00594                 }
00595             }
00596         }
00597 
00598         unset( $this->Codec );
00599         if ( $this->UseTextCodec )
00600         {
00601             //include_once( "lib/ezi18n/classes/eztextcodec.php" );
00602             $this->Codec = eZTextCodec::instance( $this->Charset, false, false );
00603 
00604             if ( $this->Codec )
00605             {
00606                 eZDebug::accumulatorStart( 'ini_conversion', false, 'INI string conversion' );
00607                 $contents = $this->Codec->convertString( $contents );
00608                 eZDebug::accumulatorStop( 'ini_conversion', false, 'INI string conversion' );
00609             }
00610         }
00611         else
00612             $this->Codec = null;
00613 
00614         foreach ( explode( "\n", $contents ) as $line )
00615         {
00616             if ( $line == '' or $line[0] == '#' )
00617                 continue;
00618             if ( preg_match( "/^(.+)##.*/", $line, $regs ) )
00619                 $line = $regs[1];
00620             if ( trim( $line ) == '' )
00621                 continue;
00622             // check for new block
00623             if ( preg_match("#^\[(.+)\]\s*$#", $line, $newBlockNameArray ) )
00624             {
00625                 $newBlockName = trim( $newBlockNameArray[1] );
00626                 $currentBlock = $newBlockName;
00627                 continue;
00628             }
00629 
00630             // check for variable
00631             if ( preg_match("#^([\w_*@-]+)\\[\\]$#", $line, $valueArray ) )
00632             {
00633                 $varName = trim( $valueArray[1] );
00634 
00635                 if ( $placement )
00636                 {
00637                     if ( isset( $this->BlockValuesPlacement[$currentBlock][$varName] ) &&
00638                          !is_array( $this->BlockValuesPlacement[$currentBlock][$varName] ) )
00639                     {
00640                         eZDebug::writeError( "Wrong operation on the ini setting array '$varName'", 'eZINI' );
00641                         continue;
00642                     }
00643 
00644                     $this->BlockValuesPlacement[$currentBlock][$varName][] = $file;
00645                 }
00646                 else
00647                 {
00648                     $this->BlockValues[$currentBlock][$varName] = array();
00649 
00650                     // In direct access mode we create empty elements at the beginning of an array
00651                     // in case it is redefined in this ini file. So when we will save it, definition
00652                     // will be created as well.
00653                     if ( $this->AddArrayDefinition )
00654                     {
00655                         $this->BlockValues[$currentBlock][$varName][] = "";
00656                     }
00657                 }
00658             }
00659             else if ( preg_match("#^([\w_*@-]+)(\\[([^\\]]*)\\])?=(.*)$#", $line, $valueArray ) )
00660             {
00661                 $varName = trim( $valueArray[1] );
00662                 $varValue = $valueArray[4];
00663 
00664                 if ( $valueArray[2] )
00665                 {
00666                     if ( $valueArray[3] )
00667                     {
00668                         $keyName = $valueArray[3];
00669                         if ( $placement )
00670                         {
00671                             $this->BlockValuesPlacement[$currentBlock][$varName][$keyName] = $file;
00672                         }
00673                         else
00674                         {
00675                             $this->BlockValues[$currentBlock][$varName][$keyName] = $varValue;
00676                         }
00677                     }
00678                     else
00679                     {
00680                         if ( $placement )
00681                         {
00682                             $this->BlockValuesPlacement[$currentBlock][$varName][] = $file;
00683                         }
00684                         else
00685                         {
00686                             $this->BlockValues[$currentBlock][$varName][] = $varValue;
00687                         }
00688                     }
00689                 }
00690                 else
00691                 {
00692                     if ( $placement )
00693                     {
00694                         $this->BlockValuesPlacement[$currentBlock][$varName] = $file;
00695                     }
00696                     else
00697                     {
00698                         $this->BlockValues[$currentBlock][$varName] = $varValue;
00699                     }
00700                 }
00701             }
00702         }
00703     }
00704 
00705     /*!
00706      \removes the cache file if it exists.
00707     */
00708     function resetCache()
00709     {
00710         if ( file_exists( $this->CacheFile ) )
00711             unlink( $this->CacheFile );
00712         if ( file_exists( $this->PlacementCacheFile ) )
00713             unlink( $this->PlacementCacheFile );
00714     }
00715 
00716 
00717     /*!
00718       Saves the file to disk.
00719       If filename is given the file is saved with that name if not the current name is used.
00720       If \a $useOverride is true then the file will be placed in the override directory,
00721       if \a $useOverride is "append" it will append ".append" to the filename.
00722     */
00723     function save( $fileName = false, $suffix = false, $useOverride = false,
00724                    $onlyModified = false, $useRootDir = true, $resetArrays = false,
00725                    $encapsulateInPHP = true )
00726     {
00727         //include_once( 'lib/ezfile/classes/ezdir.php' );
00728         $lineSeparator = eZSys::lineSeparator();
00729         $pathArray = array();
00730         $dirArray = array();
00731         if ( $fileName === false )
00732             $fileName = $this->FileName;
00733         if ( $useRootDir === true )
00734         {
00735             $pathArray[] = $this->RootDir;
00736             $dirArray[] = $this->RootDir;
00737         }
00738         else if ( is_string( $useRootDir ) )
00739         {
00740             $pathArray[] = $useRootDir;
00741             $dirArray[] = $useRootDir;
00742         }
00743         if ( $useOverride )
00744         {
00745             $pathArray[] = 'override';
00746             $dirArray[] = 'override';
00747         }
00748         if ( is_string( $useOverride ) and
00749              $useOverride == "append" )
00750             $fileName .= ".append";
00751         if ( $suffix !== false )
00752             $fileName .= $suffix;
00753 
00754         /* Try to guess which filename would fit better: 'xxx.apend' or 'xxx.append.php'.
00755          * We choose 'xxx.append.php' in all cases except when
00756          * 'xxx.append' exists already and 'xxx.append.php' does not exist.
00757          */
00758         if( strstr( $fileName, '.append' ) )
00759         {
00760             $fnAppend    = ereg_replace( '\.php$', '', $fileName );
00761             $fnAppendPhp = $fnAppend.'.php';
00762             $fpAppend    = eZDir::path( array_merge( $pathArray, array( $fnAppend ) ) );
00763             $fpAppendPhp = eZDir::path( array_merge( $pathArray, array( $fnAppendPhp ) ) );
00764             $fileName = ( file_exists( $fpAppend ) && !file_exists( $fpAppendPhp ) )
00765                        ? $fnAppend : $fnAppendPhp;
00766         }
00767 
00768         $originalFileName = $fileName;
00769         $backupFileName = $originalFileName . eZSys::backupFilename();
00770         $fileName .= '.tmp';
00771 
00772         $dirPath = eZDir::path( $dirArray );
00773         if ( !file_exists( $dirPath ) )
00774             eZDir::mkdir( $dirPath, octdec( '777' ), true );
00775 
00776         //include_once( 'lib/ezfile/classes/ezdir.php' );
00777         $filePath = eZDir::path( array_merge( $pathArray, array( $fileName ) ) );
00778         $originalFilePath = eZDir::path( array_merge( $pathArray, array( $originalFileName ) ) );
00779         $backupFilePath = eZDir::path( array_merge( $pathArray, array( $backupFileName ) ) );
00780 
00781         $fp = @fopen( $filePath, "w+");
00782         if ( !$fp )
00783         {
00784             eZDebug::writeError( "Failed opening file '$filePath' for writing", "eZINI" );
00785             return false;
00786         }
00787         $writeOK = true;
00788         $written = 0;
00789 
00790         $charset = $this->Codec ? $this->Codec->RequestedOutputCharsetCode : $this->Charset;
00791         if ( $encapsulateInPHP )
00792         {
00793             $written = fwrite( $fp, "<?php /* #?ini charset=\"$charset\"?$lineSeparator$lineSeparator" );
00794         }
00795         else
00796         {
00797             $written = fwrite( $fp, "#?ini charset=\"$charset\"?$lineSeparator$lineSeparator" );
00798         }
00799 
00800         if ( $written === false )
00801             $writeOK = false;
00802         $i = 0;
00803         if ( $writeOK )
00804         {
00805             foreach( array_keys( $this->BlockValues ) as $blockName )
00806             {
00807                 if ( $onlyModified )
00808                 {
00809                     $groupHasModified = false;
00810                     if ( isset( $this->ModifiedBlockValues[$blockName] ) )
00811                     {
00812                         foreach ( $this->ModifiedBlockValues[$blockName] as $modifiedValue )
00813                         {
00814                             if ( $modifiedValue )
00815                                 $groupHasModified = true;
00816                         }
00817                     }
00818                     if ( !$groupHasModified )
00819                         continue;
00820                 }
00821                 $written = 0;
00822                 if ( $i > 0 )
00823                     $written = fwrite( $fp, "$lineSeparator" );
00824                 if ( $written === false )
00825                 {
00826                     $writeOK = false;
00827                     break;
00828                 }
00829                 $written = fwrite( $fp, "[$blockName]$lineSeparator" );
00830                 if ( $written === false )
00831                 {
00832                     $writeOK = false;
00833                     break;
00834                 }
00835                 foreach( array_keys( $this->BlockValues[$blockName] ) as $blockVariable )
00836                 {
00837                     if ( $onlyModified )
00838                     {
00839                         if ( !isset( $this->ModifiedBlockValues[$blockName][$blockVariable] ) or
00840                              !$this->ModifiedBlockValues[$blockName][$blockVariable] )
00841                             continue;
00842                     }
00843                     $varKey = $blockVariable;
00844                     $varValue = $this->BlockValues[$blockName][$blockVariable];
00845                     if ( is_array( $varValue ) )
00846                     {
00847                         if ( count( $varValue ) > 0 )
00848                         {
00849                             $customResetArray = ( isset( $this->BlockValues[$blockName]['ResetArrays'] ) and
00850                                                   $this->BlockValues[$blockName]['ResetArrays'] == 'false' )
00851                                                 ? true
00852                                                 : false;
00853                             if ( $resetArrays and !$customResetArray )
00854                                 $written = fwrite( $fp, "$varKey" . "[]$lineSeparator" );
00855                             foreach ( $varValue as $varArrayKey => $varArrayValue )
00856                             {
00857                                 if ( is_string( $varArrayKey ) )
00858                                     $written = fwrite( $fp, "$varKey" . "[$varArrayKey]=$varArrayValue$lineSeparator" );
00859                                 else
00860                                 {
00861                                     if ( $varArrayValue == NULL )
00862                                         $written = fwrite( $fp, "$varKey" . "[]$lineSeparator" );
00863                                     else
00864                                         $written = fwrite( $fp, "$varKey" . "[]=$varArrayValue$lineSeparator" );
00865                                 }
00866                                 if ( $written === false )
00867                                     break;
00868                             }
00869                         }
00870                         else
00871                             $written = fwrite( $fp, "$varKey" . "[]$lineSeparator" );
00872                     }
00873                     else
00874                     {
00875                         $written = fwrite( $fp, "$varKey=$varValue$lineSeparator" );
00876                     }
00877                     if ( $written === false )
00878                     {
00879                         $writeOK = false;
00880                         break;
00881                     }
00882                 }
00883                 if ( !$writeOK )
00884                     break;
00885                 ++$i;
00886             }
00887         }
00888         if ( $writeOK )
00889         {
00890             if ( $encapsulateInPHP )
00891             {
00892                 $written = fwrite( $fp, "*/ ?>" );
00893 
00894                 if ( $written === false )
00895                     $writeOK = false;
00896             }
00897         }
00898         @fclose( $fp );
00899         if ( !$writeOK )
00900         {
00901             unlink( $filePath );
00902             return false;
00903         }
00904 
00905         chmod( $filePath, self::$filePermission );
00906 
00907         if ( file_exists( $backupFilePath ) )
00908             unlink( $backupFilePath );
00909         if ( file_exists( $originalFilePath ) )
00910         {
00911             if ( !rename( $originalFilePath, $backupFilePath ) )
00912                 return false;
00913         }
00914         if ( !rename( $filePath, $originalFilePath ) )
00915         {
00916             rename( $backupFilePath, $originalFilePath );
00917             return false;
00918         }
00919 
00920         return true;
00921     }
00922 
00923     /*!
00924      Removes all read data from .ini files.
00925     */
00926     function reset()
00927     {
00928         $this->BlockValues = array();
00929         $this->ModifiedBlockValues = array();
00930     }
00931 
00932     /*!
00933      \return the root directory from where all .ini and override files are read.
00934 
00935      This is set by the instance() or eZINI() functions.
00936     */
00937     function rootDir()
00938     {
00939         return $this->RootDir;
00940     }
00941 
00942     /*!
00943      \return the override directories, if no directories has been set "override" is returned.
00944 
00945     The override directories are returned as an array of arrays. The first
00946     value in the array is the override directory, the second is a boolean which
00947     defines if the directory is relative to the rootDir() or not. If the second value
00948     is false the override dir is relative, true means that the override dir is relative
00949     to the eZ Publish root directory.
00950     The third value of the array will contain the identifier of the override, if it exists.
00951     Identifiers are useful if you want to overwrite the current override setting.
00952     */
00953     function overrideDirs()
00954     {
00955         if ( $this->UseLocalOverrides == true )
00956             $dirs =& $this->LocalOverrideDirArray;
00957         else
00958             $dirs =& $GLOBALS["eZINIOverrideDirList"];
00959 
00960         if ( !isset( $dirs ) or !is_array( $dirs ) )
00961             $dirs = array( array( "override", false, false ) );
00962         return $dirs;
00963     }
00964 
00965     /*!
00966      Appends the override directory \a $dir to the override directory list.
00967      If global dir is set top
00968     */
00969     function prependOverrideDir( $dir, $globalDir = false, $identifier = false )
00970     {
00971         if ( eZINI::isDebugEnabled() )
00972             eZDebug::writeNotice( "Changing override dir to '$dir'", "eZINI" );
00973 
00974         if ( $this->UseLocalOverrides == true )
00975             $dirs =& $this->LocalOverrideDirArray;
00976         else
00977             $dirs =& $GLOBALS["eZINIOverrideDirList"];
00978 
00979         if ( !isset( $dirs ) or !is_array( $dirs ) )
00980             $dirs = array( array( 'override', false, false ) );
00981 
00982         // Check if the override with the current identifier already exists
00983         $overrideOverwritten = false;
00984         if ( $identifier !== false )
00985         {
00986             foreach ( array_keys( $dirs ) as $dirKey )
00987             {
00988                 if ( $dirs[$dirKey][2] == $identifier )
00989                 {
00990                     $dirs[$dirKey][0] = $dir;
00991                     $dirs[$dirKey][1] = $globalDir;
00992                     $overrideOverwritten = true;
00993                 }
00994             }
00995         }
00996 
00997         if ( $overrideOverwritten == false )
00998             $dirs = array_merge( array( array( $dir, $globalDir, $identifier ) ), $dirs );
00999 
01000         $this->CacheFile = false;
01001      }
01002 
01003     /*!
01004      Appends the override directory \a $dir to the override directory list.
01005     */
01006     function appendOverrideDir( $dir, $globalDir = false, $identifier = false )
01007     {
01008         if ( eZINI::isDebugEnabled() )
01009             eZDebug::writeNotice( "Changing override dir to '$dir'", "eZINI" );
01010 
01011         if ( $this->UseLocalOverrides == true )
01012             $dirs =& $this->LocalOverrideDirArray;
01013         else
01014             $dirs =& $GLOBALS["eZINIOverrideDirList"];
01015 
01016         if ( !isset( $dirs ) or !is_array( $dirs ) )
01017             $dirs = array( 'override', false, false );
01018 
01019         // Check if the override with the current identifier already exists
01020         $overrideOverwritten = false;
01021         if ( $identifier !== false )
01022         {
01023             foreach ( array_keys( $dirs ) as $dirKey )
01024             {
01025                 if ( $dirs[$dirKey][2] == $identifier )
01026                 {
01027                     $dirs[$dirKey][0] = $dir;
01028                     $dirs[$dirKey][1] = $globalDir;
01029                     $overrideOverwritten = true;
01030                 }
01031             }
01032         }
01033 
01034         if ( $overrideOverwritten == false )
01035             $dirs[] = array( $dir, $globalDir, $identifier = false );
01036         $this->CacheFile = false;
01037     }
01038 
01039     /*!
01040       Reads a variable from the ini file and puts it in the parameter \a $variable.
01041       \note \a $variable is not modified if the variable does not exist
01042     */
01043     function assign( $blockName, $varName, &$variable )
01044     {
01045         if ( $this->hasVariable( $blockName, $varName ) )
01046             $variable = $this->variable( $blockName, $varName );
01047         else
01048             return false;
01049         return true;
01050     }
01051 
01052     /*!
01053       Reads a variable from the ini file.
01054       false is returned if the variable was not found.
01055     */
01056     function variable( $blockName, $varName )
01057     {
01058         $ret = false;
01059         if ( !isset( $this->BlockValues[$blockName] ) )
01060             eZDebug::writeError( "Undefined group: '$blockName' in " . $this->FileName, "eZINI" );
01061         else if ( isset( $this->BlockValues[$blockName][$varName] ) )
01062             $ret = $this->BlockValues[$blockName][$varName];
01063         else
01064             eZDebug::writeError( "Undefined variable: '$varName' in group '$blockName' in " . $this->FileName, "eZINI" );
01065 
01066         return $ret;
01067     }
01068 
01069     /*!
01070       Reads multiple variables from the ini file.
01071       false is returned if the variable was not found.
01072     */
01073     function variableMulti( $blockName, $varNames, $signatures = array() )
01074     {
01075         $ret = array();
01076 
01077         if ( !isset( $this->BlockValues[$blockName] ) )
01078         {
01079             eZDebug::writeError( "Undefined group: '$blockName' in " . $this->FileName, "eZINI" );
01080             return false;
01081         }
01082         foreach ( $varNames as $key => $varName )
01083         {
01084             if ( isset( $this->BlockValues[$blockName][$varName] ) )
01085             {
01086                 $ret[$key] = $this->BlockValues[$blockName][$varName];
01087 
01088                 if ( isset( $signatures[$key] ) )
01089                 {
01090                     switch ( $signatures[$key] )
01091                     {
01092                         case 'enabled':
01093                             $ret[$key] = $this->BlockValues[$blockName][$varName] == 'enabled';
01094                             break;
01095                     }
01096                 }
01097             }
01098             else
01099             {
01100                 $ret[] = null;
01101             }
01102         }
01103 
01104         return $ret;
01105     }
01106 
01107     /*!
01108       Checks if a variable is set. Returns true if the variable exists, false if not.
01109     */
01110     function hasVariable( $blockName, $varName )
01111     {
01112         return isset( $this->BlockValues[$blockName][$varName] );
01113     }
01114 
01115     /*!
01116       Check if a block/section is set. Returns true if the section/block is set, false if not
01117     */
01118     function hasSection( $sectionName )
01119     {
01120         return isset( $this->BlockValues[$sectionName] );
01121     }
01122 
01123     /*!
01124       \return true if the variable \a $varName in group \a $blockName has been modified.
01125     */
01126     function isVariableModified( $blockName, $varName )
01127     {
01128         return ( isset( $this->ModifiedBlockValues[$blockName][$varName] ) and
01129                  $this->ModifiedBlockValues[$blockName][$varName] );
01130     }
01131 
01132     /*!
01133       Reads a variable from the ini file. The variable
01134       will be returned as an array. ; is used as delimiter.
01135      */
01136     function variableArray( $blockName, $varName )
01137     {
01138         $ret = $this->variable( $blockName, $varName );
01139         if ( is_array( $ret ) )
01140         {
01141             $arr = array();
01142             foreach ( $ret as $key => $retItem )
01143             {
01144                 $arr[$key] = explode( ";", $retItem );
01145             }
01146             $ret = $arr;
01147         }
01148         else if ( $ret !== false )
01149         {
01150             $ret = trim( $ret ) === '' ? array() : explode( ";", $ret );
01151         }
01152 
01153         return $ret;
01154     }
01155 
01156     /*!
01157       Checks if group $blockName is set. Returns true if the group exists, false if not.
01158     */
01159     function hasGroup( $blockName )
01160     {
01161         return isSet( $this->BlockValues[$blockName] );
01162     }
01163 
01164     /*!
01165       Fetches a variable group and returns it as an associative array.
01166      */
01167     function &group( $blockName )
01168     {
01169         if ( !isset( $this->BlockValues[$blockName] ) )
01170         {
01171             eZDebug::writeError( "Unknown group: '$blockName'", "eZINI" );
01172             $ret = null;
01173             return $ret;
01174         }
01175         $ret = $this->BlockValues[$blockName];
01176 
01177         return $ret;
01178     }
01179 
01180     function isSettingReadOnly( $fileName = false, $blockName = false, $settingName = false )
01181     {
01182         if ( !$this->readOnlySettingsCheck() )
01183             return true;
01184 
01185         $ini = eZINI::instance();
01186         if ( !$ini->hasVariable( 'eZINISettings', 'ReadonlySettingList' ) )
01187             return true;
01188 
01189         $fileName = $fileName === false ? $ini->FileName : $fileName;
01190         $fileNameExploded = explode( '.', $fileName );
01191         $realFileName = $fileNameExploded[0] . '.' . $fileNameExploded[1];
01192         $blockName = $blockName === false ? '*' : $blockName;
01193         $settingName = $settingName === false ? '*' : $settingName;
01194         $currentSetting = $realFileName . '/' . $blockName . '/' . $settingName;
01195 
01196         $settingList = $ini->variable( 'eZINISettings', 'ReadonlySettingList' );
01197         $settingList[] = 'site.ini/eZINISettings/*';
01198 
01199         $result = !( in_array( $realFileName . '/*' , $settingList ) or
01200                      in_array( $realFileName . '/' . $blockName . '/*'  , $settingList ) or
01201                      in_array( $realFileName . '/' . $blockName . '/' . $settingName  , $settingList ) );
01202 
01203         return $result;
01204     }
01205     /*!
01206       Removes the group and all it's settings from the .ini file
01207     */
01208     function removeGroup( $blockName )
01209     {
01210         unset( $this->BlockValues[$blockName] );
01211         unset( $this->BlockValuesPlacement[$blockName] );
01212     }
01213 
01214     function removeSetting( $blockName, $settingName )
01215     {
01216         unset( $this->BlockValues[$blockName][$settingName] );
01217         unset( $this->BlockValuesPlacement[$blockName][$settingName] );
01218         if ( $this->BlockValues[$blockName] == null )
01219             $this->removeGroup( $blockName );
01220     }
01221 
01222     /*!
01223      Fetches all defined groups and returns them as an associative array
01224     */
01225     function &groups()
01226     {
01227         return $this->BlockValues;
01228     }
01229 
01230     /*!
01231      Fetches all defined placements for every setting and returns them as an associative array
01232     */
01233     function &groupPlacements()
01234     {
01235         if ( !$this->BlockValuesPlacement )
01236         {
01237             $this->loadPlacement();
01238         }
01239         return $this->BlockValuesPlacement;
01240     }
01241 
01242     function &findSettingPlacement( $path )
01243     {
01244         if ( is_array( $path ) && count( $path ) )
01245             $path = $path[0];
01246         $exploded = explode( '/', $path );
01247         $directoryCount = count( $exploded );
01248         switch ( $directoryCount )
01249         {
01250             case 2:
01251                 $placement = 'default';
01252             break;
01253             case 3:
01254                 $placement = 'override';
01255             break;
01256             case 4:
01257             {
01258                 $placement = 'siteaccess';
01259                 if ( $exploded[0] == 'extension' )
01260                     $placement = 'extension:' . $exploded[1];
01261             }
01262             break;
01263             case 6:
01264             {
01265                 $placement = 'ext-siteaccess:' . $exploded[4];
01266             }
01267             break;
01268             default:
01269                 $placement = 'undefined';
01270             break;
01271         }
01272         return $placement;
01273     }
01274 
01275     function settingType( $settingValue )
01276     {
01277         if ( is_array( $settingValue ) )
01278             return 'array';
01279 
01280         if ( is_numeric( $settingValue ) )
01281             return 'numeric';
01282 
01283         if ( $settingValue == 'true' or $settingValue == 'false' )
01284         {
01285             return 'true/false';
01286         }
01287         if ( $settingValue == 'enabled' or $settingValue == 'disabled' )
01288         {
01289             return 'enable/disable';
01290         }
01291 
01292         return 'string';
01293     }
01294 
01295     /*!
01296      Sets all groups overwriting the current values
01297     */
01298     function setGroups( $groupArray )
01299     {
01300         $resultArray = array();
01301         // Check for readOnly
01302         foreach ( $groupArray as $blockName => $blockVariables )
01303         {
01304             foreach ( $blockVariables as $variableName => $variableValue )
01305             {
01306                 if ( !$this->isSettingReadOnly( $this->FileName, $blockName, $variableName ) )
01307                     continue;
01308                 $resultArray[$blockName][$variableName] = $variableValue;
01309             }
01310         }
01311         $this->BlockValues = $resultArray;
01312     }
01313 
01314     /*!
01315      Sets multiple variables from the array \a $variables.
01316      \param $variables Contains an associative array with groups as first key,
01317                        variable names as second key and variable values as values.
01318      \code
01319      $ini->setVariables( array( 'SiteSettings' => array( 'SiteName' => 'mysite',
01320                                                          'SiteURL' => 'http://mysite.com' ) ) );
01321      \endcode
01322      \sa setVariable
01323     */
01324     function setVariables( $variables )
01325     {
01326         foreach ( $variables as $blockName => $blockVariables )
01327         {
01328             foreach ( $blockVariables as $variableName => $variableValue )
01329             {
01330                 $this->setVariable( $blockName, $variableName, $variableValue );
01331             }
01332         }
01333     }
01334 
01335     /*!
01336      Sets an INI file variable.
01337      \code
01338      $ini->setVariable( 'SiteSettings', 'SiteName', 'mysite' );
01339      \endcode
01340      \sa setVariables
01341     */
01342     function setVariable( $blockName, $variableName, $variableValue )
01343     {
01344         if ( !$this->isSettingReadOnly( $this->filename(), $blockName, $variableName ) )
01345             return false;
01346 
01347         $this->BlockValues[$blockName][$variableName] = $variableValue;
01348         $this->ModifiedBlockValues[$blockName][$variableName] = true;
01349     }
01350 
01351     /*!
01352       Returns BlockValues, which is a nicely named Array
01353     */
01354     function getNamedArray()
01355     {
01356         return $this->BlockValues;
01357     }
01358 
01359     /*!
01360      \static
01361      \return true if the ini file \a $fileName has been loaded yet.
01362     */
01363     static function isLoaded( $fileName = "site.ini", $rootDir = "settings", $useLocalOverrides = null )
01364     {
01365         $isLoaded =& $GLOBALS["eZINIGlobalIsLoaded-$rootDir-$fileName-$useLocalOverrides"];
01366         if ( !isset( $isLoaded ) )
01367             return false;
01368         return $isLoaded;
01369     }
01370 
01371     /*!
01372       \static
01373       Returns the current instance of the given .ini file
01374       If $useLocalOverrides is set to true you will get a copy of the current overrides,
01375       but changes to the override settings will not be global.
01376       Direct access is for accessing the filename directly in the specified path. .append and .append.php is automaticly added to filename
01377       \note Use create() if you need to get a unique copy which you can alter.
01378     */
01379     static function instance( $fileName = "site.ini", $rootDir = "settings", $useTextCodec = null, $useCache = null, $useLocalOverrides = null, $directAccess = false, $addArrayDefinition = false )
01380     {
01381         $globalsKey = "eZINIGlobalInstance-$rootDir-$fileName-$useLocalOverrides";
01382         $globalsIsLoadedKey = "eZINIGlobalIsLoaded-$rootDir-$fileName-$useLocalOverrides";
01383 
01384         if ( !isset( $GLOBALS[$globalsKey] ) ||
01385              !( $GLOBALS[$globalsKey] instanceof eZINI ) )
01386         {
01387             $GLOBALS[$globalsIsLoadedKey] = false;
01388 
01389             $GLOBALS[$globalsKey] = new eZINI( $fileName, $rootDir, $useTextCodec, $useCache, $useLocalOverrides, $directAccess, $addArrayDefinition );
01390 
01391             $GLOBALS[$globalsIsLoadedKey] = true;
01392         }
01393         return $GLOBALS[$globalsKey];
01394     }
01395 
01396     /*!
01397      Fetches the ini file \a $fileName and returns the INI object for it.
01398      \note This will not use the override system or read cache files, this is a direct fetch from one file.
01399     */
01400     static function &fetchFromFile( $fileName, $useTextCodec = null )
01401     {
01402         $impl = new eZINI( $fileName, false, $useTextCodec, false, false, true );
01403         return $impl;
01404     }
01405 
01406     /*!
01407      \static
01408      Get instance siteaccess specific site.ini
01409      \param siteAccess the site access to get ini for
01410      \param iniFile the site access to get ini for
01411      \return eZINI object, or false if not found
01412     */
01413     static function getSiteAccessIni( $siteAccess, $iniFile )
01414     {
01415         $saPath = eZSiteAccess::findPathToSiteAccess( $siteAccess );
01416         return self::fetchFromFile( "$saPath/$iniFile" );
01417     }
01418 
01419     /*!
01420       \static
01421       Similar to instance() but will always create a new copy.
01422     */
01423     static function create( $fileName = "site.ini", $rootDir = "settings", $useTextCodec = null, $useCache = null, $useLocalOverrides = null )
01424     {
01425         $impl = new eZINI( $fileName, $rootDir, $useTextCodec, $useCache, $useLocalOverrides );
01426         return $impl;
01427     }
01428 
01429     /*!
01430        Sets ReadonlySettingsCheck variable.
01431     */
01432     function setReadOnlySettingsCheck( $readOnly = true )
01433     {
01434         $this->ReadOnlySettingsCheck = $readOnly;
01435     }
01436 
01437     /*!
01438        \return ReadonlySettingsCheck variable.
01439     */
01440     function readOnlySettingsCheck()
01441     {
01442         return $this->ReadOnlySettingsCheck;
01443     }
01444 
01445     /*!
01446      \static
01447     */
01448     static function resetGlobals(  $fileName = "site.ini", $rootDir = "settings", $useLocalOverrides = null )
01449     {
01450         unset( $GLOBALS["eZINIGlobalInstance-$rootDir-$fileName-$useLocalOverrides"] );
01451         unset( $GLOBALS["eZINIGlobalIsLoaded-$rootDir-$fileName-$useLocalOverrides"] );
01452     }
01453 
01454     /// \privatesection
01455     /// The charset of the ini file
01456     public $Charset;
01457 
01458     /// Variable to store the textcodec.
01459     public $Codec;
01460 
01461     /// Variable to store the ini file values.
01462     public $BlockValues;
01463 
01464     /// Variable to store the setting placement (which file is the setting in).
01465     public $BlockValuesPlacement;
01466 
01467     /// Variable to store whether variables are modified or not
01468     public $ModifiedBlockValues;
01469 
01470     /// Stores the filename
01471     public $FileName;
01472 
01473     /// The root of all ini files
01474     public $RootDir;
01475 
01476     /// Whether to use the text codec when reading the ini file or not
01477     public $UseTextCodec;
01478 
01479     /// Stores the path and filename of the value cache file
01480     public $CacheFile;
01481 
01482     /// Stores the path and filename of the placement cache file
01483     public $PlacementCacheFile;
01484 
01485     /// true if cache should be used
01486     public $UseCache;
01487 
01488     /// true if the overrides should only be changed locally
01489     public $UseLocalOverrides;
01490 
01491     /// Contains the override dirs, if in local mode
01492     public $LocalOverrideDirArray;
01493 
01494     /// If \c true then all file loads are done directly on the filename.
01495     public $DirectAccess;
01496 
01497     /// If \c true empty element will be created in the beginning of array if it is defined in this ini file.
01498     public $AddArrayDefinition;
01499 
01500     /// If \c true eZINI will check each setting (before saving) for correspondence of settings in site.ini[eZINISetting].ReadonlySettingList
01501     public $ReadOnlySettingsCheck = true;
01502 
01503 }
01504 
01505 ?>