Oracle Enterprise Manager 11g

Oracle Enterprise Manager,Oracle veritabanı için kullandığımız grafik kullanıcı arayüzüne sahip,web tabanlı bir uygulamadır.Oracle Enterprise Manager ile objeler oluşturabilir,yetkileri yönetebilir,yedek alabilir,veri taşıyabilir,performas izleyebilir ve hata tespiti gibi işleri arayüz sayesinde çok kolay bir şekilde yaparız.Oracle Enterprise Manager,Oracle veritabanı ile gelen ücretsiz bir uygulamadır.

Oracle Enterprise Manager,Oracle veritabanı kurulurken de kurabiliriz daha sonradan da kurabiliriz veya benzer şekilde sonradan da kaldırabiliriz.

Veritabanında Oracle Enterprise Manager kurulumu yapılırsa,ORACLE_HOME dizini altında birtakım dizinler dizinler oluşturulur.Oracle enterprise manager ile gelen araçlar(emctl,emca vb.)$ORACLE_HOME/bin dizini altında oluşturulur.

Oracle Enterprise Manager’ı veritabanı kurulumu yaparken kurmadıysak dbca(database configuration asistant) ile de kurabiliriz emca(enterprise manager configuration asistant) aracı ile de komut satırından kurabiliriz.

Oracle veritabanı kurarken Oracle Enterprise Manager’ı kurmadıysak veya kurup kaldırdıysak ve şimdi Oracle Enterprise Manager kurmak istersek aşağıdaki gibi EMCA ile Oracle Enterprise Manager oluşturabiliriz.
(devamı..)

Loading


RMAN 3

Yedek Bilgilerini Görme

Alınan yedekleri data dictionary view’leri ile sorgulayarak öğrenebileceğimiz gibi LIST ve REPORT komutu ile RMAN üzerindede rapolayabiliriz.

1.List Komutu

RMAN ile alınan yedekler özel bir formatta saklanır. RMAN ile oluşturulan dosyaların ismine bakarak, hangi tarihe neye istinâden yedek alındığını bulmak biraz güç olabiliyor. Bunun için aşağıdaki komutları kullanmak uygun olacaktır.

  • Alınan yedeklerin tam olarak içeriğini görmek:
RMAN> LIST BACKUP;
  • Alınan yedeklerin özet bilgisini görmek:
RMAN> LIST BACKUP SUMMARY;
  • Image copy olarak alınan yedekleri aşağıdaki gibi görebiliriz.
RMAN> LIST COPY;
  • Sadece archivelog yedeklerini aşağıdaki gibi görebiliriz.
RMAN> LIST ARCHIVELOG ALL;
  • Belirli bir datafile yedeklerini listeleyebiliriz.
RMAN> LIST BACKUP OF DATAFILE 3;
  • Hangi dosyanın hangi yedek parçası (backup piece) içinde olduğunu görmek:
RMAN> LIST BACKUP OF DATABASE;
  • Bir önceki komutu belirli bir tarih aralığında girerek kullanmak:
RMAN> LIST BACKUP OF DATABASE BETWEEN '01-ARP-2008' AND '28-JUN-2008';
  • Alınan yedeklerin taşıdığı dosyaları görmek:
RMAN> LIST BACKUP BY FILE;

(devamı..)

Loading


RMAN 2

RMAN İLE YEDEK ALMAK

RMAN, aldığı yedekleri sadece kendisinin anladığı bir formatta tutuyor. RMAN’in oluşturduğu bir yedek setini (backupset) unzip edip dilediğiniz gibi kullanma şansına sahip değilsiniz. RMAN ile alınan bir yedek varsa; yedekten dönüş kısmı yine RMAN ile yapılmak zorunda.

Rman,aşağıdaki dosya tiplerinin yedeğini alabilmektedir.

  • Data file
  • Control file
  • Archive log
  • SPfile
  • Backup Piece(Daha önce alınmış yedek dosyaları)

RMAN,online rede log dosyalarını yedeklemez.Online redo log dosyalarını yedeklemenin en güzel yolu veritabanı yedeğinden sonra ‘alter system switch logfile’ komutunu çalıştırarak yeni bir arşiv dosyası oluşturmak ve sonrasında arşiv log dosyalarının yedeğini almak.

NOT : RMAN kullanmak istiyorsak veritabanınızın ARCHIVELOG modunda olması gerekmektedir.

NOT : RMAN yedeğinin nereye alınacağını belirtmessek default olarak FRA lokasyonu kullanır.

1.Tüm Veritabanının Yedeginin Alınması

RMAN ile bağlantı kurduktan sonra, aşağıdaki komutu girerek database’in tam bir yedeğini almanız mümkündür:

RMAN> backup database;

RMAN’de 0 ve 1 olmak üzere 2 yedek alma seviyesi vardır.0,tam(full) veritabanı yedeği alınacağını,1 ise artan(incremental) yedek alınacağını belirler.

RMAN> backup incremental level=0 database;

Tüm veritabanı ile birlikte archive log dosyalarının da yedeğini aşağıdaki komut ile alabiliriz.Bu komut ile bütün data file’leri,yedek başlama anına kadar olan tüm archivelog dosyalarını ve yedek esnasında oluşan tüm archive log dosyalarının yedeği alınır.

RMAN> backup incremental level=0 database plus archivelog;

RMAN veritabanı yedeğini yukarıdaki gibi(default) backupset olarak alırken sadece kullanılan blokların yedeği alınır.Bundan dolayı bir data file’ın boyutu yedek dosyasının(backup piece) boyutundan daha büyüktür.Çünkü backupset yedek alırken kullanılmayan blokların yedeğini almayız.RMAN aynı zamanda datafile’ı byte byte bire bir kopyasınıda yedek olarak alabilmektedir.Bu şekilde alınan yedekler image copy yedek olarak bilinir.

RMAN default olarak yedekleri backupset olarak alır.İstenilirse ‘AS BACKUPSET’ kelimesiyle özellikle yedeğin backupset olarak alınacağını aşağıdaki gibi belirtebiliriz.

RMAN> backup as backup database;

Image copy yedek almayı düşünüyorsak,komutumuz aşağıdaki gibi olmalıdır.

RMAN> backup as copy database;

(devamı..)

Loading


RMAN 1

Merhaba arkadaşlar bu yazımda RMAN’den bahsedecegim.RMAN ile ilgili teknik yazıya geçmeden önce bu yazıyı hazırlarken çok fazla yararlandıgım ve çok fazla yararını gördügüm dökümanlardan bahsetmek istiyorum.Bunlardan birincisi Talip hoca’nın(Talip Hakan Öztürk) ”Oracle Database 11g R2 İleri Veritabanı Yönetimi” adlı çok yararlandıgım ve çok begendim kitap,kitap türkçe ve çok güzel anlatılmış herkese tavsiye ederim  ve bu yazı aracılıgı ile de böyle bir kitap için Talip hoca’ya teşekür ederim.İkinci kaynak olarak Çagatay hoca’nın(Çagatay Çebi) RMAN ile ilgili makalesi,Çagatay hoca her zaman takip ettigim sınırlı türkçe bloklardandır ve makalelerini çok açıklayıcı ve yararlı bulurum herkese tavsiye ederim. Üçüncü olarak Ugur hoca’nın(Ugur İnce) RMAN ile ilgili makalesinden çok yararlandım ve özelliklede RMAN’ın avantajları kısmını okumanızı tavsiye ederim.Dördüncü olarak da RMAN ile ilgili daha ayrıntılı bilgilere ihtiyacınız olursa benimde yararlandıgım Robert Freeman ve Matthew Hart’ın yazdıgı ”Oracle RMAN 11g Backup and Recovery” adlı kitabını öneririm RMAN’i baştan aşagı anlatan güzel bir kitap.

RMAN (Recovery Manager), Oracle’in sunduğu bir yedek alma ve kurtarma aracıdır. RMAN aracı Oracle veritabanı 8 ile birlikte gelmeye başlamıştır ve her veritabanı versiyonu ile birlikte güçlenmiştir. RMAN’i diğer yöntemlere göre farklı kılan; DBA üzerindeki iş yükünü hafifletmisidir.RMAN yedek almayla ilgili birçok işi otomatik yapabilme imkanı sunar.

RMAN (Oracle Recovery Manager) Oracle tarafından ücretsiz olarak (bundle) sunulan ve veritabanızın yedeklenmesi sağlayan bir yazılımdır. Bu yazılımı hem CLI yani command line ortamından kullanabileceğiniz gibi hem de Enterprise Manager üzerinden de çalıştırabilirsiniz. RMAN aracını veritabanımızın çalıştığı sunucu üzerinde kullanabileceğimiz gibi client bilgisayar üzerinden de kullanabiliriz.Client üzerinden kullanıyorsak dikkat etmemiz gereken nokta RMAN bağlantılarının dedicated olmasıdır.Bunun için de TNSNAMES.ORA dosyasında SERVER=DEDICATED olarak set edilmelidir.

RMAN’ın diğer backup yöntemlerine göre avantajları :

  • Kullanılmayan blokların atlanması: Bir tabloda daha önceden yazılı olmayan bloklar (High Water Mark(HWM) üstünde kalan bloklar gibi) yedeklenmez. Geleneksel yedeklemede hangi bloğun kullanıldığı bilinmediğinden bu atlama işi olamaz.
  • Yedeğin sıkıştırılması(Compression): Oracle 11g ile gelen bir özelliktir.Alınan yedekleri isteğe bağlı olarak sıkıştırabiliriz.
  •  Veritabanı yedeklerini açma: Backup alma işlemlerini daha basite indirger. Örneğin hotbackup almak için tablespace’leri backup mode’a çekeyim; sonra tekrar normal mode’a alırım gibi dertleriniz olmaz.alter tablespace …. begin/end backup cümleleri kullanmaya gerek kalmadan tablespace yedeklemesi kolayca yapılabilir.
  • Gerçek artalan(incremental) yedekleme: Geri kurtarma esnasındaki süreyi kısaltmak için en son yedekten sonraki değişmeyen yedekler yedek setine yazılmaz. Böylece, CPU süresi, I/O süresi ve disk alanında performans sağlanır. RMAN, geri yükleme ve kurtarma işlemlerinde artalan güncelli yedekleri kullanır.
  • Blok seviyesinde geri kurtarma: Downtime süresini düşürmek için Oracle blok seviyesinde geri kurtarmayı destekler. Bir tablespace, sadece bozulmuş blokların onarma işlemi seviyesinde kapalı kalmaz.
  • Çoklu I/O kanalları: Veritabanı server’imizin donanım altyapısına göre RMAN birden fazla kullanabilir bu da bizim işlem performansımızı arttırır.
  • Platform bağımsız: RMAN her türlü donanım ve işletim sistemi üzerinde aynı komutlarla kullanılır. RMAN sayesinde işletim sisteminden bağımsız yani cross-platform ‘da çalışabilir. Örnek olarak Windows tabanlı bir veritabanı sunucusunda alınan RMAN backupları rahatlıkla Linux/Unix platformundaki veritabanı sucunularına veya tersi şekilde aktarılabilir.
  • Kataloglama: Tüm RMAN kayıtları hedef bir veritabanı kontrol dosyası içinde kayıt edilir. Manuel takibe gore avantaj sağlar.Kataloglama ile merkezi tek bir noktadan düzinelerce veritabanına bağlanabilir; her birini yedekleyebilirsiniz. Merkezi kontrol söz konusudur; tek tek her makinede script yazmanız gerekmez. Bir sunucu belirler, her şeyi oradan yapabilirsiniz.
  • Şifreli Yedekleme: Oracle 11g sürümü ile yedekleri şifreli olarak saklama imkanı vardır.
  • Arşiv üretmez : RMAN hotbackup şeklinde veritabanı açıkken alınan yedeklerde ekstra arşiv üretmez.(Gerçekten ekstra arşiv üretmiyor ama yüklü işlemler söz konusu ise hız düşüşü yaşanıyor.)
  • RMAN Konfigurasyonları : RMAN konfigürasyonlarını yapılandırarak yedekleme stratijimizi otomatikleştirebildiğimiz gibi işlemlerimizi tekrar tekrar yapmamızı engeller.

(devamı..)

Loading


test202


* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/

/**
* Required for error handling
*/
require_once ‘PEAR.php’;
require_once ‘PEAR/Registry.php’;
require_once ‘PEAR/Installer/Role.php’;
require_once ‘System.php’;

/**
* Last created PEAR_Config instance.
* @var object
*/
$GLOBALS[‘_PEAR_Config_instance’] = null;
if (!defined(‘PEAR_INSTALL_DIR’) || !PEAR_INSTALL_DIR) {
$PEAR_INSTALL_DIR = PHP_LIBDIR . DIRECTORY_SEPARATOR . ‘pear’;
} else {
$PEAR_INSTALL_DIR = PEAR_INSTALL_DIR;
}

// Below we define constants with default values for all configuration
// parameters except username/password. All of them can have their
// defaults set through environment variables. The reason we use the
// PHP_ prefix is for some security, PHP protects environment
// variables starting with PHP_*.

// default channel and preferred mirror is based on whether we are invoked through
// the “pear” or the “pecl” command
if (!defined(‘PEAR_RUNTYPE’)) {
define(‘PEAR_RUNTYPE’, ‘pear’);
}

if (PEAR_RUNTYPE == ‘pear’) {
define(‘PEAR_CONFIG_DEFAULT_CHANNEL’, ‘pear.php.net’);
} else {
define(‘PEAR_CONFIG_DEFAULT_CHANNEL’, ‘pecl.php.net’);
}

if (getenv(‘PHP_PEAR_SYSCONF_DIR’)) {
define(‘PEAR_CONFIG_SYSCONFDIR’, getenv(‘PHP_PEAR_SYSCONF_DIR’));
} elseif (getenv(‘SystemRoot’)) {
define(‘PEAR_CONFIG_SYSCONFDIR’, getenv(‘SystemRoot’));
} else {
define(‘PEAR_CONFIG_SYSCONFDIR’, PHP_SYSCONFDIR . ‘/pear’);
}

// Default for master_server
if (getenv(‘PHP_PEAR_MASTER_SERVER’)) {
define(‘PEAR_CONFIG_DEFAULT_MASTER_SERVER’, getenv(‘PHP_PEAR_MASTER_SERVER’));
} else {
define(‘PEAR_CONFIG_DEFAULT_MASTER_SERVER’, ‘pear.php.net’);
}

// Default for http_proxy
if (getenv(‘PHP_PEAR_HTTP_PROXY’)) {
define(‘PEAR_CONFIG_DEFAULT_HTTP_PROXY’, getenv(‘PHP_PEAR_HTTP_PROXY’));
} elseif (getenv(‘http_proxy’)) {
define(‘PEAR_CONFIG_DEFAULT_HTTP_PROXY’, getenv(‘http_proxy’));
} else {
define(‘PEAR_CONFIG_DEFAULT_HTTP_PROXY’, ”);
}

// Default for php_dir
if (getenv(‘PHP_PEAR_INSTALL_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_PHP_DIR’, getenv(‘PHP_PEAR_INSTALL_DIR’));
} else {
if (@file_exists($PEAR_INSTALL_DIR) && is_dir($PEAR_INSTALL_DIR)) {
define(‘PEAR_CONFIG_DEFAULT_PHP_DIR’, $PEAR_INSTALL_DIR);
} else {
define(‘PEAR_CONFIG_DEFAULT_PHP_DIR’, $PEAR_INSTALL_DIR);
}
}

// Default for metadata_dir
if (getenv(‘PHP_PEAR_METADATA_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_METADATA_DIR’, getenv(‘PHP_PEAR_METADATA_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_METADATA_DIR’, ”);
}

// Default for ext_dir
if (getenv(‘PHP_PEAR_EXTENSION_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_EXT_DIR’, getenv(‘PHP_PEAR_EXTENSION_DIR’));
} else {
if (ini_get(‘extension_dir’)) {
define(‘PEAR_CONFIG_DEFAULT_EXT_DIR’, ini_get(‘extension_dir’));
} elseif (defined(‘PEAR_EXTENSION_DIR’) &&
file_exists(PEAR_EXTENSION_DIR) && is_dir(PEAR_EXTENSION_DIR)) {
define(‘PEAR_CONFIG_DEFAULT_EXT_DIR’, PEAR_EXTENSION_DIR);
} elseif (defined(‘PHP_EXTENSION_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_EXT_DIR’, PHP_EXTENSION_DIR);
} else {
define(‘PEAR_CONFIG_DEFAULT_EXT_DIR’, ‘.’);
}
}

// Default for doc_dir
if (getenv(‘PHP_PEAR_DOC_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_DOC_DIR’, getenv(‘PHP_PEAR_DOC_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_DOC_DIR’,
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.’docs’);
}

// Default for bin_dir
if (getenv(‘PHP_PEAR_BIN_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_BIN_DIR’, getenv(‘PHP_PEAR_BIN_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_BIN_DIR’, PHP_BINDIR);
}

// Default for data_dir
if (getenv(‘PHP_PEAR_DATA_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_DATA_DIR’, getenv(‘PHP_PEAR_DATA_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_DATA_DIR’,
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.’data’);
}

// Default for cfg_dir
if (getenv(‘PHP_PEAR_CFG_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_CFG_DIR’, getenv(‘PHP_PEAR_CFG_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_CFG_DIR’,
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.’cfg’);
}

// Default for www_dir
if (getenv(‘PHP_PEAR_WWW_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_WWW_DIR’, getenv(‘PHP_PEAR_WWW_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_WWW_DIR’,
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.’www’);
}

// Default for man_dir
if (getenv(‘PHP_PEAR_MAN_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_MAN_DIR’, getenv(‘PHP_PEAR_MAN_DIR’));
} else {
if (defined(‘PHP_MANDIR’)) { // Added in PHP5.3.7
define(‘PEAR_CONFIG_DEFAULT_MAN_DIR’, PHP_MANDIR);
} else {
define(‘PEAR_CONFIG_DEFAULT_MAN_DIR’, PHP_PREFIX . DIRECTORY_SEPARATOR .
‘local’ . DIRECTORY_SEPARATOR .’man’);
}
}

// Default for test_dir
if (getenv(‘PHP_PEAR_TEST_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_TEST_DIR’, getenv(‘PHP_PEAR_TEST_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_TEST_DIR’,
$PEAR_INSTALL_DIR.DIRECTORY_SEPARATOR.’tests’);
}

// Default for temp_dir
if (getenv(‘PHP_PEAR_TEMP_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_TEMP_DIR’, getenv(‘PHP_PEAR_TEMP_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_TEMP_DIR’,
System::tmpdir() . DIRECTORY_SEPARATOR . ‘pear’ .
DIRECTORY_SEPARATOR . ‘temp’);
}

// Default for cache_dir
if (getenv(‘PHP_PEAR_CACHE_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_CACHE_DIR’, getenv(‘PHP_PEAR_CACHE_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_CACHE_DIR’,
System::tmpdir() . DIRECTORY_SEPARATOR . ‘pear’ .
DIRECTORY_SEPARATOR . ‘cache’);
}

// Default for download_dir
if (getenv(‘PHP_PEAR_DOWNLOAD_DIR’)) {
define(‘PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR’, getenv(‘PHP_PEAR_DOWNLOAD_DIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR’,
System::tmpdir() . DIRECTORY_SEPARATOR . ‘pear’ .
DIRECTORY_SEPARATOR . ‘download’);
}

// Default for php_bin
if (getenv(‘PHP_PEAR_PHP_BIN’)) {
define(‘PEAR_CONFIG_DEFAULT_PHP_BIN’, getenv(‘PHP_PEAR_PHP_BIN’));
} else {
define(‘PEAR_CONFIG_DEFAULT_PHP_BIN’, PEAR_CONFIG_DEFAULT_BIN_DIR.
DIRECTORY_SEPARATOR.’php’.(OS_WINDOWS ? ‘.exe’ : ”));
}

// Default for verbose
if (getenv(‘PHP_PEAR_VERBOSE’)) {
define(‘PEAR_CONFIG_DEFAULT_VERBOSE’, getenv(‘PHP_PEAR_VERBOSE’));
} else {
define(‘PEAR_CONFIG_DEFAULT_VERBOSE’, 1);
}

// Default for preferred_state
if (getenv(‘PHP_PEAR_PREFERRED_STATE’)) {
define(‘PEAR_CONFIG_DEFAULT_PREFERRED_STATE’, getenv(‘PHP_PEAR_PREFERRED_STATE’));
} else {
define(‘PEAR_CONFIG_DEFAULT_PREFERRED_STATE’, ‘stable’);
}

// Default for umask
if (getenv(‘PHP_PEAR_UMASK’)) {
define(‘PEAR_CONFIG_DEFAULT_UMASK’, getenv(‘PHP_PEAR_UMASK’));
} else {
define(‘PEAR_CONFIG_DEFAULT_UMASK’, decoct(umask()));
}

// Default for cache_ttl
if (getenv(‘PHP_PEAR_CACHE_TTL’)) {
define(‘PEAR_CONFIG_DEFAULT_CACHE_TTL’, getenv(‘PHP_PEAR_CACHE_TTL’));
} else {
define(‘PEAR_CONFIG_DEFAULT_CACHE_TTL’, 3600);
}

// Default for sig_type
if (getenv(‘PHP_PEAR_SIG_TYPE’)) {
define(‘PEAR_CONFIG_DEFAULT_SIG_TYPE’, getenv(‘PHP_PEAR_SIG_TYPE’));
} else {
define(‘PEAR_CONFIG_DEFAULT_SIG_TYPE’, ‘gpg’);
}

// Default for sig_bin
if (getenv(‘PHP_PEAR_SIG_BIN’)) {
define(‘PEAR_CONFIG_DEFAULT_SIG_BIN’, getenv(‘PHP_PEAR_SIG_BIN’));
} else {
define(‘PEAR_CONFIG_DEFAULT_SIG_BIN’,
System::which(
‘gpg’, OS_WINDOWS ? ‘c:\gnupg\gpg.exe’ : ‘/usr/local/bin/gpg’));
}

// Default for sig_keydir
if (getenv(‘PHP_PEAR_SIG_KEYDIR’)) {
define(‘PEAR_CONFIG_DEFAULT_SIG_KEYDIR’, getenv(‘PHP_PEAR_SIG_KEYDIR’));
} else {
define(‘PEAR_CONFIG_DEFAULT_SIG_KEYDIR’,
PEAR_CONFIG_SYSCONFDIR . DIRECTORY_SEPARATOR . ‘pearkeys’);
}

/**
* This is a class for storing configuration data, keeping track of
* which are system-defined, user-defined or defaulted.
* @category pear
* @package PEAR
* @author Stig Bakken
* @author Greg Beaver
* @copyright 1997-2009 The Authors
* @license http://opensource.org/licenses/bsd-license.php New BSD License
* @version Release: 1.10.12
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Config extends PEAR
{
/**
* Array of config files used.
*
* @var array layer => config file
*/
var $files = array(
‘system’ => ”,
‘user’ => ”,
);

var $layers = array();

/**
* Configuration data, two-dimensional array where the first
* dimension is the config layer (‘user’, ‘system’ and ‘default’),
* and the second dimension is keyname => value.
*
* The order in the first dimension is important! Earlier
* layers will shadow later ones when a config value is
* requested (if a ‘user’ value exists, it will be returned first,
* then ‘system’ and finally ‘default’).
*
* @var array layer => array(keyname => value, …)
*/
var $configuration = array(
‘user’ => array(),
‘system’ => array(),
‘default’ => array(),
);

/**
* Configuration values that can be set for a channel
*
* All other configuration values can only have a global value
* @var array
* @access private
*/
var $_channelConfigInfo = array(
‘php_dir’, ‘ext_dir’, ‘doc_dir’, ‘bin_dir’, ‘data_dir’, ‘cfg_dir’,
‘test_dir’, ‘www_dir’, ‘php_bin’, ‘php_prefix’, ‘php_suffix’, ‘username’,
‘password’, ‘verbose’, ‘preferred_state’, ‘umask’, ‘preferred_mirror’, ‘php_ini’
);

/**
* Channels that can be accessed
* @see setChannels()
* @var array
* @access private
*/
var $_channels = array(‘pear.php.net’, ‘pecl.php.net’, ‘__uri’);

/**
* This variable is used to control the directory values returned
* @see setInstallRoot();
* @var string|false
* @access private
*/
var $_installRoot = false;

/**
* If requested, this will always refer to the registry
* contained in php_dir
* @var PEAR_Registry
*/
var $_registry = array();

/**
* @var array
* @access private
*/
var $_regInitialized = array();

/**
* @var bool
* @access private
*/
var $_noRegistry = false;

/**
* amount of errors found while parsing config
* @var integer
* @access private
*/
var $_errorsFound = 0;
var $_lastError = null;

/**
* Information about the configuration data. Stores the type,
* default value and a documentation string for each configuration
* value.
*
* @var array layer => array(infotype => value, …)
*/
var $configuration_info = array(
// Channels/Internet Access
‘default_channel’ => array(
‘type’ => ‘string’,
‘default’ => PEAR_CONFIG_DEFAULT_CHANNEL,
‘doc’ => ‘the default channel to use for all non explicit commands’,
‘prompt’ => ‘Default Channel’,
‘group’ => ‘Internet Access’,
),
‘preferred_mirror’ => array(
‘type’ => ‘string’,
‘default’ => PEAR_CONFIG_DEFAULT_CHANNEL,
‘doc’ => ‘the default server or mirror to use for channel actions’,
‘prompt’ => ‘Default Channel Mirror’,
‘group’ => ‘Internet Access’,
),
‘remote_config’ => array(
‘type’ => ‘password’,
‘default’ => ”,
‘doc’ => ‘ftp url of remote configuration file to use for synchronized install’,
‘prompt’ => ‘Remote Configuration File’,
‘group’ => ‘Internet Access’,
),
‘auto_discover’ => array(
‘type’ => ‘integer’,
‘default’ => 0,
‘doc’ => ‘whether to automatically discover new channels’,
‘prompt’ => ‘Auto-discover new Channels’,
‘group’ => ‘Internet Access’,
),
// Internet Access
‘master_server’ => array(
‘type’ => ‘string’,
‘default’ => ‘pear.php.net’,
‘doc’ => ‘name of the main PEAR server [NOT USED IN THIS VERSION]’,
‘prompt’ => ‘PEAR server [DEPRECATED]’,
‘group’ => ‘Internet Access’,
),
‘http_proxy’ => array(
‘type’ => ‘string’,
‘default’ => PEAR_CONFIG_DEFAULT_HTTP_PROXY,
‘doc’ => ‘HTTP proxy (host:port) to use when downloading packages’,
‘prompt’ => ‘HTTP Proxy Server Address’,
‘group’ => ‘Internet Access’,
),
// File Locations
‘php_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_PHP_DIR,
‘doc’ => ‘directory where .php files are installed’,
‘prompt’ => ‘PEAR directory’,
‘group’ => ‘File Locations’,
),
‘ext_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_EXT_DIR,
‘doc’ => ‘directory where loadable extensions are installed’,
‘prompt’ => ‘PHP extension directory’,
‘group’ => ‘File Locations’,
),
‘doc_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_DOC_DIR,
‘doc’ => ‘directory where documentation is installed’,
‘prompt’ => ‘PEAR documentation directory’,
‘group’ => ‘File Locations’,
),
‘bin_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_BIN_DIR,
‘doc’ => ‘directory where executables are installed’,
‘prompt’ => ‘PEAR executables directory’,
‘group’ => ‘File Locations’,
),
‘data_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_DATA_DIR,
‘doc’ => ‘directory where data files are installed’,
‘prompt’ => ‘PEAR data directory’,
‘group’ => ‘File Locations (Advanced)’,
),
‘cfg_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_CFG_DIR,
‘doc’ => ‘directory where modifiable configuration files are installed’,
‘prompt’ => ‘PEAR configuration file directory’,
‘group’ => ‘File Locations (Advanced)’,
),
‘www_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_WWW_DIR,
‘doc’ => ‘directory where www frontend files (html/js) are installed’,
‘prompt’ => ‘PEAR www files directory’,
‘group’ => ‘File Locations (Advanced)’,
),
‘man_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_MAN_DIR,
‘doc’ => ‘directory where unix manual pages are installed’,
‘prompt’ => ‘Systems manpage files directory’,
‘group’ => ‘File Locations (Advanced)’,
),
‘test_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_TEST_DIR,
‘doc’ => ‘directory where regression tests are installed’,
‘prompt’ => ‘PEAR test directory’,
‘group’ => ‘File Locations (Advanced)’,
),
‘cache_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_CACHE_DIR,
‘doc’ => ‘directory which is used for web service cache’,
‘prompt’ => ‘PEAR Installer cache directory’,
‘group’ => ‘File Locations (Advanced)’,
),
‘temp_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_TEMP_DIR,
‘doc’ => ‘directory which is used for all temp files’,
‘prompt’ => ‘PEAR Installer temp directory’,
‘group’ => ‘File Locations (Advanced)’,
),
‘download_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_DOWNLOAD_DIR,
‘doc’ => ‘directory which is used for all downloaded files’,
‘prompt’ => ‘PEAR Installer download directory’,
‘group’ => ‘File Locations (Advanced)’,
),
‘php_bin’ => array(
‘type’ => ‘file’,
‘default’ => PEAR_CONFIG_DEFAULT_PHP_BIN,
‘doc’ => ‘PHP CLI/CGI binary for executing scripts’,
‘prompt’ => ‘PHP CLI/CGI binary’,
‘group’ => ‘File Locations (Advanced)’,
),
‘php_prefix’ => array(
‘type’ => ‘string’,
‘default’ => ”,
‘doc’ => ‘–program-prefix for php_bin\’s ./configure, used for pecl installs’,
‘prompt’ => ‘–program-prefix passed to PHP\’s ./configure’,
‘group’ => ‘File Locations (Advanced)’,
),
‘php_suffix’ => array(
‘type’ => ‘string’,
‘default’ => ”,
‘doc’ => ‘–program-suffix for php_bin\’s ./configure, used for pecl installs’,
‘prompt’ => ‘–program-suffix passed to PHP\’s ./configure’,
‘group’ => ‘File Locations (Advanced)’,
),
‘php_ini’ => array(
‘type’ => ‘file’,
‘default’ => ”,
‘doc’ => ‘location of php.ini in which to enable PECL extensions on install’,
‘prompt’ => ‘php.ini location’,
‘group’ => ‘File Locations (Advanced)’,
),
‘metadata_dir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_METADATA_DIR,
‘doc’ => ‘directory where metadata files are installed (registry, filemap, channels, …)’,
‘prompt’ => ‘PEAR metadata directory’,
‘group’ => ‘File Locations (Advanced)’,
),
// Maintainers
‘username’ => array(
‘type’ => ‘string’,
‘default’ => ”,
‘doc’ => ‘(maintainers) your PEAR account name’,
‘prompt’ => ‘PEAR username (for maintainers)’,
‘group’ => ‘Maintainers’,
),
‘password’ => array(
‘type’ => ‘password’,
‘default’ => ”,
‘doc’ => ‘(maintainers) your PEAR account password’,
‘prompt’ => ‘PEAR password (for maintainers)’,
‘group’ => ‘Maintainers’,
),
// Advanced
‘verbose’ => array(
‘type’ => ‘integer’,
‘default’ => PEAR_CONFIG_DEFAULT_VERBOSE,
‘doc’ => ‘verbosity level
0: really quiet
1: somewhat quiet
2: verbose
3: debug’,
‘prompt’ => ‘Debug Log Level’,
‘group’ => ‘Advanced’,
),
‘preferred_state’ => array(
‘type’ => ‘set’,
‘default’ => PEAR_CONFIG_DEFAULT_PREFERRED_STATE,
‘doc’ => ‘the installer will prefer releases with this state when installing packages without a version or state specified’,
‘valid_set’ => array(
‘stable’, ‘beta’, ‘alpha’, ‘devel’, ‘snapshot’),
‘prompt’ => ‘Preferred Package State’,
‘group’ => ‘Advanced’,
),
‘umask’ => array(
‘type’ => ‘mask’,
‘default’ => PEAR_CONFIG_DEFAULT_UMASK,
‘doc’ => ‘umask used when creating files (Unix-like systems only)’,
‘prompt’ => ‘Unix file mask’,
‘group’ => ‘Advanced’,
),
‘cache_ttl’ => array(
‘type’ => ‘integer’,
‘default’ => PEAR_CONFIG_DEFAULT_CACHE_TTL,
‘doc’ => ‘amount of secs where the local cache is used and not updated’,
‘prompt’ => ‘Cache TimeToLive’,
‘group’ => ‘Advanced’,
),
‘sig_type’ => array(
‘type’ => ‘set’,
‘default’ => PEAR_CONFIG_DEFAULT_SIG_TYPE,
‘doc’ => ‘which package signature mechanism to use’,
‘valid_set’ => array(‘gpg’),
‘prompt’ => ‘Package Signature Type’,
‘group’ => ‘Maintainers’,
),
‘sig_bin’ => array(
‘type’ => ‘string’,
‘default’ => PEAR_CONFIG_DEFAULT_SIG_BIN,
‘doc’ => ‘which package signature mechanism to use’,
‘prompt’ => ‘Signature Handling Program’,
‘group’ => ‘Maintainers’,
),
‘sig_keyid’ => array(
‘type’ => ‘string’,
‘default’ => ”,
‘doc’ => ‘which key to use for signing with’,
‘prompt’ => ‘Signature Key Id’,
‘group’ => ‘Maintainers’,
),
‘sig_keydir’ => array(
‘type’ => ‘directory’,
‘default’ => PEAR_CONFIG_DEFAULT_SIG_KEYDIR,
‘doc’ => ‘directory where signature keys are located’,
‘prompt’ => ‘Signature Key Directory’,
‘group’ => ‘Maintainers’,
),
// __channels is reserved – used for channel-specific configuration
);

/**
* Constructor.
*
* @param string file to read user-defined options from
* @param string file to read system-wide defaults from
* @param bool determines whether a registry object “follows”
* the value of php_dir (is automatically created
* and moved when php_dir is changed)
* @param bool if true, fails if configuration files cannot be loaded
*
* @access public
*
* @see PEAR_Config::singleton
*/
function __construct($user_file = ”, $system_file = ”, $ftp_file = false,
$strict = true)
{
parent::__construct();
PEAR_Installer_Role::initializeConfig($this);
$sl = DIRECTORY_SEPARATOR;
if (empty($user_file)) {
if (OS_WINDOWS) {
$user_file = PEAR_CONFIG_SYSCONFDIR . $sl . ‘pear.ini’;
} else {
$user_file = getenv(‘HOME’) . $sl . ‘.pearrc’;
}
}

if (empty($system_file)) {
$system_file = PEAR_CONFIG_SYSCONFDIR . $sl;
if (OS_WINDOWS) {
$system_file .= ‘pearsys.ini’;
} else {
$system_file .= ‘pear.conf’;
}
}

$this->layers = array_keys($this->configuration);
$this->files[‘user’] = $user_file;
$this->files[‘system’] = $system_file;
if ($user_file && file_exists($user_file)) {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$this->readConfigFile($user_file, ‘user’, $strict);
$this->popErrorHandling();
if ($this->_errorsFound > 0) {
return;
}
}

if ($system_file && @file_exists($system_file)) {
$this->mergeConfigFile($system_file, false, ‘system’, $strict);
if ($this->_errorsFound > 0) {
return;
}

}

if (!$ftp_file) {
$ftp_file = $this->get(‘remote_config’);
}

if ($ftp_file && defined(‘PEAR_REMOTEINSTALL_OK’)) {
$this->readFTPConfigFile($ftp_file);
}

foreach ($this->configuration_info as $key => $info) {
$this->configuration[‘default’][$key] = $info[‘default’];
}

$this->_registry[‘default’] = new PEAR_Registry(
$this->configuration[‘default’][‘php_dir’], false, false,
$this->configuration[‘default’][‘metadata_dir’]);
$this->_registry[‘default’]->setConfig($this, false);
$this->_regInitialized[‘default’] = false;
//$GLOBALS[‘_PEAR_Config_instance’] = &$this;
}

/**
* Return the default locations of user and system configuration files
*/
public static function getDefaultConfigFiles()
{
$sl = DIRECTORY_SEPARATOR;
if (OS_WINDOWS) {
return array(
‘user’ => PEAR_CONFIG_SYSCONFDIR . $sl . ‘pear.ini’,
‘system’ => PEAR_CONFIG_SYSCONFDIR . $sl . ‘pearsys.ini’
);
}

return array(
‘user’ => getenv(‘HOME’) . $sl . ‘.pearrc’,
‘system’ => PEAR_CONFIG_SYSCONFDIR . $sl . ‘pear.conf’
);
}

/**
* Static singleton method. If you want to keep only one instance
* of this class in use, this method will give you a reference to
* the last created PEAR_Config object if one exists, or create a
* new object.
*
* @param string (optional) file to read user-defined options from
* @param string (optional) file to read system-wide defaults from
*
* @return object an existing or new PEAR_Config instance
*
* @see PEAR_Config::PEAR_Config
*/
public static function &singleton($user_file = ”, $system_file = ”, $strict = true)
{
if (is_object($GLOBALS[‘_PEAR_Config_instance’])) {
return $GLOBALS[‘_PEAR_Config_instance’];
}

$t_conf = new PEAR_Config($user_file, $system_file, false, $strict);
if ($t_conf->_errorsFound > 0) {
return $t_conf->lastError;
}

$GLOBALS[‘_PEAR_Config_instance’] = &$t_conf;
return $GLOBALS[‘_PEAR_Config_instance’];
}

/**
* Determine whether any configuration files have been detected, and whether a
* registry object can be retrieved from this configuration.
* @return bool
* @since PEAR 1.4.0a1
*/
function validConfiguration()
{
if ($this->isDefinedLayer(‘user’) || $this->isDefinedLayer(‘system’)) {
return true;
}

return false;
}

/**
* Reads configuration data from a file. All existing values in
* the config layer are discarded and replaced with data from the
* file.
* @param string file to read from, if NULL or not specified, the
* last-used file for the same layer (second param) is used
* @param string config layer to insert data into (‘user’ or ‘system’)
* @return bool TRUE on success or a PEAR error on failure
*/
function readConfigFile($file = null, $layer = ‘user’, $strict = true)
{
if (empty($this->files[$layer])) {
return $this->raiseError(“unknown config layer `$layer'”);
}

if ($file === null) {
$file = $this->files[$layer];
}

$data = $this->_readConfigDataFrom($file);
if (PEAR::isError($data)) {
if (!$strict) {
return true;
}

$this->_errorsFound++;
$this->lastError = $data;

return $data;
}

$this->files[$layer] = $file;
$this->_decodeInput($data);
$this->configuration[$layer] = $data;
$this->_setupChannels();
if (!$this->_noRegistry && ($phpdir = $this->get(‘php_dir’, $layer, ‘pear.php.net’))) {
$this->_registry[$layer] = new PEAR_Registry(
$phpdir, false, false,
$this->get(‘metadata_dir’, $layer, ‘pear.php.net’));
$this->_registry[$layer]->setConfig($this, false);
$this->_regInitialized[$layer] = false;
} else {
unset($this->_registry[$layer]);
}
return true;
}

/**
* @param string url to the remote config file, like ftp://www.example.com/pear/config.ini
* @return true|PEAR_Error
*/
function readFTPConfigFile($path)
{
do { // poor man’s try
if (!class_exists(‘PEAR_FTP’)) {
if (!class_exists(‘PEAR_Common’)) {
require_once ‘PEAR/Common.php’;
}
if (PEAR_Common::isIncludeable(‘PEAR/FTP.php’)) {
require_once ‘PEAR/FTP.php’;
}
}

if (!class_exists(‘PEAR_FTP’)) {
return PEAR::raiseError(‘PEAR_RemoteInstaller must be installed to use remote config’);
}

$this->_ftp = new PEAR_FTP;
$this->_ftp->pushErrorHandling(PEAR_ERROR_RETURN);
$e = $this->_ftp->init($path);
if (PEAR::isError($e)) {
$this->_ftp->popErrorHandling();
return $e;
}

$tmp = System::mktemp(‘-d’);
PEAR_Common::addTempFile($tmp);
$e = $this->_ftp->get(basename($path), $tmp . DIRECTORY_SEPARATOR .
‘pear.ini’, false, FTP_BINARY);
if (PEAR::isError($e)) {
$this->_ftp->popErrorHandling();
return $e;
}

PEAR_Common::addTempFile($tmp . DIRECTORY_SEPARATOR . ‘pear.ini’);
$this->_ftp->disconnect();
$this->_ftp->popErrorHandling();
$this->files[‘ftp’] = $tmp . DIRECTORY_SEPARATOR . ‘pear.ini’;
$e = $this->readConfigFile(null, ‘ftp’);
if (PEAR::isError($e)) {
return $e;
}

$fail = array();
foreach ($this->configuration_info as $key => $val) {
if (in_array($this->getGroup($key),
array(‘File Locations’, ‘File Locations (Advanced)’)) &&
$this->getType($key) == ‘directory’) {
// any directory configs must be set for this to work
if (!isset($this->configuration[‘ftp’][$key])) {
$fail[] = $key;
}
}
}

if (!count($fail)) {
return true;
}

$fail = ‘”‘ . implode(‘”, “‘, $fail) . ‘”‘;
unset($this->files[‘ftp’]);
unset($this->configuration[‘ftp’]);
return PEAR::raiseError(‘ERROR: Ftp configuration file must set all ‘ .
‘directory configuration variables. These variables were not set: ‘ .
$fail);
} while (false); // poor man’s catch
unset($this->files[‘ftp’]);
return PEAR::raiseError(‘no remote host specified’);
}

/**
* Reads the existing configurations and creates the _channels array from it
*/
function _setupChannels()
{
$set = array_flip(array_values($this->_channels));
foreach ($this->configuration as $layer => $data) {
$i = 1000;
if (isset($data[‘__channels’]) && is_array($data[‘__channels’])) {
foreach ($data[‘__channels’] as $channel => $info) {
$set[$channel] = $i++;
}
}
}
$this->_channels = array_values(array_flip($set));
$this->setChannels($this->_channels);
}

function deleteChannel($channel)
{
$ch = strtolower($channel);
foreach ($this->configuration as $layer => $data) {
if (isset($data[‘__channels’]) && isset($data[‘__channels’][$ch])) {
unset($this->configuration[$layer][‘__channels’][$ch]);
}
}

$this->_channels = array_flip($this->_channels);
unset($this->_channels[$ch]);
$this->_channels = array_flip($this->_channels);
}

/**
* Merges data into a config layer from a file. Does the same
* thing as readConfigFile, except it does not replace all
* existing values in the config layer.
* @param string file to read from
* @param bool whether to overwrite existing data (default TRUE)
* @param string config layer to insert data into (‘user’ or ‘system’)
* @param string if true, errors are returned if file opening fails
* @return bool TRUE on success or a PEAR error on failure
*/
function mergeConfigFile($file, $override = true, $layer = ‘user’, $strict = true)
{
if (empty($this->files[$layer])) {
return $this->raiseError(“unknown config layer `$layer'”);
}

if ($file === null) {
$file = $this->files[$layer];
}

$data = $this->_readConfigDataFrom($file);
if (PEAR::isError($data)) {
if (!$strict) {
return true;
}

$this->_errorsFound++;
$this->lastError = $data;

return $data;
}

$this->_decodeInput($data);
if ($override) {
$this->configuration[$layer] =
PEAR_Config::arrayMergeRecursive($this->configuration[$layer], $data);
} else {
$this->configuration[$layer] =
PEAR_Config::arrayMergeRecursive($data, $this->configuration[$layer]);
}

$this->_setupChannels();
if (!$this->_noRegistry && ($phpdir = $this->get(‘php_dir’, $layer, ‘pear.php.net’))) {
$this->_registry[$layer] = new PEAR_Registry(
$phpdir, false, false,
$this->get(‘metadata_dir’, $layer, ‘pear.php.net’));
$this->_registry[$layer]->setConfig($this, false);
$this->_regInitialized[$layer] = false;
} else {
unset($this->_registry[$layer]);
}
return true;
}

/**
* @param array
* @param array
* @return array
*/
public static function arrayMergeRecursive($arr2, $arr1)
{
$ret = array();
foreach ($arr2 as $key => $data) {
if (!isset($arr1[$key])) {
$ret[$key] = $data;
unset($arr1[$key]);
continue;
}
if (is_array($data)) {
if (!is_array($arr1[$key])) {
$ret[$key] = $arr1[$key];
unset($arr1[$key]);
continue;
}
$ret[$key] = PEAR_Config::arrayMergeRecursive($arr1[$key], $arr2[$key]);
unset($arr1[$key]);
}
}

return array_merge($ret, $arr1);
}

/**
* Writes data into a config layer from a file.
*
* @param string|null file to read from, or null for default
* @param string config layer to insert data into (‘user’ or
* ‘system’)
* @param string|null data to write to config file or null for internal data [DEPRECATED]
* @return bool TRUE on success or a PEAR error on failure
*/
function writeConfigFile($file = null, $layer = ‘user’, $data = null)
{
$this->_lazyChannelSetup($layer);
if ($layer == ‘both’ || $layer == ‘all’) {
foreach ($this->files as $type => $file) {
$err = $this->writeConfigFile($file, $type, $data);
if (PEAR::isError($err)) {
return $err;
}
}
return true;
}

if (empty($this->files[$layer])) {
return $this->raiseError(“unknown config file type `$layer'”);
}

if ($file === null) {
$file = $this->files[$layer];
}

$data = ($data === null) ? $this->configuration[$layer] : $data;
$this->_encodeOutput($data);
$opt = array(‘-p’, dirname($file));
if (!@System::mkDir($opt)) {
return $this->raiseError(“could not create directory: ” . dirname($file));
}

if (file_exists($file) && is_file($file) && !is_writeable($file)) {
return $this->raiseError(“no write access to $file!”);
}

$fp = @fopen($file, “w”);
if (!$fp) {
return $this->raiseError(“PEAR_Config::writeConfigFile fopen(‘$file’,’w’) failed ($php_errormsg)”);
}

$contents = “#PEAR_Config 0.9\n” . serialize($data);
if (!@fwrite($fp, $contents)) {
return $this->raiseError(“PEAR_Config::writeConfigFile: fwrite failed ($php_errormsg)”);
}
return true;
}

/**
* Reads configuration data from a file and returns the parsed data
* in an array.
*
* @param string file to read from
* @return array configuration data or a PEAR error on failure
* @access private
*/
function _readConfigDataFrom($file)
{
$fp = false;
if (file_exists($file)) {
$fp = @fopen($file, “r”);
}

if (!$fp) {
return $this->raiseError(“PEAR_Config::readConfigFile fopen(‘$file’,’r’) failed”);
}

$size = filesize($file);
fclose($fp);
$contents = file_get_contents($file);
if (empty($contents)) {
return $this->raiseError(‘Configuration file “‘ . $file . ‘” is empty’);
}

$version = false;
if (preg_match(‘/^#PEAR_Config\s+(\S+)\s+/si’, $contents, $matches)) {
$version = $matches[1];
$contents = substr($contents, strlen($matches[0]));
} else {
// Museum config file
if (substr($contents,0,2) == ‘a:’) {
$version = ‘0.1’;
}
}

if ($version && version_compare(“$version”, ‘1’, ‘<')) { // no '@', it is possible that unserialize // raises a notice but it seems to block IO to // STDOUT if a '@' is used and a notice is raise $data = unserialize($contents); if (!is_array($data) && !$data) { if ($contents == serialize(false)) { $data = array(); } else { $err = $this->raiseError(“PEAR_Config: bad data in $file”);
return $err;
}
}
if (!is_array($data)) {
if (strlen(trim($contents)) > 0) {
$error = “PEAR_Config: bad data in $file”;
$err = $this->raiseError($error);
return $err;
}

$data = array();
}
// add parsing of newer formats here…
} else {
$err = $this->raiseError(“$file: unknown version `$version'”);
return $err;
}

return $data;
}

/**
* Gets the file used for storing the config for a layer
*
* @param string $layer ‘user’ or ‘system’
*/
function getConfFile($layer)
{
return $this->files[$layer];
}

/**
* @param string Configuration class name, used for detecting duplicate calls
* @param array information on a role as parsed from its xml file
* @return true|PEAR_Error
* @access private
*/
function _addConfigVars($class, $vars)
{
static $called = array();
if (isset($called[$class])) {
return;
}

$called[$class] = 1;
if (count($vars) > 3) {
return $this->raiseError(‘Roles can only define 3 new config variables or less’);
}

foreach ($vars as $name => $var) {
if (!is_array($var)) {
return $this->raiseError(‘Configuration information must be an array’);
}

if (!isset($var[‘type’])) {
return $this->raiseError(‘Configuration information must contain a type’);
} elseif (!in_array($var[‘type’],
array(‘string’, ‘mask’, ‘password’, ‘directory’, ‘file’, ‘set’))) {
return $this->raiseError(
‘Configuration type must be one of directory, file, string, ‘ .
‘mask, set, or password’);
}
if (!isset($var[‘default’])) {
return $this->raiseError(
‘Configuration information must contain a default value (“default” index)’);
}

if (is_array($var[‘default’])) {
$real_default = ”;
foreach ($var[‘default’] as $config_var => $val) {
if (strpos($config_var, ‘text’) === 0) {
$real_default .= $val;
} elseif (strpos($config_var, ‘constant’) === 0) {
if (!defined($val)) {
return $this->raiseError(
‘Unknown constant “‘ . $val . ‘” requested in ‘ .
‘default value for configuration variable “‘ .
$name . ‘”‘);
}

$real_default .= constant($val);
} elseif (isset($this->configuration_info[$config_var])) {
$real_default .=
$this->configuration_info[$config_var][‘default’];
} else {
return $this->raiseError(
‘Unknown request for “‘ . $config_var . ‘” value in ‘ .
‘default value for configuration variable “‘ .
$name . ‘”‘);
}
}
$var[‘default’] = $real_default;
}

if ($var[‘type’] == ‘integer’) {
$var[‘default’] = (integer) $var[‘default’];
}

if (!isset($var[‘doc’])) {
return $this->raiseError(
‘Configuration information must contain a summary (“doc” index)’);
}

if (!isset($var[‘prompt’])) {
return $this->raiseError(
‘Configuration information must contain a simple prompt (“prompt” index)’);
}

if (!isset($var[‘group’])) {
return $this->raiseError(
‘Configuration information must contain a simple group (“group” index)’);
}

if (isset($this->configuration_info[$name])) {
return $this->raiseError(‘Configuration variable “‘ . $name .
‘” already exists’);
}

$this->configuration_info[$name] = $var;
// fix bug #7351: setting custom config variable in a channel fails
$this->_channelConfigInfo[] = $name;
}

return true;
}

/**
* Encodes/scrambles configuration data before writing to files.
* Currently, ‘password’ values will be base64-encoded as to avoid
* that people spot cleartext passwords by accident.
*
* @param array (reference) array to encode values in
* @return bool TRUE on success
* @access private
*/
function _encodeOutput(&$data)
{
foreach ($data as $key => $value) {
if ($key == ‘__channels’) {
foreach ($data[‘__channels’] as $channel => $blah) {
$this->_encodeOutput($data[‘__channels’][$channel]);
}
}

if (!isset($this->configuration_info[$key])) {
continue;
}

$type = $this->configuration_info[$key][‘type’];
switch ($type) {
// we base64-encode passwords so they are at least
// not shown in plain by accident
case ‘password’: {
$data[$key] = base64_encode($data[$key]);
break;
}
case ‘mask’: {
$data[$key] = octdec($data[$key]);
break;
}
}
}

return true;
}

/**
* Decodes/unscrambles configuration data after reading from files.
*
* @param array (reference) array to encode values in
* @return bool TRUE on success
* @access private
*
* @see PEAR_Config::_encodeOutput
*/
function _decodeInput(&$data)
{
if (!is_array($data)) {
return true;
}

foreach ($data as $key => $value) {
if ($key == ‘__channels’) {
foreach ($data[‘__channels’] as $channel => $blah) {
$this->_decodeInput($data[‘__channels’][$channel]);
}
}

if (!isset($this->configuration_info[$key])) {
continue;
}

$type = $this->configuration_info[$key][‘type’];
switch ($type) {
case ‘password’: {
$data[$key] = base64_decode($data[$key]);
break;
}
case ‘mask’: {
$data[$key] = decoct($data[$key]);
break;
}
}
}

return true;
}

/**
* Retrieve the default channel.
*
* On startup, channels are not initialized, so if the default channel is not
* pear.php.net, then initialize the config.
* @param string registry layer
* @return string|false
*/
function getDefaultChannel($layer = null)
{
$ret = false;
if ($layer === null) {
foreach ($this->layers as $layer) {
if (isset($this->configuration[$layer][‘default_channel’])) {
$ret = $this->configuration[$layer][‘default_channel’];
break;
}
}
} elseif (isset($this->configuration[$layer][‘default_channel’])) {
$ret = $this->configuration[$layer][‘default_channel’];
}

if ($ret == ‘pear.php.net’ && defined(‘PEAR_RUNTYPE’) && PEAR_RUNTYPE == ‘pecl’) {
$ret = ‘pecl.php.net’;
}

if ($ret) {
if ($ret != ‘pear.php.net’) {
$this->_lazyChannelSetup();
}

return $ret;
}

return PEAR_CONFIG_DEFAULT_CHANNEL;
}

/**
* Returns a configuration value, prioritizing layers as per the
* layers property.
*
* @param string config key
* @return mixed the config value, or NULL if not found
* @access public
*/
function get($key, $layer = null, $channel = false)
{
if (!isset($this->configuration_info[$key])) {
return null;
}

if ($key == ‘__channels’) {
return null;
}

if ($key == ‘default_channel’) {
return $this->getDefaultChannel($layer);
}

if (!$channel) {
$channel = $this->getDefaultChannel();
} elseif ($channel != ‘pear.php.net’) {
$this->_lazyChannelSetup();
}
$channel = strtolower($channel);

$test = (in_array($key, $this->_channelConfigInfo)) ?
$this->_getChannelValue($key, $layer, $channel) :
null;
if ($test !== null) {
if ($this->_installRoot) {
if (in_array($this->getGroup($key),
array(‘File Locations’, ‘File Locations (Advanced)’)) &&
$this->getType($key) == ‘directory’) {
return $this->_prependPath($test, $this->_installRoot);
}
}
return $test;
}

if ($layer === null) {
foreach ($this->layers as $layer) {
if (isset($this->configuration[$layer][$key])) {
$test = $this->configuration[$layer][$key];
if ($this->_installRoot) {
if (in_array($this->getGroup($key),
array(‘File Locations’, ‘File Locations (Advanced)’)) &&
$this->getType($key) == ‘directory’) {
return $this->_prependPath($test, $this->_installRoot);
}
}

if ($key == ‘preferred_mirror’) {
$reg = &$this->getRegistry();
if (is_object($reg)) {
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $channel;
}

if (!$chan->getMirror($test) && $chan->getName() != $test) {
return $channel; // mirror does not exist
}
}
}
return $test;
}
}
} elseif (isset($this->configuration[$layer][$key])) {
$test = $this->configuration[$layer][$key];
if ($this->_installRoot) {
if (in_array($this->getGroup($key),
array(‘File Locations’, ‘File Locations (Advanced)’)) &&
$this->getType($key) == ‘directory’) {
return $this->_prependPath($test, $this->_installRoot);
}
}

if ($key == ‘preferred_mirror’) {
$reg = &$this->getRegistry();
if (is_object($reg)) {
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $channel;
}

if (!$chan->getMirror($test) && $chan->getName() != $test) {
return $channel; // mirror does not exist
}
}
}

return $test;
}

return null;
}

/**
* Returns a channel-specific configuration value, prioritizing layers as per the
* layers property.
*
* @param string config key
* @return mixed the config value, or NULL if not found
* @access private
*/
function _getChannelValue($key, $layer, $channel)
{
if ($key == ‘__channels’ || $channel == ‘pear.php.net’) {
return null;
}

$ret = null;
if ($layer === null) {
foreach ($this->layers as $ilayer) {
if (isset($this->configuration[$ilayer][‘__channels’][$channel][$key])) {
$ret = $this->configuration[$ilayer][‘__channels’][$channel][$key];
break;
}
}
} elseif (isset($this->configuration[$layer][‘__channels’][$channel][$key])) {
$ret = $this->configuration[$layer][‘__channels’][$channel][$key];
}

if ($key != ‘preferred_mirror’) {
return $ret;
}

if ($ret !== null) {
$reg = &$this->getRegistry($layer);
if (is_object($reg)) {
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $channel;
}

if (!$chan->getMirror($ret) && $chan->getName() != $ret) {
return $channel; // mirror does not exist
}
}

return $ret;
}

if ($channel != $this->getDefaultChannel($layer)) {
return $channel; // we must use the channel name as the preferred mirror
// if the user has not chosen an alternate
}

return $this->getDefaultChannel($layer);
}

/**
* Set a config value in a specific layer (defaults to ‘user’).
* Enforces the types defined in the configuration_info array. An
* integer config variable will be cast to int, and a set config
* variable will be validated against its legal values.
*
* @param string config key
* @param string config value
* @param string (optional) config layer
* @param string channel to set this value for, or null for global value
* @return bool TRUE on success, FALSE on failure
*/
function set($key, $value, $layer = ‘user’, $channel = false)
{
if ($key == ‘__channels’) {
return false;
}

if (!isset($this->configuration[$layer])) {
return false;
}

if ($key == ‘default_channel’) {
// can only set this value globally
$channel = ‘pear.php.net’;
if ($value != ‘pear.php.net’) {
$this->_lazyChannelSetup($layer);
}
}

if ($key == ‘preferred_mirror’) {
if ($channel == ‘__uri’) {
return false; // can’t set the __uri pseudo-channel’s mirror
}

$reg = &$this->getRegistry($layer);
if (is_object($reg)) {
$chan = $reg->getChannel($channel ? $channel : ‘pear.php.net’);
if (PEAR::isError($chan)) {
return false;
}

if (!$chan->getMirror($value) && $chan->getName() != $value) {
return false; // mirror does not exist
}
}
}

if (!isset($this->configuration_info[$key])) {
return false;
}

extract($this->configuration_info[$key]);
switch ($type) {
case ‘integer’:
$value = (int)$value;
break;
case ‘set’: {
// If a valid_set is specified, require the value to
// be in the set. If there is no valid_set, accept
// any value.
if ($valid_set) {
reset($valid_set);
if ((key($valid_set) === 0 && !in_array($value, $valid_set)) ||
(key($valid_set) !== 0 && empty($valid_set[$value])))
{
return false;
}
}
break;
}
}

if (!$channel) {
$channel = $this->get(‘default_channel’, null, ‘pear.php.net’);
}

if (!in_array($channel, $this->_channels)) {
$this->_lazyChannelSetup($layer);
$reg = &$this->getRegistry($layer);
if ($reg) {
$channel = $reg->channelName($channel);
}

if (!in_array($channel, $this->_channels)) {
return false;
}
}

if ($channel != ‘pear.php.net’) {
if (in_array($key, $this->_channelConfigInfo)) {
$this->configuration[$layer][‘__channels’][$channel][$key] = $value;
return true;
}

return false;
}

if ($key == ‘default_channel’) {
if (!isset($reg)) {
$reg = &$this->getRegistry($layer);
if (!$reg) {
$reg = &$this->getRegistry();
}
}

if ($reg) {
$value = $reg->channelName($value);
}

if (!$value) {
return false;
}
}

$this->configuration[$layer][$key] = $value;
if ($key == ‘php_dir’ && !$this->_noRegistry) {
if (!isset($this->_registry[$layer]) ||
$value != $this->_registry[$layer]->install_dir) {
$this->_registry[$layer] = new PEAR_Registry($value);
$this->_regInitialized[$layer] = false;
$this->_registry[$layer]->setConfig($this, false);
}
}

return true;
}

function _lazyChannelSetup($uselayer = false)
{
if ($this->_noRegistry) {
return;
}

$merge = false;
foreach ($this->_registry as $layer => $p) {
if ($uselayer && $uselayer != $layer) {
continue;
}

if (!$this->_regInitialized[$layer]) {
if ($layer == ‘default’ && isset($this->_registry[‘user’]) ||
isset($this->_registry[‘system’])) {
// only use the default registry if there are no alternatives
continue;
}

if (!is_object($this->_registry[$layer])) {
if ($phpdir = $this->get(‘php_dir’, $layer, ‘pear.php.net’)) {
$this->_registry[$layer] = new PEAR_Registry(
$phpdir, false, false,
$this->get(‘metadata_dir’, $layer, ‘pear.php.net’));
$this->_registry[$layer]->setConfig($this, false);
$this->_regInitialized[$layer] = false;
} else {
unset($this->_registry[$layer]);
return;
}
}

$this->setChannels($this->_registry[$layer]->listChannels(), $merge);
$this->_regInitialized[$layer] = true;
$merge = true;
}
}
}

/**
* Set the list of channels.
*
* This should be set via a call to {@link PEAR_Registry::listChannels()}
* @param array
* @param bool
* @return bool success of operation
*/
function setChannels($channels, $merge = false)
{
if (!is_array($channels)) {
return false;
}

if ($merge) {
$this->_channels = array_merge($this->_channels, $channels);
} else {
$this->_channels = $channels;
}

foreach ($channels as $channel) {
$channel = strtolower($channel);
if ($channel == ‘pear.php.net’) {
continue;
}

foreach ($this->layers as $layer) {
if (!isset($this->configuration[$layer][‘__channels’])) {
$this->configuration[$layer][‘__channels’] = array();
}
if (!isset($this->configuration[$layer][‘__channels’][$channel])
|| !is_array($this->configuration[$layer][‘__channels’][$channel])) {
$this->configuration[$layer][‘__channels’][$channel] = array();
}
}
}

return true;
}

/**
* Get the type of a config value.
*
* @param string config key
*
* @return string type, one of “string”, “integer”, “file”,
* “directory”, “set” or “password”.
*
* @access public
*
*/
function getType($key)
{
if (isset($this->configuration_info[$key])) {
return $this->configuration_info[$key][‘type’];
}
return false;
}

/**
* Get the documentation for a config value.
*
* @param string config key
* @return string documentation string
*
* @access public
*
*/
function getDocs($key)
{
if (isset($this->configuration_info[$key])) {
return $this->configuration_info[$key][‘doc’];
}

return false;
}

/**
* Get the short documentation for a config value.
*
* @param string config key
* @return string short documentation string
*
* @access public
*
*/
function getPrompt($key)
{
if (isset($this->configuration_info[$key])) {
return $this->configuration_info[$key][‘prompt’];
}

return false;
}

/**
* Get the parameter group for a config key.
*
* @param string config key
* @return string parameter group
*
* @access public
*
*/
function getGroup($key)
{
if (isset($this->configuration_info[$key])) {
return $this->configuration_info[$key][‘group’];
}

return false;
}

/**
* Get the list of parameter groups.
*
* @return array list of parameter groups
*
* @access public
*
*/
function getGroups()
{
$tmp = array();
foreach ($this->configuration_info as $key => $info) {
$tmp[$info[‘group’]] = 1;
}

return array_keys($tmp);
}

/**
* Get the list of the parameters in a group.
*
* @param string $group parameter group
* @return array list of parameters in $group
*
* @access public
*
*/
function getGroupKeys($group)
{
$keys = array();
foreach ($this->configuration_info as $key => $info) {
if ($info[‘group’] == $group) {
$keys[] = $key;
}
}

return $keys;
}

/**
* Get the list of allowed set values for a config value. Returns
* NULL for config values that are not sets.
*
* @param string config key
* @return array enumerated array of set values, or NULL if the
* config key is unknown or not a set
*
* @access public
*
*/
function getSetValues($key)
{
if (isset($this->configuration_info[$key]) &&
isset($this->configuration_info[$key][‘type’]) &&
$this->configuration_info[$key][‘type’] == ‘set’)
{
$valid_set = $this->configuration_info[$key][‘valid_set’];
reset($valid_set);
if (key($valid_set) === 0) {
return $valid_set;
}

return array_keys($valid_set);
}

return null;
}

/**
* Get all the current config keys.
*
* @return array simple array of config keys
*
* @access public
*/
function getKeys()
{
$keys = array();
foreach ($this->layers as $layer) {
$test = $this->configuration[$layer];
if (isset($test[‘__channels’])) {
foreach ($test[‘__channels’] as $channel => $configs) {
$keys = array_merge($keys, $configs);
}
}

unset($test[‘__channels’]);
$keys = array_merge($keys, $test);

}
return array_keys($keys);
}

/**
* Remove the a config key from a specific config layer.
*
* @param string config key
* @param string (optional) config layer
* @param string (optional) channel (defaults to default channel)
* @return bool TRUE on success, FALSE on failure
*
* @access public
*/
function remove($key, $layer = ‘user’, $channel = null)
{
if ($channel === null) {
$channel = $this->getDefaultChannel();
}

if ($channel !== ‘pear.php.net’) {
if (isset($this->configuration[$layer][‘__channels’][$channel][$key])) {
unset($this->configuration[$layer][‘__channels’][$channel][$key]);
return true;
}
}

if (isset($this->configuration[$layer][$key])) {
unset($this->configuration[$layer][$key]);
return true;
}

return false;
}

/**
* Temporarily remove an entire config layer. USE WITH CARE!
*
* @param string config key
* @param string (optional) config layer
* @return bool TRUE on success, FALSE on failure
*
* @access public
*/
function removeLayer($layer)
{
if (isset($this->configuration[$layer])) {
$this->configuration[$layer] = array();
return true;
}

return false;
}

/**
* Stores configuration data in a layer.
*
* @param string config layer to store
* @return bool TRUE on success, or PEAR error on failure
*
* @access public
*/
function store($layer = ‘user’, $data = null)
{
return $this->writeConfigFile(null, $layer, $data);
}

/**
* Tells what config layer that gets to define a key.
*
* @param string config key
* @param boolean return the defining channel
*
* @return string|array the config layer, or an empty string if not found.
*
* if $returnchannel, the return is an array array(‘layer’ => layername,
* ‘channel’ => channelname), or an empty string if not found
*
* @access public
*/
function definedBy($key, $returnchannel = false)
{
foreach ($this->layers as $layer) {
$channel = $this->getDefaultChannel();
if ($channel !== ‘pear.php.net’) {
if (isset($this->configuration[$layer][‘__channels’][$channel][$key])) {
if ($returnchannel) {
return array(‘layer’ => $layer, ‘channel’ => $channel);
}
return $layer;
}
}

if (isset($this->configuration[$layer][$key])) {
if ($returnchannel) {
return array(‘layer’ => $layer, ‘channel’ => ‘pear.php.net’);
}
return $layer;
}
}

return ”;
}

/**
* Tells whether a given key exists as a config value.
*
* @param string config key
* @return bool whether exists in this object
*
* @access public
*/
function isDefined($key)
{
foreach ($this->layers as $layer) {
if (isset($this->configuration[$layer][$key])) {
return true;
}
}

return false;
}

/**
* Tells whether a given config layer exists.
*
* @param string config layer
* @return bool whether exists in this object
*
* @access public
*/
function isDefinedLayer($layer)
{
return isset($this->configuration[$layer]);
}

/**
* Returns the layers defined (except the ‘default’ one)
*
* @return array of the defined layers
*/
function getLayers()
{
$cf = $this->configuration;
unset($cf[‘default’]);
return array_keys($cf);
}

function apiVersion()
{
return ‘1.1’;
}

/**
* @return PEAR_Registry
*/
function &getRegistry($use = null)
{
$layer = $use === null ? ‘user’ : $use;
if (isset($this->_registry[$layer])) {
return $this->_registry[$layer];
} elseif ($use === null && isset($this->_registry[‘system’])) {
return $this->_registry[‘system’];
} elseif ($use === null && isset($this->_registry[‘default’])) {
return $this->_registry[‘default’];
} elseif ($use) {
$a = false;
return $a;
}

// only go here if null was passed in
echo “CRITICAL ERROR: Registry could not be initialized from any value”;
exit(1);
}

/**
* This is to allow customization like the use of installroot
* @param PEAR_Registry
* @return bool
*/
function setRegistry(&$reg, $layer = ‘user’)
{
if ($this->_noRegistry) {
return false;
}

if (!in_array($layer, array(‘user’, ‘system’))) {
return false;
}

$this->_registry[$layer] = &$reg;
if (is_object($reg)) {
$this->_registry[$layer]->setConfig($this, false);
}

return true;
}

function noRegistry()
{
$this->_noRegistry = true;
}

/**
* @return PEAR_REST
*/
function &getREST($version, $options = array())
{
$version = str_replace(‘.’, ”, $version);
if (!class_exists($class = ‘PEAR_REST_’ . $version)) {
require_once ‘PEAR/REST/’ . $version . ‘.php’;
}

$remote = new $class($this, $options);
return $remote;
}

/**
* The ftp server is set in {@link readFTPConfigFile()}. It exists only if a
* remote configuration file has been specified
* @return PEAR_FTP|false
*/
function &getFTP()
{
if (isset($this->_ftp)) {
return $this->_ftp;
}

$a = false;
return $a;
}

static function _prependPath($path, $prepend)
{
if (strlen($prepend) > 0) {
if (OS_WINDOWS && preg_match(‘/^[a-z]:/i’, $path)) {
if (preg_match(‘/^[a-z]:/i’, $prepend)) {
$prepend = substr($prepend, 2);
} elseif ($prepend[0] != ‘\\’) {
$prepend = “\\$prepend”;
}
$path = substr($path, 0, 2) . $prepend . substr($path, 2);
} else {
$path = $prepend . $path;
}
}
return $path;
}

/**
* @param string|false installation directory to prepend to all _dir variables, or false to
* disable
*/
function setInstallRoot($root)
{
if (substr($root, -1) == DIRECTORY_SEPARATOR) {
$root = substr($root, 0, -1);
}
$old = $this->_installRoot;
$this->_installRoot = $root;
if (($old != $root) && !$this->_noRegistry) {
foreach (array_keys($this->_registry) as $layer) {
if ($layer == ‘ftp’ || !isset($this->_registry[$layer])) {
continue;
}
$r = new PEAR_Registry(
$this->get(‘php_dir’, $layer, ‘pear.php.net’), false, false,
$this->get(‘metadata_dir’, $layer, ‘pear.php.net’));
$this->_registry[$layer] = &$r;
$this->_registry[$layer]->setConfig($this, false);
$this->_regInitialized[$layer] = false;
unset($r);
}
}
}
}

Loading

Yorum yap devamı...

SqlPlus’ta Önceki Komutlara Yukarı Ok Tuşuyla Ulaşabilmek(rlwrap)

Merhaba arkadaşlar Linux ortamında kurulu olan Oracle ile SqlPlus’ta çalışırken bir önceki yazdıgımız komutlara yukarı ok tuşuyla erişemememiz veya tab tuşunu kullanamamız çogu zaman eziyet haline gelebiliyor bu yazımda bunun çözümünden bahsedeceğim.
Öncelikle buradan rlwrap toolunu indiriyoruz.

Daha sonra oracle kullanıcısıyla aşagıdaki komutu kullanarak tool’u tar’dan çıkartırız.

tar -zxvf rlwrap-0.30.tar.gz

rlwrap-0.30 adında bir dosya çıkacakdır.Komut satırına cd rlwrap-0.30 yazarak dosyanın içine gireriz.

Daha sonra oracle kullanıcısıyla aşagıda ki komutu kullanarak dosyayı kurmasını saglarız ;

./configure

(devamı..)

Loading


  • Sertifikasyon



  • Etiketler

  • Topluluklar

                     
                     
  • Copyright © 1996-2010 Mustafa Bektaş Tepe. All rights reserved.
    Türkçeleştirme Blogizma | AltyapıWordPress