Редакция 69 | Только различия | Не учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS
Редакция 69 | Редакция 94 | ||
---|---|---|---|
1 | <?php
|
1 | <?php
|
2 | /**
|
2 | /**
|
3 | * PEAR_Registry
|
3 | * PEAR_Registry
|
4 | *
|
4 | *
|
5 | * PHP versions 4 and 5
|
5 | * PHP versions 4 and 5
|
6 | *
|
6 | *
|
7 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
7 | * LICENSE: This source file is subject to version 3.0 of the PHP license
|
8 | * that is available through the world-wide-web at the following URI:
|
8 | * that is available through the world-wide-web at the following URI:
|
9 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
9 | * http://www.php.net/license/3_0.txt. If you did not receive a copy of
|
10 | * the PHP License and are unable to obtain it through the web, please
|
10 | * the PHP License and are unable to obtain it through the web, please
|
11 | * send a note to license@php.net so we can mail you a copy immediately.
|
11 | * send a note to license@php.net so we can mail you a copy immediately.
|
12 | *
|
12 | *
|
13 | * @category pear
|
13 | * @category pear
|
14 | * @package PEAR
|
14 | * @package PEAR
|
15 | * @author Stig Bakken <ssb@php.net>
|
15 | * @author Stig Bakken <ssb@php.net>
|
16 | * @author Tomas V. V. Cox <cox@idecnet.com>
|
16 | * @author Tomas V. V. Cox <cox@idecnet.com>
|
17 | * @author Greg Beaver <cellog@php.net>
|
17 | * @author Greg Beaver <cellog@php.net>
|
18 | * @copyright 1997-2008 The PHP Group
|
18 | * @copyright 1997-2008 The PHP Group
|
19 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
19 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
20 | * @version CVS: $Id: Registry.php,v 1.171 2008/05/14 04:16:08 cellog Exp $
|
20 | * @version CVS: $Id: Registry.php,v 1.171 2008/05/14 04:16:08 cellog Exp $
|
21 | * @link http://pear.php.net/package/PEAR
|
21 | * @link http://pear.php.net/package/PEAR
|
22 | * @since File available since Release 0.1
|
22 | * @since File available since Release 0.1
|
23 | */
|
23 | */
|
24 | 24 | ||
25 | /**
|
25 | /**
|
26 | * for PEAR_Error
|
26 | * for PEAR_Error
|
27 | */
|
27 | */
|
28 | require_once 'PEAR.php'; |
28 | require_once 'PEAR.php'; |
29 | require_once 'PEAR/DependencyDB.php'; |
29 | require_once 'PEAR/DependencyDB.php'; |
30 | 30 | ||
31 | define('PEAR_REGISTRY_ERROR_LOCK', -2); |
31 | define('PEAR_REGISTRY_ERROR_LOCK', -2); |
32 | define('PEAR_REGISTRY_ERROR_FORMAT', -3); |
32 | define('PEAR_REGISTRY_ERROR_FORMAT', -3); |
33 | define('PEAR_REGISTRY_ERROR_FILE', -4); |
33 | define('PEAR_REGISTRY_ERROR_FILE', -4); |
34 | define('PEAR_REGISTRY_ERROR_CONFLICT', -5); |
34 | define('PEAR_REGISTRY_ERROR_CONFLICT', -5); |
35 | define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6); |
35 | define('PEAR_REGISTRY_ERROR_CHANNEL_FILE', -6); |
36 | 36 | ||
37 | /**
|
37 | /**
|
38 | * Administration class used to maintain the installed package database.
|
38 | * Administration class used to maintain the installed package database.
|
39 | * @category pear
|
39 | * @category pear
|
40 | * @package PEAR
|
40 | * @package PEAR
|
41 | * @author Stig Bakken <ssb@php.net>
|
41 | * @author Stig Bakken <ssb@php.net>
|
42 | * @author Tomas V. V. Cox <cox@idecnet.com>
|
42 | * @author Tomas V. V. Cox <cox@idecnet.com>
|
43 | * @author Greg Beaver <cellog@php.net>
|
43 | * @author Greg Beaver <cellog@php.net>
|
44 | * @copyright 1997-2008 The PHP Group
|
44 | * @copyright 1997-2008 The PHP Group
|
45 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
45 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
46 | * @version Release: 1.7.2
|
46 | * @version Release: 1.7.2
|
47 | * @link http://pear.php.net/package/PEAR
|
47 | * @link http://pear.php.net/package/PEAR
|
48 | * @since Class available since Release 1.4.0a1
|
48 | * @since Class available since Release 1.4.0a1
|
49 | */
|
49 | */
|
50 | class PEAR_Registry extends PEAR |
50 | class PEAR_Registry extends PEAR |
51 | {
|
51 | {
|
52 | // {{{ properties
|
52 | // {{{ properties
|
53 | 53 | ||
54 | /**
|
54 | /**
|
55 | * File containing all channel information.
|
55 | * File containing all channel information.
|
56 | * @var string
|
56 | * @var string
|
57 | */
|
57 | */
|
58 | var $channels = ''; |
58 | var $channels = ''; |
59 | 59 | ||
60 | /** Directory where registry files are stored.
|
60 | /** Directory where registry files are stored.
|
61 | * @var string
|
61 | * @var string
|
62 | */
|
62 | */
|
63 | var $statedir = ''; |
63 | var $statedir = ''; |
64 | 64 | ||
65 | /** File where the file map is stored
|
65 | /** File where the file map is stored
|
66 | * @var string
|
66 | * @var string
|
67 | */
|
67 | */
|
68 | var $filemap = ''; |
68 | var $filemap = ''; |
69 | 69 | ||
70 | /** Directory where registry files for channels are stored.
|
70 | /** Directory where registry files for channels are stored.
|
71 | * @var string
|
71 | * @var string
|
72 | */
|
72 | */
|
73 | var $channelsdir = ''; |
73 | var $channelsdir = ''; |
74 | 74 | ||
75 | /** Name of file used for locking the registry
|
75 | /** Name of file used for locking the registry
|
76 | * @var string
|
76 | * @var string
|
77 | */
|
77 | */
|
78 | var $lockfile = ''; |
78 | var $lockfile = ''; |
79 | 79 | ||
80 | /** File descriptor used during locking
|
80 | /** File descriptor used during locking
|
81 | * @var resource
|
81 | * @var resource
|
82 | */
|
82 | */
|
83 | var $lock_fp = null; |
83 | var $lock_fp = null; |
84 | 84 | ||
85 | /** Mode used during locking
|
85 | /** Mode used during locking
|
86 | * @var int
|
86 | * @var int
|
87 | */
|
87 | */
|
88 | var $lock_mode = 0; // XXX UNUSED |
88 | var $lock_mode = 0; // XXX UNUSED |
89 | 89 | ||
90 | /** Cache of package information. Structure:
|
90 | /** Cache of package information. Structure:
|
91 | * array(
|
91 | * array(
|
92 | * 'package' => array('id' => ... ),
|
92 | * 'package' => array('id' => ... ),
|
93 | * ... )
|
93 | * ... )
|
94 | * @var array
|
94 | * @var array
|
95 | */
|
95 | */
|
96 | var $pkginfo_cache = array(); |
96 | var $pkginfo_cache = array(); |
97 | 97 | ||
98 | /** Cache of file map. Structure:
|
98 | /** Cache of file map. Structure:
|
99 | * array( '/path/to/file' => 'package', ... )
|
99 | * array( '/path/to/file' => 'package', ... )
|
100 | * @var array
|
100 | * @var array
|
101 | */
|
101 | */
|
102 | var $filemap_cache = array(); |
102 | var $filemap_cache = array(); |
103 | 103 | ||
104 | /**
|
104 | /**
|
105 | * @var false|PEAR_ChannelFile
|
105 | * @var false|PEAR_ChannelFile
|
106 | */
|
106 | */
|
107 | var $_pearChannel; |
107 | var $_pearChannel; |
108 | 108 | ||
109 | /**
|
109 | /**
|
110 | * @var false|PEAR_ChannelFile
|
110 | * @var false|PEAR_ChannelFile
|
111 | */
|
111 | */
|
112 | var $_peclChannel; |
112 | var $_peclChannel; |
113 | 113 | ||
114 | /**
|
114 | /**
|
115 | * @var PEAR_DependencyDB
|
115 | * @var PEAR_DependencyDB
|
116 | */
|
116 | */
|
117 | var $_dependencyDB; |
117 | var $_dependencyDB; |
118 | 118 | ||
119 | /**
|
119 | /**
|
120 | * @var PEAR_Config
|
120 | * @var PEAR_Config
|
121 | */
|
121 | */
|
122 | var $_config; |
122 | var $_config; |
123 | // }}}
|
123 | // }}}
|
124 | 124 | ||
125 | // {{{ constructor
|
125 | // {{{ constructor
|
126 | 126 | ||
127 | /**
|
127 | /**
|
128 | * PEAR_Registry constructor.
|
128 | * PEAR_Registry constructor.
|
129 | *
|
129 | *
|
130 | * @param string (optional) PEAR install directory (for .php files)
|
130 | * @param string (optional) PEAR install directory (for .php files)
|
131 | * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
|
131 | * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PEAR channel, if
|
132 | * default values are not desired. Only used the very first time a PEAR
|
132 | * default values are not desired. Only used the very first time a PEAR
|
133 | * repository is initialized
|
133 | * repository is initialized
|
134 | * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
|
134 | * @param PEAR_ChannelFile PEAR_ChannelFile object representing the PECL channel, if
|
135 | * default values are not desired. Only used the very first time a PEAR
|
135 | * default values are not desired. Only used the very first time a PEAR
|
136 | * repository is initialized
|
136 | * repository is initialized
|
137 | *
|
137 | *
|
138 | * @access public
|
138 | * @access public
|
139 | */
|
139 | */
|
140 | function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false, |
140 | function PEAR_Registry($pear_install_dir = PEAR_INSTALL_DIR, $pear_channel = false, |
141 | $pecl_channel = false) |
141 | $pecl_channel = false) |
142 | {
|
142 | {
|
143 | parent::PEAR(); |
143 | parent::PEAR(); |
144 | $this->setInstallDir($pear_install_dir); |
144 | $this->setInstallDir($pear_install_dir); |
145 | $this->_pearChannel = $pear_channel; |
145 | $this->_pearChannel = $pear_channel; |
146 | $this->_peclChannel = $pecl_channel; |
146 | $this->_peclChannel = $pecl_channel; |
147 | $this->_config = false; |
147 | $this->_config = false; |
148 | }
|
148 | }
|
149 | 149 | ||
150 | function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR) |
150 | function setInstallDir($pear_install_dir = PEAR_INSTALL_DIR) |
151 | {
|
151 | {
|
152 | $ds = DIRECTORY_SEPARATOR; |
152 | $ds = DIRECTORY_SEPARATOR; |
153 | $this->install_dir = $pear_install_dir; |
153 | $this->install_dir = $pear_install_dir; |
154 | $this->channelsdir = $pear_install_dir.$ds.'.channels'; |
154 | $this->channelsdir = $pear_install_dir.$ds.'.channels'; |
155 | $this->statedir = $pear_install_dir.$ds.'.registry'; |
155 | $this->statedir = $pear_install_dir.$ds.'.registry'; |
156 | $this->filemap = $pear_install_dir.$ds.'.filemap'; |
156 | $this->filemap = $pear_install_dir.$ds.'.filemap'; |
157 | $this->lockfile = $pear_install_dir.$ds.'.lock'; |
157 | $this->lockfile = $pear_install_dir.$ds.'.lock'; |
158 | }
|
158 | }
|
159 | 159 | ||
160 | function hasWriteAccess() |
160 | function hasWriteAccess() |
161 | {
|
161 | {
|
162 | if (!file_exists($this->install_dir)) { |
162 | if (!file_exists($this->install_dir)) { |
163 | $dir = $this->install_dir; |
163 | $dir = $this->install_dir; |
164 | while ($dir && $dir != '.') { |
164 | while ($dir && $dir != '.') { |
165 | $olddir = $dir; |
165 | $olddir = $dir; |
166 | $dir = dirname($dir); // cd .. |
166 | $dir = dirname($dir); // cd .. |
167 | if ($dir != '.' && file_exists($dir)) { |
167 | if ($dir != '.' && file_exists($dir)) { |
168 | if (is_writeable($dir)) { |
168 | if (is_writeable($dir)) { |
169 | return true; |
169 | return true; |
170 | } else { |
170 | } else { |
171 | return false; |
171 | return false; |
172 | }
|
172 | }
|
173 | }
|
173 | }
|
174 | if ($dir == $olddir) { // this can happen in safe mode |
174 | if ($dir == $olddir) { // this can happen in safe mode |
175 | return @is_writable($dir); |
175 | return @is_writable($dir); |
176 | }
|
176 | }
|
177 | }
|
177 | }
|
178 | return false; |
178 | return false; |
179 | }
|
179 | }
|
180 | return is_writeable($this->install_dir); |
180 | return is_writeable($this->install_dir); |
181 | }
|
181 | }
|
182 | 182 | ||
183 | function setConfig(&$config, $resetInstallDir = true) |
183 | function setConfig(&$config, $resetInstallDir = true) |
184 | {
|
184 | {
|
185 | $this->_config = &$config; |
185 | $this->_config = &$config; |
186 | if ($resetInstallDir) { |
186 | if ($resetInstallDir) { |
187 | $this->setInstallDir($config->get('php_dir')); |
187 | $this->setInstallDir($config->get('php_dir')); |
188 | }
|
188 | }
|
189 | }
|
189 | }
|
190 | 190 | ||
191 | function _initializeChannelDirs() |
191 | function _initializeChannelDirs() |
192 | {
|
192 | {
|
193 | static $running = false; |
193 | static $running = false; |
194 | if (!$running) { |
194 | if (!$running) { |
195 | $running = true; |
195 | $running = true; |
196 | $ds = DIRECTORY_SEPARATOR; |
196 | $ds = DIRECTORY_SEPARATOR; |
197 | if (!is_dir($this->channelsdir) || |
197 | if (!is_dir($this->channelsdir) || |
198 | !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || |
198 | !file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || |
199 | !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || |
199 | !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || |
200 | !file_exists($this->channelsdir . $ds . '__uri.reg')) { |
200 | !file_exists($this->channelsdir . $ds . '__uri.reg')) { |
201 | if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { |
201 | if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { |
202 | $pear_channel = $this->_pearChannel; |
202 | $pear_channel = $this->_pearChannel; |
203 | if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) { |
203 | if (!is_a($pear_channel, 'PEAR_ChannelFile') || !$pear_channel->validate()) { |
204 | if (!class_exists('PEAR_ChannelFile')) { |
204 | if (!class_exists('PEAR_ChannelFile')) { |
205 | require_once 'PEAR/ChannelFile.php'; |
205 | require_once 'PEAR/ChannelFile.php'; |
206 | }
|
206 | }
|
207 | $pear_channel = new PEAR_ChannelFile; |
207 | $pear_channel = new PEAR_ChannelFile; |
208 | $pear_channel->setName('pear.php.net'); |
208 | $pear_channel->setName('pear.php.net'); |
209 | $pear_channel->setAlias('pear'); |
209 | $pear_channel->setAlias('pear'); |
210 | $pear_channel->setServer('pear.php.net'); |
210 | $pear_channel->setServer('pear.php.net'); |
211 | $pear_channel->setSummary('PHP Extension and Application Repository'); |
211 | $pear_channel->setSummary('PHP Extension and Application Repository'); |
212 | $pear_channel->setDefaultPEARProtocols(); |
212 | $pear_channel->setDefaultPEARProtocols(); |
213 | $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); |
213 | $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); |
214 | $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); |
214 | $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); |
215 | } else { |
215 | } else { |
216 | $pear_channel->setName('pear.php.net'); |
216 | $pear_channel->setName('pear.php.net'); |
217 | $pear_channel->setAlias('pear'); |
217 | $pear_channel->setAlias('pear'); |
218 | }
|
218 | }
|
219 | $pear_channel->validate(); |
219 | $pear_channel->validate(); |
220 | $this->_addChannel($pear_channel); |
220 | $this->_addChannel($pear_channel); |
221 | }
|
221 | }
|
222 | if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) { |
222 | if (!file_exists($this->channelsdir . $ds . 'pecl.php.net.reg')) { |
223 | $pecl_channel = $this->_peclChannel; |
223 | $pecl_channel = $this->_peclChannel; |
224 | if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) { |
224 | if (!is_a($pecl_channel, 'PEAR_ChannelFile') || !$pecl_channel->validate()) { |
225 | if (!class_exists('PEAR_ChannelFile')) { |
225 | if (!class_exists('PEAR_ChannelFile')) { |
226 | require_once 'PEAR/ChannelFile.php'; |
226 | require_once 'PEAR/ChannelFile.php'; |
227 | }
|
227 | }
|
228 | $pecl_channel = new PEAR_ChannelFile; |
228 | $pecl_channel = new PEAR_ChannelFile; |
229 | $pecl_channel->setName('pecl.php.net'); |
229 | $pecl_channel->setName('pecl.php.net'); |
230 | $pecl_channel->setAlias('pecl'); |
230 | $pecl_channel->setAlias('pecl'); |
231 | $pecl_channel->setServer('pecl.php.net'); |
231 | $pecl_channel->setServer('pecl.php.net'); |
232 | $pecl_channel->setSummary('PHP Extension Community Library'); |
232 | $pecl_channel->setSummary('PHP Extension Community Library'); |
233 | $pecl_channel->setDefaultPEARProtocols(); |
233 | $pecl_channel->setDefaultPEARProtocols(); |
234 | $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); |
234 | $pecl_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); |
235 | $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); |
235 | $pecl_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); |
236 | $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); |
236 | $pecl_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); |
237 | } else { |
237 | } else { |
238 | $pecl_channel->setName('pecl.php.net'); |
238 | $pecl_channel->setName('pecl.php.net'); |
239 | $pecl_channel->setAlias('pecl'); |
239 | $pecl_channel->setAlias('pecl'); |
240 | }
|
240 | }
|
241 | $pecl_channel->validate(); |
241 | $pecl_channel->validate(); |
242 | $this->_addChannel($pecl_channel); |
242 | $this->_addChannel($pecl_channel); |
243 | }
|
243 | }
|
244 | if (!file_exists($this->channelsdir . $ds . '__uri.reg')) { |
244 | if (!file_exists($this->channelsdir . $ds . '__uri.reg')) { |
245 | if (!class_exists('PEAR_ChannelFile')) { |
245 | if (!class_exists('PEAR_ChannelFile')) { |
246 | require_once 'PEAR/ChannelFile.php'; |
246 | require_once 'PEAR/ChannelFile.php'; |
247 | }
|
247 | }
|
248 | $private = new PEAR_ChannelFile; |
248 | $private = new PEAR_ChannelFile; |
249 | $private->setName('__uri'); |
249 | $private->setName('__uri'); |
250 | $private->addFunction('xmlrpc', '1.0', '****'); |
250 | $private->addFunction('xmlrpc', '1.0', '****'); |
251 | $private->setSummary('Pseudo-channel for static packages'); |
251 | $private->setSummary('Pseudo-channel for static packages'); |
252 | $this->_addChannel($private); |
252 | $this->_addChannel($private); |
253 | }
|
253 | }
|
254 | $this->_rebuildFileMap(); |
254 | $this->_rebuildFileMap(); |
255 | }
|
255 | }
|
256 | $running = false; |
256 | $running = false; |
257 | }
|
257 | }
|
258 | }
|
258 | }
|
259 | 259 | ||
260 | function _initializeDirs() |
260 | function _initializeDirs() |
261 | {
|
261 | {
|
262 | $ds = DIRECTORY_SEPARATOR; |
262 | $ds = DIRECTORY_SEPARATOR; |
263 | // XXX Compatibility code should be removed in the future
|
263 | // XXX Compatibility code should be removed in the future
|
264 | // rename all registry files if any to lowercase
|
264 | // rename all registry files if any to lowercase
|
265 | if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) && |
265 | if (!OS_WINDOWS && file_exists($this->statedir) && is_dir($this->statedir) && |
266 | $handle = opendir($this->statedir)) { |
266 | $handle = opendir($this->statedir)) { |
267 | $dest = $this->statedir . $ds; |
267 | $dest = $this->statedir . $ds; |
268 | while (false !== ($file = readdir($handle))) { |
268 | while (false !== ($file = readdir($handle))) { |
269 | if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) { |
269 | if (preg_match('/^.*[A-Z].*\.reg\\z/', $file)) { |
270 | rename($dest . $file, $dest . strtolower($file)); |
270 | rename($dest . $file, $dest . strtolower($file)); |
271 | }
|
271 | }
|
272 | }
|
272 | }
|
273 | closedir($handle); |
273 | closedir($handle); |
274 | }
|
274 | }
|
275 | $this->_initializeChannelDirs(); |
275 | $this->_initializeChannelDirs(); |
276 | if (!file_exists($this->filemap)) { |
276 | if (!file_exists($this->filemap)) { |
277 | $this->_rebuildFileMap(); |
277 | $this->_rebuildFileMap(); |
278 | }
|
278 | }
|
279 | $this->_initializeDepDB(); |
279 | $this->_initializeDepDB(); |
280 | }
|
280 | }
|
281 | 281 | ||
282 | function _initializeDepDB() |
282 | function _initializeDepDB() |
283 | {
|
283 | {
|
284 | if (!isset($this->_dependencyDB)) { |
284 | if (!isset($this->_dependencyDB)) { |
285 | static $initializing = false; |
285 | static $initializing = false; |
286 | if (!$initializing) { |
286 | if (!$initializing) { |
287 | $initializing = true; |
287 | $initializing = true; |
288 | if (!$this->_config) { // never used? |
288 | if (!$this->_config) { // never used? |
289 | if (OS_WINDOWS) { |
289 | if (OS_WINDOWS) { |
290 | $file = 'pear.ini'; |
290 | $file = 'pear.ini'; |
291 | } else { |
291 | } else { |
292 | $file = '.pearrc'; |
292 | $file = '.pearrc'; |
293 | }
|
293 | }
|
294 | $this->_config = &new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR . |
294 | $this->_config = &new PEAR_Config($this->statedir . DIRECTORY_SEPARATOR . |
295 | $file); |
295 | $file); |
296 | $this->_config->setRegistry($this); |
296 | $this->_config->setRegistry($this); |
297 | $this->_config->set('php_dir', $this->install_dir); |
297 | $this->_config->set('php_dir', $this->install_dir); |
298 | }
|
298 | }
|
299 | $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); |
299 | $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); |
300 | if (PEAR::isError($this->_dependencyDB)) { |
300 | if (PEAR::isError($this->_dependencyDB)) { |
301 | // attempt to recover by removing the dep db
|
301 | // attempt to recover by removing the dep db
|
302 | if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') . |
302 | if (file_exists($this->_config->get('php_dir', null, 'pear.php.net') . |
303 | DIRECTORY_SEPARATOR . '.depdb')) { |
303 | DIRECTORY_SEPARATOR . '.depdb')) { |
304 | @unlink($this->_config->get('php_dir', null, 'pear.php.net') . |
304 | @unlink($this->_config->get('php_dir', null, 'pear.php.net') . |
305 | DIRECTORY_SEPARATOR . '.depdb'); |
305 | DIRECTORY_SEPARATOR . '.depdb'); |
306 | }
|
306 | }
|
307 | $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); |
307 | $this->_dependencyDB = &PEAR_DependencyDB::singleton($this->_config); |
308 | if (PEAR::isError($this->_dependencyDB)) { |
308 | if (PEAR::isError($this->_dependencyDB)) { |
309 | echo $this->_dependencyDB->getMessage(); |
309 | echo $this->_dependencyDB->getMessage(); |
310 | echo 'Unrecoverable error'; |
310 | echo 'Unrecoverable error'; |
311 | exit(1); |
311 | exit(1); |
312 | }
|
312 | }
|
313 | }
|
313 | }
|
314 | $initializing = false; |
314 | $initializing = false; |
315 | }
|
315 | }
|
316 | }
|
316 | }
|
317 | }
|
317 | }
|
318 | // }}}
|
318 | // }}}
|
319 | // {{{ destructor
|
319 | // {{{ destructor
|
320 | 320 | ||
321 | /**
|
321 | /**
|
322 | * PEAR_Registry destructor. Makes sure no locks are forgotten.
|
322 | * PEAR_Registry destructor. Makes sure no locks are forgotten.
|
323 | *
|
323 | *
|
324 | * @access private
|
324 | * @access private
|
325 | */
|
325 | */
|
326 | function _PEAR_Registry() |
326 | function _PEAR_Registry() |
327 | {
|
327 | {
|
328 | parent::_PEAR(); |
328 | parent::_PEAR(); |
329 | if (is_resource($this->lock_fp)) { |
329 | if (is_resource($this->lock_fp)) { |
330 | $this->_unlock(); |
330 | $this->_unlock(); |
331 | }
|
331 | }
|
332 | }
|
332 | }
|
333 | 333 | ||
334 | // }}}
|
334 | // }}}
|
335 | 335 | ||
336 | // {{{ _assertStateDir()
|
336 | // {{{ _assertStateDir()
|
337 | 337 | ||
338 | /**
|
338 | /**
|
339 | * Make sure the directory where we keep registry files exists.
|
339 | * Make sure the directory where we keep registry files exists.
|
340 | *
|
340 | *
|
341 | * @return bool TRUE if directory exists, FALSE if it could not be
|
341 | * @return bool TRUE if directory exists, FALSE if it could not be
|
342 | * created
|
342 | * created
|
343 | *
|
343 | *
|
344 | * @access private
|
344 | * @access private
|
345 | */
|
345 | */
|
346 | function _assertStateDir($channel = false) |
346 | function _assertStateDir($channel = false) |
347 | {
|
347 | {
|
348 | if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { |
348 | if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { |
349 | return $this->_assertChannelStateDir($channel); |
349 | return $this->_assertChannelStateDir($channel); |
350 | }
|
350 | }
|
351 | static $init = false; |
351 | static $init = false; |
352 | if (!file_exists($this->statedir)) { |
352 | if (!file_exists($this->statedir)) { |
353 | if (!$this->hasWriteAccess()) { |
353 | if (!$this->hasWriteAccess()) { |
354 | return false; |
354 | return false; |
355 | }
|
355 | }
|
356 | require_once 'System.php'; |
356 | require_once 'System.php'; |
357 | if (!System::mkdir(array('-p', $this->statedir))) { |
357 | if (!System::mkdir(array('-p', $this->statedir))) { |
358 | return $this->raiseError("could not create directory '{$this->statedir}'"); |
358 | return $this->raiseError("could not create directory '{$this->statedir}'"); |
359 | }
|
359 | }
|
360 | $init = true; |
360 | $init = true; |
361 | } elseif (!is_dir($this->statedir)) { |
361 | } elseif (!is_dir($this->statedir)) { |
362 | return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' . |
362 | return $this->raiseError('Cannot create directory ' . $this->statedir . ', ' . |
363 | 'it already exists and is not a directory'); |
363 | 'it already exists and is not a directory'); |
364 | }
|
364 | }
|
365 | $ds = DIRECTORY_SEPARATOR; |
365 | $ds = DIRECTORY_SEPARATOR; |
366 | if (!file_exists($this->channelsdir)) { |
366 | if (!file_exists($this->channelsdir)) { |
367 | if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || |
367 | if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg') || |
368 | !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || |
368 | !file_exists($this->channelsdir . $ds . 'pecl.php.net.reg') || |
369 | !file_exists($this->channelsdir . $ds . '__uri.reg')) { |
369 | !file_exists($this->channelsdir . $ds . '__uri.reg')) { |
370 | $init = true; |
370 | $init = true; |
371 | }
|
371 | }
|
372 | } elseif (!is_dir($this->channelsdir)) { |
372 | } elseif (!is_dir($this->channelsdir)) { |
373 | return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' . |
373 | return $this->raiseError('Cannot create directory ' . $this->channelsdir . ', ' . |
374 | 'it already exists and is not a directory'); |
374 | 'it already exists and is not a directory'); |
375 | }
|
375 | }
|
376 | if ($init) { |
376 | if ($init) { |
377 | static $running = false; |
377 | static $running = false; |
378 | if (!$running) { |
378 | if (!$running) { |
379 | $running = true; |
379 | $running = true; |
380 | $this->_initializeDirs(); |
380 | $this->_initializeDirs(); |
381 | $running = false; |
381 | $running = false; |
382 | $init = false; |
382 | $init = false; |
383 | }
|
383 | }
|
384 | } else { |
384 | } else { |
385 | $this->_initializeDepDB(); |
385 | $this->_initializeDepDB(); |
386 | }
|
386 | }
|
387 | return true; |
387 | return true; |
388 | }
|
388 | }
|
389 | 389 | ||
390 | // }}}
|
390 | // }}}
|
391 | // {{{ _assertChannelStateDir()
|
391 | // {{{ _assertChannelStateDir()
|
392 | 392 | ||
393 | /**
|
393 | /**
|
394 | * Make sure the directory where we keep registry files exists for a non-standard channel.
|
394 | * Make sure the directory where we keep registry files exists for a non-standard channel.
|
395 | *
|
395 | *
|
396 | * @param string channel name
|
396 | * @param string channel name
|
397 | * @return bool TRUE if directory exists, FALSE if it could not be
|
397 | * @return bool TRUE if directory exists, FALSE if it could not be
|
398 | * created
|
398 | * created
|
399 | *
|
399 | *
|
400 | * @access private
|
400 | * @access private
|
401 | */
|
401 | */
|
402 | function _assertChannelStateDir($channel) |
402 | function _assertChannelStateDir($channel) |
403 | {
|
403 | {
|
404 | $ds = DIRECTORY_SEPARATOR; |
404 | $ds = DIRECTORY_SEPARATOR; |
405 | if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { |
405 | if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { |
406 | if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { |
406 | if (!file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { |
407 | $this->_initializeChannelDirs(); |
407 | $this->_initializeChannelDirs(); |
408 | }
|
408 | }
|
409 | return $this->_assertStateDir($channel); |
409 | return $this->_assertStateDir($channel); |
410 | }
|
410 | }
|
411 | $channelDir = $this->_channelDirectoryName($channel); |
411 | $channelDir = $this->_channelDirectoryName($channel); |
412 | if (!is_dir($this->channelsdir) || |
412 | if (!is_dir($this->channelsdir) || |
413 | !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { |
413 | !file_exists($this->channelsdir . $ds . 'pear.php.net.reg')) { |
414 | $this->_initializeChannelDirs(); |
414 | $this->_initializeChannelDirs(); |
415 | }
|
415 | }
|
416 | if (!file_exists($channelDir)) { |
416 | if (!file_exists($channelDir)) { |
417 | if (!$this->hasWriteAccess()) { |
417 | if (!$this->hasWriteAccess()) { |
418 | return false; |
418 | return false; |
419 | }
|
419 | }
|
420 | require_once 'System.php'; |
420 | require_once 'System.php'; |
421 | if (!System::mkdir(array('-p', $channelDir))) { |
421 | if (!System::mkdir(array('-p', $channelDir))) { |
422 | return $this->raiseError("could not create directory '" . $channelDir . |
422 | return $this->raiseError("could not create directory '" . $channelDir . |
423 | "'"); |
423 | "'"); |
424 | }
|
424 | }
|
425 | } elseif (!is_dir($channelDir)) { |
425 | } elseif (!is_dir($channelDir)) { |
426 | return $this->raiseError("could not create directory '" . $channelDir . |
426 | return $this->raiseError("could not create directory '" . $channelDir . |
427 | "', already exists and is not a directory"); |
427 | "', already exists and is not a directory"); |
428 | }
|
428 | }
|
429 | return true; |
429 | return true; |
430 | }
|
430 | }
|
431 | 431 | ||
432 | // }}}
|
432 | // }}}
|
433 | // {{{ _assertChannelDir()
|
433 | // {{{ _assertChannelDir()
|
434 | 434 | ||
435 | /**
|
435 | /**
|
436 | * Make sure the directory where we keep registry files for channels exists
|
436 | * Make sure the directory where we keep registry files for channels exists
|
437 | *
|
437 | *
|
438 | * @return bool TRUE if directory exists, FALSE if it could not be
|
438 | * @return bool TRUE if directory exists, FALSE if it could not be
|
439 | * created
|
439 | * created
|
440 | *
|
440 | *
|
441 | * @access private
|
441 | * @access private
|
442 | */
|
442 | */
|
443 | function _assertChannelDir() |
443 | function _assertChannelDir() |
444 | {
|
444 | {
|
445 | if (!file_exists($this->channelsdir)) { |
445 | if (!file_exists($this->channelsdir)) { |
446 | if (!$this->hasWriteAccess()) { |
446 | if (!$this->hasWriteAccess()) { |
447 | return false; |
447 | return false; |
448 | }
|
448 | }
|
449 | require_once 'System.php'; |
449 | require_once 'System.php'; |
450 | if (!System::mkdir(array('-p', $this->channelsdir))) { |
450 | if (!System::mkdir(array('-p', $this->channelsdir))) { |
451 | return $this->raiseError("could not create directory '{$this->channelsdir}'"); |
451 | return $this->raiseError("could not create directory '{$this->channelsdir}'"); |
452 | }
|
452 | }
|
453 | } elseif (!is_dir($this->channelsdir)) { |
453 | } elseif (!is_dir($this->channelsdir)) { |
454 | return $this->raiseError("could not create directory '{$this->channelsdir}" . |
454 | return $this->raiseError("could not create directory '{$this->channelsdir}" . |
455 | "', it already exists and is not a directory"); |
455 | "', it already exists and is not a directory"); |
456 | 456 | ||
457 | }
|
457 | }
|
458 | if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { |
458 | if (!file_exists($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { |
459 | if (!$this->hasWriteAccess()) { |
459 | if (!$this->hasWriteAccess()) { |
460 | return false; |
460 | return false; |
461 | }
|
461 | }
|
462 | require_once 'System.php'; |
462 | require_once 'System.php'; |
463 | if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) { |
463 | if (!System::mkdir(array('-p', $this->channelsdir . DIRECTORY_SEPARATOR . '.alias'))) { |
464 | return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'"); |
464 | return $this->raiseError("could not create directory '{$this->channelsdir}/.alias'"); |
465 | }
|
465 | }
|
466 | } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { |
466 | } elseif (!is_dir($this->channelsdir . DIRECTORY_SEPARATOR . '.alias')) { |
467 | return $this->raiseError("could not create directory '{$this->channelsdir}" . |
467 | return $this->raiseError("could not create directory '{$this->channelsdir}" . |
468 | "/.alias', it already exists and is not a directory"); |
468 | "/.alias', it already exists and is not a directory"); |
469 | 469 | ||
470 | }
|
470 | }
|
471 | return true; |
471 | return true; |
472 | }
|
472 | }
|
473 | 473 | ||
474 | // }}}
|
474 | // }}}
|
475 | // {{{ _packageFileName()
|
475 | // {{{ _packageFileName()
|
476 | 476 | ||
477 | /**
|
477 | /**
|
478 | * Get the name of the file where data for a given package is stored.
|
478 | * Get the name of the file where data for a given package is stored.
|
479 | *
|
479 | *
|
480 | * @param string channel name, or false if this is a PEAR package
|
480 | * @param string channel name, or false if this is a PEAR package
|
481 | * @param string package name
|
481 | * @param string package name
|
482 | *
|
482 | *
|
483 | * @return string registry file name
|
483 | * @return string registry file name
|
484 | *
|
484 | *
|
485 | * @access public
|
485 | * @access public
|
486 | */
|
486 | */
|
487 | function _packageFileName($package, $channel = false) |
487 | function _packageFileName($package, $channel = false) |
488 | {
|
488 | {
|
489 | if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { |
489 | if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { |
490 | return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR . |
490 | return $this->_channelDirectoryName($channel) . DIRECTORY_SEPARATOR . |
491 | strtolower($package) . '.reg'; |
491 | strtolower($package) . '.reg'; |
492 | }
|
492 | }
|
493 | return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg'; |
493 | return $this->statedir . DIRECTORY_SEPARATOR . strtolower($package) . '.reg'; |
494 | }
|
494 | }
|
495 | 495 | ||
496 | // }}}
|
496 | // }}}
|
497 | // {{{ _channelFileName()
|
497 | // {{{ _channelFileName()
|
498 | 498 | ||
499 | /**
|
499 | /**
|
500 | * Get the name of the file where data for a given channel is stored.
|
500 | * Get the name of the file where data for a given channel is stored.
|
501 | * @param string channel name
|
501 | * @param string channel name
|
502 | * @return string registry file name
|
502 | * @return string registry file name
|
503 | */
|
503 | */
|
504 | function _channelFileName($channel, $noaliases = false) |
504 | function _channelFileName($channel, $noaliases = false) |
505 | {
|
505 | {
|
506 | if (!$noaliases) { |
506 | if (!$noaliases) { |
507 | if (file_exists($this->_getChannelAliasFileName($channel))) { |
507 | if (file_exists($this->_getChannelAliasFileName($channel))) { |
508 | $channel = implode('', file($this->_getChannelAliasFileName($channel))); |
508 | $channel = implode('', file($this->_getChannelAliasFileName($channel))); |
509 | }
|
509 | }
|
510 | }
|
510 | }
|
511 | return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_', |
511 | return $this->channelsdir . DIRECTORY_SEPARATOR . str_replace('/', '_', |
512 | strtolower($channel)) . '.reg'; |
512 | strtolower($channel)) . '.reg'; |
513 | }
|
513 | }
|
514 | 514 | ||
515 | // }}}
|
515 | // }}}
|
516 | // {{{ getChannelAliasFileName()
|
516 | // {{{ getChannelAliasFileName()
|
517 | 517 | ||
518 | /**
|
518 | /**
|
519 | * @param string
|
519 | * @param string
|
520 | * @return string
|
520 | * @return string
|
521 | */
|
521 | */
|
522 | function _getChannelAliasFileName($alias) |
522 | function _getChannelAliasFileName($alias) |
523 | {
|
523 | {
|
524 | return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' . |
524 | return $this->channelsdir . DIRECTORY_SEPARATOR . '.alias' . |
525 | DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt'; |
525 | DIRECTORY_SEPARATOR . str_replace('/', '_', strtolower($alias)) . '.txt'; |
526 | }
|
526 | }
|
527 | 527 | ||
528 | // }}}
|
528 | // }}}
|
529 | // {{{ _getChannelFromAlias()
|
529 | // {{{ _getChannelFromAlias()
|
530 | 530 | ||
531 | /**
|
531 | /**
|
532 | * Get the name of a channel from its alias
|
532 | * Get the name of a channel from its alias
|
533 | */
|
533 | */
|
534 | function _getChannelFromAlias($channel) |
534 | function _getChannelFromAlias($channel) |
535 | {
|
535 | {
|
536 | if (!$this->_channelExists($channel)) { |
536 | if (!$this->_channelExists($channel)) { |
537 | if ($channel == 'pear.php.net') { |
537 | if ($channel == 'pear.php.net') { |
538 | return 'pear.php.net'; |
538 | return 'pear.php.net'; |
539 | }
|
539 | }
|
540 | if ($channel == 'pecl.php.net') { |
540 | if ($channel == 'pecl.php.net') { |
541 | return 'pecl.php.net'; |
541 | return 'pecl.php.net'; |
542 | }
|
542 | }
|
543 | if ($channel == '__uri') { |
543 | if ($channel == '__uri') { |
544 | return '__uri'; |
544 | return '__uri'; |
545 | }
|
545 | }
|
546 | return false; |
546 | return false; |
547 | }
|
547 | }
|
548 | $channel = strtolower($channel); |
548 | $channel = strtolower($channel); |
549 | if (file_exists($this->_getChannelAliasFileName($channel))) { |
549 | if (file_exists($this->_getChannelAliasFileName($channel))) { |
550 | // translate an alias to an actual channel
|
550 | // translate an alias to an actual channel
|
551 | return implode('', file($this->_getChannelAliasFileName($channel))); |
551 | return implode('', file($this->_getChannelAliasFileName($channel))); |
552 | } else { |
552 | } else { |
553 | return $channel; |
553 | return $channel; |
554 | }
|
554 | }
|
555 | }
|
555 | }
|
556 | // }}}
|
556 | // }}}
|
557 | // {{{ _getChannelFromAlias()
|
557 | // {{{ _getChannelFromAlias()
|
558 | 558 | ||
559 | /**
|
559 | /**
|
560 | * Get the alias of a channel from its alias or its name
|
560 | * Get the alias of a channel from its alias or its name
|
561 | */
|
561 | */
|
562 | function _getAlias($channel) |
562 | function _getAlias($channel) |
563 | {
|
563 | {
|
564 | if (!$this->_channelExists($channel)) { |
564 | if (!$this->_channelExists($channel)) { |
565 | if ($channel == 'pear.php.net') { |
565 | if ($channel == 'pear.php.net') { |
566 | return 'pear'; |
566 | return 'pear'; |
567 | }
|
567 | }
|
568 | if ($channel == 'pecl.php.net') { |
568 | if ($channel == 'pecl.php.net') { |
569 | return 'pecl'; |
569 | return 'pecl'; |
570 | }
|
570 | }
|
571 | return false; |
571 | return false; |
572 | }
|
572 | }
|
573 | $channel = $this->_getChannel($channel); |
573 | $channel = $this->_getChannel($channel); |
574 | if (PEAR::isError($channel)) { |
574 | if (PEAR::isError($channel)) { |
575 | return $channel; |
575 | return $channel; |
576 | }
|
576 | }
|
577 | return $channel->getAlias(); |
577 | return $channel->getAlias(); |
578 | }
|
578 | }
|
579 | // }}}
|
579 | // }}}
|
580 | // {{{ _channelDirectoryName()
|
580 | // {{{ _channelDirectoryName()
|
581 | 581 | ||
582 | /**
|
582 | /**
|
583 | * Get the name of the file where data for a given package is stored.
|
583 | * Get the name of the file where data for a given package is stored.
|
584 | *
|
584 | *
|
585 | * @param string channel name, or false if this is a PEAR package
|
585 | * @param string channel name, or false if this is a PEAR package
|
586 | * @param string package name
|
586 | * @param string package name
|
587 | *
|
587 | *
|
588 | * @return string registry file name
|
588 | * @return string registry file name
|
589 | *
|
589 | *
|
590 | * @access public
|
590 | * @access public
|
591 | */
|
591 | */
|
592 | function _channelDirectoryName($channel) |
592 | function _channelDirectoryName($channel) |
593 | {
|
593 | {
|
594 | if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { |
594 | if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { |
595 | return $this->statedir; |
595 | return $this->statedir; |
596 | } else { |
596 | } else { |
597 | $ch = $this->_getChannelFromAlias($channel); |
597 | $ch = $this->_getChannelFromAlias($channel); |
598 | if (!$ch) { |
598 | if (!$ch) { |
599 | $ch = $channel; |
599 | $ch = $channel; |
600 | }
|
600 | }
|
601 | return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' . |
601 | return $this->statedir . DIRECTORY_SEPARATOR . strtolower('.channel.' . |
602 | str_replace('/', '_', $ch)); |
602 | str_replace('/', '_', $ch)); |
603 | }
|
603 | }
|
604 | }
|
604 | }
|
605 | 605 | ||
606 | // }}}
|
606 | // }}}
|
607 | // {{{ _openPackageFile()
|
607 | // {{{ _openPackageFile()
|
608 | 608 | ||
609 | function _openPackageFile($package, $mode, $channel = false) |
609 | function _openPackageFile($package, $mode, $channel = false) |
610 | {
|
610 | {
|
611 | if (!$this->_assertStateDir($channel)) { |
611 | if (!$this->_assertStateDir($channel)) { |
612 | return null; |
612 | return null; |
613 | }
|
613 | }
|
614 | if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { |
614 | if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { |
615 | return null; |
615 | return null; |
616 | }
|
616 | }
|
617 | $file = $this->_packageFileName($package, $channel); |
617 | $file = $this->_packageFileName($package, $channel); |
618 | if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { |
618 | if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { |
619 | return null; |
619 | return null; |
620 | }
|
620 | }
|
621 | $fp = @fopen($file, $mode); |
621 | $fp = @fopen($file, $mode); |
622 | if (!$fp) { |
622 | if (!$fp) { |
623 | return null; |
623 | return null; |
624 | }
|
624 | }
|
625 | return $fp; |
625 | return $fp; |
626 | }
|
626 | }
|
627 | 627 | ||
628 | // }}}
|
628 | // }}}
|
629 | // {{{ _closePackageFile()
|
629 | // {{{ _closePackageFile()
|
630 | 630 | ||
631 | function _closePackageFile($fp) |
631 | function _closePackageFile($fp) |
632 | {
|
632 | {
|
633 | fclose($fp); |
633 | fclose($fp); |
634 | }
|
634 | }
|
635 | 635 | ||
636 | // }}}
|
636 | // }}}
|
637 | // {{{ _openChannelFile()
|
637 | // {{{ _openChannelFile()
|
638 | 638 | ||
639 | function _openChannelFile($channel, $mode) |
639 | function _openChannelFile($channel, $mode) |
640 | {
|
640 | {
|
641 | if (!$this->_assertChannelDir()) { |
641 | if (!$this->_assertChannelDir()) { |
642 | return null; |
642 | return null; |
643 | }
|
643 | }
|
644 | if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { |
644 | if (!in_array($mode, array('r', 'rb')) && !$this->hasWriteAccess()) { |
645 | return null; |
645 | return null; |
646 | }
|
646 | }
|
647 | $file = $this->_channelFileName($channel); |
647 | $file = $this->_channelFileName($channel); |
648 | if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { |
648 | if (!file_exists($file) && $mode == 'r' || $mode == 'rb') { |
649 | return null; |
649 | return null; |
650 | }
|
650 | }
|
651 | $fp = @fopen($file, $mode); |
651 | $fp = @fopen($file, $mode); |
652 | if (!$fp) { |
652 | if (!$fp) { |
653 | return null; |
653 | return null; |
654 | }
|
654 | }
|
655 | return $fp; |
655 | return $fp; |
656 | }
|
656 | }
|
657 | 657 | ||
658 | // }}}
|
658 | // }}}
|
659 | // {{{ _closePackageFile()
|
659 | // {{{ _closePackageFile()
|
660 | 660 | ||
661 | function _closeChannelFile($fp) |
661 | function _closeChannelFile($fp) |
662 | {
|
662 | {
|
663 | fclose($fp); |
663 | fclose($fp); |
664 | }
|
664 | }
|
665 | 665 | ||
666 | // }}}
|
666 | // }}}
|
667 | // {{{ _rebuildFileMap()
|
667 | // {{{ _rebuildFileMap()
|
668 | 668 | ||
669 | function _rebuildFileMap() |
669 | function _rebuildFileMap() |
670 | {
|
670 | {
|
671 | if (!class_exists('PEAR_Installer_Role')) { |
671 | if (!class_exists('PEAR_Installer_Role')) { |
672 | require_once 'PEAR/Installer/Role.php'; |
672 | require_once 'PEAR/Installer/Role.php'; |
673 | }
|
673 | }
|
674 | $channels = $this->_listAllPackages(); |
674 | $channels = $this->_listAllPackages(); |
675 | $files = array(); |
675 | $files = array(); |
676 | foreach ($channels as $channel => $packages) { |
676 | foreach ($channels as $channel => $packages) { |
677 | foreach ($packages as $package) { |
677 | foreach ($packages as $package) { |
678 | $version = $this->_packageInfo($package, 'version', $channel); |
678 | $version = $this->_packageInfo($package, 'version', $channel); |
679 | $filelist = $this->_packageInfo($package, 'filelist', $channel); |
679 | $filelist = $this->_packageInfo($package, 'filelist', $channel); |
680 | if (!is_array($filelist)) { |
680 | if (!is_array($filelist)) { |
681 | continue; |
681 | continue; |
682 | }
|
682 | }
|
683 | foreach ($filelist as $name => $attrs) { |
683 | foreach ($filelist as $name => $attrs) { |
684 | if (isset($attrs['attribs'])) { |
684 | if (isset($attrs['attribs'])) { |
685 | $attrs = $attrs['attribs']; |
685 | $attrs = $attrs['attribs']; |
686 | }
|
686 | }
|
687 | // it is possible for conflicting packages in different channels to
|
687 | // it is possible for conflicting packages in different channels to
|
688 | // conflict with data files/doc files
|
688 | // conflict with data files/doc files
|
689 | if ($name == 'dirtree') { |
689 | if ($name == 'dirtree') { |
690 | continue; |
690 | continue; |
691 | }
|
691 | }
|
692 | if (isset($attrs['role']) && !in_array($attrs['role'], |
692 | if (isset($attrs['role']) && !in_array($attrs['role'], |
693 | PEAR_Installer_Role::getInstallableRoles())) { |
693 | PEAR_Installer_Role::getInstallableRoles())) { |
694 | // these are not installed
|
694 | // these are not installed
|
695 | continue; |
695 | continue; |
696 | }
|
696 | }
|
697 | if (isset($attrs['role']) && !in_array($attrs['role'], |
697 | if (isset($attrs['role']) && !in_array($attrs['role'], |
698 | PEAR_Installer_Role::getBaseinstallRoles())) { |
698 | PEAR_Installer_Role::getBaseinstallRoles())) { |
699 | $attrs['baseinstalldir'] = $package; |
699 | $attrs['baseinstalldir'] = $package; |
700 | }
|
700 | }
|
701 | if (isset($attrs['baseinstalldir'])) { |
701 | if (isset($attrs['baseinstalldir'])) { |
702 | $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; |
702 | $file = $attrs['baseinstalldir'].DIRECTORY_SEPARATOR.$name; |
703 | } else { |
703 | } else { |
704 | $file = $name; |
704 | $file = $name; |
705 | }
|
705 | }
|
706 | $file = preg_replace(',^/+,', '', $file); |
706 | $file = preg_replace(',^/+,', '', $file); |
707 | if ($channel != 'pear.php.net') { |
707 | if ($channel != 'pear.php.net') { |
708 | if (!isset($files[$attrs['role']])) { |
708 | if (!isset($files[$attrs['role']])) { |
709 | $files[$attrs['role']] = array(); |
709 | $files[$attrs['role']] = array(); |
710 | }
|
710 | }
|
711 | $files[$attrs['role']][$file] = array(strtolower($channel), |
711 | $files[$attrs['role']][$file] = array(strtolower($channel), |
712 | strtolower($package)); |
712 | strtolower($package)); |
713 | } else { |
713 | } else { |
714 | if (!isset($files[$attrs['role']])) { |
714 | if (!isset($files[$attrs['role']])) { |
715 | $files[$attrs['role']] = array(); |
715 | $files[$attrs['role']] = array(); |
716 | }
|
716 | }
|
717 | $files[$attrs['role']][$file] = strtolower($package); |
717 | $files[$attrs['role']][$file] = strtolower($package); |
718 | }
|
718 | }
|
719 | }
|
719 | }
|
720 | }
|
720 | }
|
721 | }
|
721 | }
|
722 | $this->_assertStateDir(); |
722 | $this->_assertStateDir(); |
723 | if (!$this->hasWriteAccess()) { |
723 | if (!$this->hasWriteAccess()) { |
724 | return false; |
724 | return false; |
725 | }
|
725 | }
|
726 | $fp = @fopen($this->filemap, 'wb'); |
726 | $fp = @fopen($this->filemap, 'wb'); |
727 | if (!$fp) { |
727 | if (!$fp) { |
728 | return false; |
728 | return false; |
729 | }
|
729 | }
|
730 | $this->filemap_cache = $files; |
730 | $this->filemap_cache = $files; |
731 | fwrite($fp, serialize($files)); |
731 | fwrite($fp, serialize($files)); |
732 | fclose($fp); |
732 | fclose($fp); |
733 | return true; |
733 | return true; |
734 | }
|
734 | }
|
735 | 735 | ||
736 | // }}}
|
736 | // }}}
|
737 | // {{{ _readFileMap()
|
737 | // {{{ _readFileMap()
|
738 | 738 | ||
739 | function _readFileMap() |
739 | function _readFileMap() |
740 | {
|
740 | {
|
741 | if (!file_exists($this->filemap)) { |
741 | if (!file_exists($this->filemap)) { |
742 | return array(); |
742 | return array(); |
743 | }
|
743 | }
|
744 | $fp = @fopen($this->filemap, 'r'); |
744 | $fp = @fopen($this->filemap, 'r'); |
745 | if (!$fp) { |
745 | if (!$fp) { |
746 | return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); |
746 | return $this->raiseError('PEAR_Registry: could not open filemap "' . $this->filemap . '"', PEAR_REGISTRY_ERROR_FILE, null, null, $php_errormsg); |
747 | }
|
747 | }
|
748 | clearstatcache(); |
748 | clearstatcache(); |
749 | $rt = get_magic_quotes_runtime(); |
749 | $rt = get_magic_quotes_runtime(); |
750 | set_magic_quotes_runtime(0); |
750 | set_magic_quotes_runtime(0); |
751 | $fsize = filesize($this->filemap); |
751 | $fsize = filesize($this->filemap); |
752 | fclose($fp); |
752 | fclose($fp); |
753 | $data = file_get_contents($this->filemap); |
753 | $data = file_get_contents($this->filemap); |
754 | set_magic_quotes_runtime($rt); |
754 | set_magic_quotes_runtime($rt); |
755 | $tmp = unserialize($data); |
755 | $tmp = unserialize($data); |
756 | if (!$tmp && $fsize > 7) { |
756 | if (!$tmp && $fsize > 7) { |
757 | return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data); |
757 | return $this->raiseError('PEAR_Registry: invalid filemap data', PEAR_REGISTRY_ERROR_FORMAT, null, null, $data); |
758 | }
|
758 | }
|
759 | $this->filemap_cache = $tmp; |
759 | $this->filemap_cache = $tmp; |
760 | return true; |
760 | return true; |
761 | }
|
761 | }
|
762 | 762 | ||
763 | // }}}
|
763 | // }}}
|
764 | // {{{ _lock()
|
764 | // {{{ _lock()
|
765 | 765 | ||
766 | /**
|
766 | /**
|
767 | * Lock the registry.
|
767 | * Lock the registry.
|
768 | *
|
768 | *
|
769 | * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
|
769 | * @param integer lock mode, one of LOCK_EX, LOCK_SH or LOCK_UN.
|
770 | * See flock manual for more information.
|
770 | * See flock manual for more information.
|
771 | *
|
771 | *
|
772 | * @return bool TRUE on success, FALSE if locking failed, or a
|
772 | * @return bool TRUE on success, FALSE if locking failed, or a
|
773 | * PEAR error if some other error occurs (such as the
|
773 | * PEAR error if some other error occurs (such as the
|
774 | * lock file not being writable).
|
774 | * lock file not being writable).
|
775 | *
|
775 | *
|
776 | * @access private
|
776 | * @access private
|
777 | */
|
777 | */
|
778 | function _lock($mode = LOCK_EX) |
778 | function _lock($mode = LOCK_EX) |
779 | {
|
779 | {
|
780 | if (!eregi('Windows 9', php_uname())) { |
780 | if (!eregi('Windows 9', php_uname())) { |
781 | if ($mode != LOCK_UN && is_resource($this->lock_fp)) { |
781 | if ($mode != LOCK_UN && is_resource($this->lock_fp)) { |
782 | // XXX does not check type of lock (LOCK_SH/LOCK_EX)
|
782 | // XXX does not check type of lock (LOCK_SH/LOCK_EX)
|
783 | return true; |
783 | return true; |
784 | }
|
784 | }
|
785 | if (!$this->_assertStateDir()) { |
785 | if (!$this->_assertStateDir()) { |
786 | if ($mode == LOCK_EX) { |
786 | if ($mode == LOCK_EX) { |
787 | return $this->raiseError('Registry directory is not writeable by the current user'); |
787 | return $this->raiseError('Registry directory is not writeable by the current user'); |
788 | } else { |
788 | } else { |
789 | return true; |
789 | return true; |
790 | }
|
790 | }
|
791 | }
|
791 | }
|
792 | $open_mode = 'w'; |
792 | $open_mode = 'w'; |
793 | // XXX People reported problems with LOCK_SH and 'w'
|
793 | // XXX People reported problems with LOCK_SH and 'w'
|
794 | if ($mode === LOCK_SH || $mode === LOCK_UN) { |
794 | if ($mode === LOCK_SH || $mode === LOCK_UN) { |
795 | if (!file_exists($this->lockfile)) { |
795 | if (!file_exists($this->lockfile)) { |
796 | touch($this->lockfile); |
796 | touch($this->lockfile); |
797 | }
|
797 | }
|
798 | $open_mode = 'r'; |
798 | $open_mode = 'r'; |
799 | }
|
799 | }
|
800 | 800 | ||
801 | if (!is_resource($this->lock_fp)) { |
801 | if (!is_resource($this->lock_fp)) { |
802 | $this->lock_fp = @fopen($this->lockfile, $open_mode); |
802 | $this->lock_fp = @fopen($this->lockfile, $open_mode); |
803 | }
|
803 | }
|
804 | 804 | ||
805 | if (!is_resource($this->lock_fp)) { |
805 | if (!is_resource($this->lock_fp)) { |
806 | $this->lock_fp = null; |
806 | $this->lock_fp = null; |
807 | return $this->raiseError("could not create lock file" . |
807 | return $this->raiseError("could not create lock file" . |
808 | (isset($php_errormsg) ? ": " . $php_errormsg : "")); |
808 | (isset($php_errormsg) ? ": " . $php_errormsg : "")); |
809 | }
|
809 | }
|
810 | if (!(int)flock($this->lock_fp, $mode)) { |
810 | if (!(int)flock($this->lock_fp, $mode)) { |
811 | switch ($mode) { |
811 | switch ($mode) { |
812 | case LOCK_SH: $str = 'shared'; break; |
812 | case LOCK_SH: $str = 'shared'; break; |
813 | case LOCK_EX: $str = 'exclusive'; break; |
813 | case LOCK_EX: $str = 'exclusive'; break; |
814 | case LOCK_UN: $str = 'unlock'; break; |
814 | case LOCK_UN: $str = 'unlock'; break; |
815 | default: $str = 'unknown'; break; |
815 | default: $str = 'unknown'; break; |
816 | }
|
816 | }
|
817 | //is resource at this point, close it on error.
|
817 | //is resource at this point, close it on error.
|
818 | fclose($this->lock_fp); |
818 | fclose($this->lock_fp); |
819 | $this->lock_fp = null; |
819 | $this->lock_fp = null; |
820 | return $this->raiseError("could not acquire $str lock ($this->lockfile)", |
820 | return $this->raiseError("could not acquire $str lock ($this->lockfile)", |
821 | PEAR_REGISTRY_ERROR_LOCK); |
821 | PEAR_REGISTRY_ERROR_LOCK); |
822 | }
|
822 | }
|
823 | }
|
823 | }
|
824 | return true; |
824 | return true; |
825 | }
|
825 | }
|
826 | 826 | ||
827 | // }}}
|
827 | // }}}
|
828 | // {{{ _unlock()
|
828 | // {{{ _unlock()
|
829 | 829 | ||
830 | function _unlock() |
830 | function _unlock() |
831 | {
|
831 | {
|
832 | $ret = $this->_lock(LOCK_UN); |
832 | $ret = $this->_lock(LOCK_UN); |
833 | if (is_resource($this->lock_fp)) { |
833 | if (is_resource($this->lock_fp)) { |
834 | fclose($this->lock_fp); |
834 | fclose($this->lock_fp); |
835 | }
|
835 | }
|
836 | $this->lock_fp = null; |
836 | $this->lock_fp = null; |
837 | return $ret; |
837 | return $ret; |
838 | }
|
838 | }
|
839 | 839 | ||
840 | // }}}
|
840 | // }}}
|
841 | // {{{ _packageExists()
|
841 | // {{{ _packageExists()
|
842 | 842 | ||
843 | function _packageExists($package, $channel = false) |
843 | function _packageExists($package, $channel = false) |
844 | {
|
844 | {
|
845 | return file_exists($this->_packageFileName($package, $channel)); |
845 | return file_exists($this->_packageFileName($package, $channel)); |
846 | }
|
846 | }
|
847 | 847 | ||
848 | // }}}
|
848 | // }}}
|
849 | // {{{ _channelExists()
|
849 | // {{{ _channelExists()
|
850 | 850 | ||
851 | /**
|
851 | /**
|
852 | * Determine whether a channel exists in the registry
|
852 | * Determine whether a channel exists in the registry
|
853 | * @param string Channel name
|
853 | * @param string Channel name
|
854 | * @param bool if true, then aliases will be ignored
|
854 | * @param bool if true, then aliases will be ignored
|
855 | * @return boolean
|
855 | * @return boolean
|
856 | */
|
856 | */
|
857 | function _channelExists($channel, $noaliases = false) |
857 | function _channelExists($channel, $noaliases = false) |
858 | {
|
858 | {
|
859 | $a = file_exists($this->_channelFileName($channel, $noaliases)); |
859 | $a = file_exists($this->_channelFileName($channel, $noaliases)); |
860 | if (!$a && $channel == 'pear.php.net') { |
860 | if (!$a && $channel == 'pear.php.net') { |
861 | return true; |
861 | return true; |
862 | }
|
862 | }
|
863 | if (!$a && $channel == 'pecl.php.net') { |
863 | if (!$a && $channel == 'pecl.php.net') { |
864 | return true; |
864 | return true; |
865 | }
|
865 | }
|
866 | return $a; |
866 | return $a; |
867 | }
|
867 | }
|
868 | 868 | ||
869 | // }}}
|
869 | // }}}
|
870 | // {{{ _addChannel()
|
870 | // {{{ _addChannel()
|
871 | 871 | ||
872 | /**
|
872 | /**
|
873 | * @param PEAR_ChannelFile Channel object
|
873 | * @param PEAR_ChannelFile Channel object
|
874 | * @param donotuse
|
874 | * @param donotuse
|
875 | * @param string Last-Modified HTTP tag from remote request
|
875 | * @param string Last-Modified HTTP tag from remote request
|
876 | * @return boolean|PEAR_Error True on creation, false if it already exists
|
876 | * @return boolean|PEAR_Error True on creation, false if it already exists
|
877 | */
|
877 | */
|
878 | function _addChannel($channel, $update = false, $lastmodified = false) |
878 | function _addChannel($channel, $update = false, $lastmodified = false) |
879 | {
|
879 | {
|
880 | if (!is_a($channel, 'PEAR_ChannelFile')) { |
880 | if (!is_a($channel, 'PEAR_ChannelFile')) { |
881 | return false; |
881 | return false; |
882 | }
|
882 | }
|
883 | if (!$channel->validate()) { |
883 | if (!$channel->validate()) { |
884 | return false; |
884 | return false; |
885 | }
|
885 | }
|
886 | if (file_exists($this->_channelFileName($channel->getName()))) { |
886 | if (file_exists($this->_channelFileName($channel->getName()))) { |
887 | if (!$update) { |
887 | if (!$update) { |
888 | return false; |
888 | return false; |
889 | }
|
889 | }
|
890 | $checker = $this->_getChannel($channel->getName()); |
890 | $checker = $this->_getChannel($channel->getName()); |
891 | if (PEAR::isError($checker)) { |
891 | if (PEAR::isError($checker)) { |
892 | return $checker; |
892 | return $checker; |
893 | }
|
893 | }
|
894 | if ($channel->getAlias() != $checker->getAlias()) { |
894 | if ($channel->getAlias() != $checker->getAlias()) { |
895 | if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) { |
895 | if (file_exists($this->_getChannelAliasFileName($checker->getAlias()))) { |
896 | @unlink($this->_getChannelAliasFileName($checker->getAlias())); |
896 | @unlink($this->_getChannelAliasFileName($checker->getAlias())); |
897 | }
|
897 | }
|
898 | }
|
898 | }
|
899 | } else { |
899 | } else { |
900 | if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net'))) { |
900 | if ($update && !in_array($channel->getName(), array('pear.php.net', 'pecl.php.net'))) { |
901 | return false; |
901 | return false; |
902 | }
|
902 | }
|
903 | }
|
903 | }
|
904 | $ret = $this->_assertChannelDir(); |
904 | $ret = $this->_assertChannelDir(); |
905 | if (PEAR::isError($ret)) { |
905 | if (PEAR::isError($ret)) { |
906 | return $ret; |
906 | return $ret; |
907 | }
|
907 | }
|
908 | $ret = $this->_assertChannelStateDir($channel->getName()); |
908 | $ret = $this->_assertChannelStateDir($channel->getName()); |
909 | if (PEAR::isError($ret)) { |
909 | if (PEAR::isError($ret)) { |
910 | return $ret; |
910 | return $ret; |
911 | }
|
911 | }
|
912 | if ($channel->getAlias() != $channel->getName()) { |
912 | if ($channel->getAlias() != $channel->getName()) { |
913 | if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) && |
913 | if (file_exists($this->_getChannelAliasFileName($channel->getAlias())) && |
914 | $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) { |
914 | $this->_getChannelFromAlias($channel->getAlias()) != $channel->getName()) { |
915 | $channel->setAlias($channel->getName()); |
915 | $channel->setAlias($channel->getName()); |
916 | }
|
916 | }
|
917 | if (!$this->hasWriteAccess()) { |
917 | if (!$this->hasWriteAccess()) { |
918 | return false; |
918 | return false; |
919 | }
|
919 | }
|
920 | $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w'); |
920 | $fp = @fopen($this->_getChannelAliasFileName($channel->getAlias()), 'w'); |
921 | if (!$fp) { |
921 | if (!$fp) { |
922 | return false; |
922 | return false; |
923 | }
|
923 | }
|
924 | fwrite($fp, $channel->getName()); |
924 | fwrite($fp, $channel->getName()); |
925 | fclose($fp); |
925 | fclose($fp); |
926 | }
|
926 | }
|
927 | if (!$this->hasWriteAccess()) { |
927 | if (!$this->hasWriteAccess()) { |
928 | return false; |
928 | return false; |
929 | }
|
929 | }
|
930 | $fp = @fopen($this->_channelFileName($channel->getName()), 'wb'); |
930 | $fp = @fopen($this->_channelFileName($channel->getName()), 'wb'); |
931 | if (!$fp) { |
931 | if (!$fp) { |
932 | return false; |
932 | return false; |
933 | }
|
933 | }
|
934 | $info = $channel->toArray(); |
934 | $info = $channel->toArray(); |
935 | if ($lastmodified) { |
935 | if ($lastmodified) { |
936 | $info['_lastmodified'] = $lastmodified; |
936 | $info['_lastmodified'] = $lastmodified; |
937 | } else { |
937 | } else { |
938 | $info['_lastmodified'] = date('r'); |
938 | $info['_lastmodified'] = date('r'); |
939 | }
|
939 | }
|
940 | fwrite($fp, serialize($info)); |
940 | fwrite($fp, serialize($info)); |
941 | fclose($fp); |
941 | fclose($fp); |
942 | return true; |
942 | return true; |
943 | }
|
943 | }
|
944 | 944 | ||
945 | // }}}
|
945 | // }}}
|
946 | // {{{ _deleteChannel()
|
946 | // {{{ _deleteChannel()
|
947 | 947 | ||
948 | /**
|
948 | /**
|
949 | * Deletion fails if there are any packages installed from the channel
|
949 | * Deletion fails if there are any packages installed from the channel
|
950 | * @param string|PEAR_ChannelFile channel name
|
950 | * @param string|PEAR_ChannelFile channel name
|
951 | * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
|
951 | * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
|
952 | */
|
952 | */
|
953 | function _deleteChannel($channel) |
953 | function _deleteChannel($channel) |
954 | {
|
954 | {
|
955 | if (!is_string($channel)) { |
955 | if (!is_string($channel)) { |
956 | if (is_a($channel, 'PEAR_ChannelFile')) { |
956 | if (is_a($channel, 'PEAR_ChannelFile')) { |
957 | if (!$channel->validate()) { |
957 | if (!$channel->validate()) { |
958 | return false; |
958 | return false; |
959 | }
|
959 | }
|
960 | $channel = $channel->getName(); |
960 | $channel = $channel->getName(); |
961 | } else { |
961 | } else { |
962 | return false; |
962 | return false; |
963 | }
|
963 | }
|
964 | }
|
964 | }
|
965 | if ($this->_getChannelFromAlias($channel) == '__uri') { |
965 | if ($this->_getChannelFromAlias($channel) == '__uri') { |
966 | return false; |
966 | return false; |
967 | }
|
967 | }
|
968 | if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { |
968 | if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { |
969 | return false; |
969 | return false; |
970 | }
|
970 | }
|
971 | if (!$this->_channelExists($channel)) { |
971 | if (!$this->_channelExists($channel)) { |
972 | return false; |
972 | return false; |
973 | }
|
973 | }
|
974 | if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { |
974 | if (!$channel || $this->_getChannelFromAlias($channel) == 'pear.php.net') { |
975 | return false; |
975 | return false; |
976 | }
|
976 | }
|
977 | $channel = $this->_getChannelFromAlias($channel); |
977 | $channel = $this->_getChannelFromAlias($channel); |
978 | if ($channel == 'pear.php.net') { |
978 | if ($channel == 'pear.php.net') { |
979 | return false; |
979 | return false; |
980 | }
|
980 | }
|
981 | $test = $this->_listChannelPackages($channel); |
981 | $test = $this->_listChannelPackages($channel); |
982 | if (count($test)) { |
982 | if (count($test)) { |
983 | return false; |
983 | return false; |
984 | }
|
984 | }
|
985 | $test = @rmdir($this->_channelDirectoryName($channel)); |
985 | $test = @rmdir($this->_channelDirectoryName($channel)); |
986 | if (!$test) { |
986 | if (!$test) { |
987 | return false; |
987 | return false; |
988 | }
|
988 | }
|
989 | $file = $this->_getChannelAliasFileName($this->_getAlias($channel)); |
989 | $file = $this->_getChannelAliasFileName($this->_getAlias($channel)); |
990 | if (file_exists($file)) { |
990 | if (file_exists($file)) { |
991 | $test = @unlink($file); |
991 | $test = @unlink($file); |
992 | if (!$test) { |
992 | if (!$test) { |
993 | return false; |
993 | return false; |
994 | }
|
994 | }
|
995 | }
|
995 | }
|
996 | $file = $this->_channelFileName($channel); |
996 | $file = $this->_channelFileName($channel); |
997 | $ret = true; |
997 | $ret = true; |
998 | if (file_exists($file)) { |
998 | if (file_exists($file)) { |
999 | $ret = @unlink($file); |
999 | $ret = @unlink($file); |
1000 | }
|
1000 | }
|
1001 | return $ret; |
1001 | return $ret; |
1002 | }
|
1002 | }
|
1003 | 1003 | ||
1004 | // }}}
|
1004 | // }}}
|
1005 | // {{{ _isChannelAlias()
|
1005 | // {{{ _isChannelAlias()
|
1006 | 1006 | ||
1007 | /**
|
1007 | /**
|
1008 | * Determine whether a channel exists in the registry
|
1008 | * Determine whether a channel exists in the registry
|
1009 | * @param string Channel Alias
|
1009 | * @param string Channel Alias
|
1010 | * @return boolean
|
1010 | * @return boolean
|
1011 | */
|
1011 | */
|
1012 | function _isChannelAlias($alias) |
1012 | function _isChannelAlias($alias) |
1013 | {
|
1013 | {
|
1014 | return file_exists($this->_getChannelAliasFileName($alias)); |
1014 | return file_exists($this->_getChannelAliasFileName($alias)); |
1015 | }
|
1015 | }
|
1016 | 1016 | ||
1017 | // }}}
|
1017 | // }}}
|
1018 | // {{{ _packageInfo()
|
1018 | // {{{ _packageInfo()
|
1019 | 1019 | ||
1020 | /**
|
1020 | /**
|
1021 | * @param string|null
|
1021 | * @param string|null
|
1022 | * @param string|null
|
1022 | * @param string|null
|
1023 | * @param string|null
|
1023 | * @param string|null
|
1024 | * @return array|null
|
1024 | * @return array|null
|
1025 | * @access private
|
1025 | * @access private
|
1026 | */
|
1026 | */
|
1027 | function _packageInfo($package = null, $key = null, $channel = 'pear.php.net') |
1027 | function _packageInfo($package = null, $key = null, $channel = 'pear.php.net') |
1028 | {
|
1028 | {
|
1029 | if ($package === null) { |
1029 | if ($package === null) { |
1030 | if ($channel === null) { |
1030 | if ($channel === null) { |
1031 | $channels = $this->_listChannels(); |
1031 | $channels = $this->_listChannels(); |
1032 | $ret = array(); |
1032 | $ret = array(); |
1033 | foreach ($channels as $channel) { |
1033 | foreach ($channels as $channel) { |
1034 | $channel = strtolower($channel); |
1034 | $channel = strtolower($channel); |
1035 | $ret[$channel] = array(); |
1035 | $ret[$channel] = array(); |
1036 | $packages = $this->_listPackages($channel); |
1036 | $packages = $this->_listPackages($channel); |
1037 | foreach ($packages as $package) { |
1037 | foreach ($packages as $package) { |
1038 | $ret[$channel][] = $this->_packageInfo($package, null, $channel); |
1038 | $ret[$channel][] = $this->_packageInfo($package, null, $channel); |
1039 | }
|
1039 | }
|
1040 | }
|
1040 | }
|
1041 | return $ret; |
1041 | return $ret; |
1042 | }
|
1042 | }
|
1043 | $ps = $this->_listPackages($channel); |
1043 | $ps = $this->_listPackages($channel); |
1044 | if (!count($ps)) { |
1044 | if (!count($ps)) { |
1045 | return array(); |
1045 | return array(); |
1046 | }
|
1046 | }
|
1047 | return array_map(array(&$this, '_packageInfo'), |
1047 | return array_map(array(&$this, '_packageInfo'), |
1048 | $ps, array_fill(0, count($ps), null), |
1048 | $ps, array_fill(0, count($ps), null), |
1049 | array_fill(0, count($ps), $channel)); |
1049 | array_fill(0, count($ps), $channel)); |
1050 | }
|
1050 | }
|
1051 | $fp = $this->_openPackageFile($package, 'r', $channel); |
1051 | $fp = $this->_openPackageFile($package, 'r', $channel); |
1052 | if ($fp === null) { |
1052 | if ($fp === null) { |
1053 | return null; |
1053 | return null; |
1054 | }
|
1054 | }
|
1055 | $rt = get_magic_quotes_runtime(); |
1055 | $rt = get_magic_quotes_runtime(); |
1056 | set_magic_quotes_runtime(0); |
1056 | set_magic_quotes_runtime(0); |
1057 | clearstatcache(); |
1057 | clearstatcache(); |
1058 | $this->_closePackageFile($fp); |
1058 | $this->_closePackageFile($fp); |
1059 | $data = file_get_contents($this->_packageFileName($package, $channel)); |
1059 | $data = file_get_contents($this->_packageFileName($package, $channel)); |
1060 | set_magic_quotes_runtime($rt); |
1060 | set_magic_quotes_runtime($rt); |
1061 | $data = unserialize($data); |
1061 | $data = unserialize($data); |
1062 | if ($key === null) { |
1062 | if ($key === null) { |
1063 | return $data; |
1063 | return $data; |
1064 | }
|
1064 | }
|
1065 | // compatibility for package.xml version 2.0
|
1065 | // compatibility for package.xml version 2.0
|
1066 | if (isset($data['old'][$key])) { |
1066 | if (isset($data['old'][$key])) { |
1067 | return $data['old'][$key]; |
1067 | return $data['old'][$key]; |
1068 | }
|
1068 | }
|
1069 | if (isset($data[$key])) { |
1069 | if (isset($data[$key])) { |
1070 | return $data[$key]; |
1070 | return $data[$key]; |
1071 | }
|
1071 | }
|
1072 | return null; |
1072 | return null; |
1073 | }
|
1073 | }
|
1074 | 1074 | ||
1075 | // }}}
|
1075 | // }}}
|
1076 | // {{{ _channelInfo()
|
1076 | // {{{ _channelInfo()
|
1077 | 1077 | ||
1078 | /**
|
1078 | /**
|
1079 | * @param string Channel name
|
1079 | * @param string Channel name
|
1080 | * @param bool whether to strictly retrieve info of channels, not just aliases
|
1080 | * @param bool whether to strictly retrieve info of channels, not just aliases
|
1081 | * @return array|null
|
1081 | * @return array|null
|
1082 | */
|
1082 | */
|
1083 | function _channelInfo($channel, $noaliases = false) |
1083 | function _channelInfo($channel, $noaliases = false) |
1084 | {
|
1084 | {
|
1085 | if (!$this->_channelExists($channel, $noaliases)) { |
1085 | if (!$this->_channelExists($channel, $noaliases)) { |
1086 | return null; |
1086 | return null; |
1087 | }
|
1087 | }
|
1088 | $fp = $this->_openChannelFile($channel, 'r'); |
1088 | $fp = $this->_openChannelFile($channel, 'r'); |
1089 | if ($fp === null) { |
1089 | if ($fp === null) { |
1090 | return null; |
1090 | return null; |
1091 | }
|
1091 | }
|
1092 | $rt = get_magic_quotes_runtime(); |
1092 | $rt = get_magic_quotes_runtime(); |
1093 | set_magic_quotes_runtime(0); |
1093 | set_magic_quotes_runtime(0); |
1094 | clearstatcache(); |
1094 | clearstatcache(); |
1095 | $this->_closeChannelFile($fp); |
1095 | $this->_closeChannelFile($fp); |
1096 | $data = file_get_contents($this->_channelFileName($channel)); |
1096 | $data = file_get_contents($this->_channelFileName($channel)); |
1097 | set_magic_quotes_runtime($rt); |
1097 | set_magic_quotes_runtime($rt); |
1098 | $data = unserialize($data); |
1098 | $data = unserialize($data); |
1099 | return $data; |
1099 | return $data; |
1100 | }
|
1100 | }
|
1101 | 1101 | ||
1102 | // }}}
|
1102 | // }}}
|
1103 | // {{{ _listChannels()
|
1103 | // {{{ _listChannels()
|
1104 | 1104 | ||
1105 | function _listChannels() |
1105 | function _listChannels() |
1106 | {
|
1106 | {
|
1107 | $channellist = array(); |
1107 | $channellist = array(); |
1108 | if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) { |
1108 | if (!file_exists($this->channelsdir) || !is_dir($this->channelsdir)) { |
1109 | return array('pear.php.net', 'pecl.php.net', '__uri'); |
1109 | return array('pear.php.net', 'pecl.php.net', '__uri'); |
1110 | }
|
1110 | }
|
1111 | $dp = opendir($this->channelsdir); |
1111 | $dp = opendir($this->channelsdir); |
1112 | while ($ent = readdir($dp)) { |
1112 | while ($ent = readdir($dp)) { |
1113 | if ($ent{0} == '.' || substr($ent, -4) != '.reg') { |
1113 | if ($ent{0} == '.' || substr($ent, -4) != '.reg') { |
1114 | continue; |
1114 | continue; |
1115 | }
|
1115 | }
|
1116 | if ($ent == '__uri.reg') { |
1116 | if ($ent == '__uri.reg') { |
1117 | $channellist[] = '__uri'; |
1117 | $channellist[] = '__uri'; |
1118 | continue; |
1118 | continue; |
1119 | }
|
1119 | }
|
1120 | $channellist[] = str_replace('_', '/', substr($ent, 0, -4)); |
1120 | $channellist[] = str_replace('_', '/', substr($ent, 0, -4)); |
1121 | }
|
1121 | }
|
1122 | closedir($dp); |
1122 | closedir($dp); |
1123 | if (!in_array('pear.php.net', $channellist)) { |
1123 | if (!in_array('pear.php.net', $channellist)) { |
1124 | $channellist[] = 'pear.php.net'; |
1124 | $channellist[] = 'pear.php.net'; |
1125 | }
|
1125 | }
|
1126 | if (!in_array('pecl.php.net', $channellist)) { |
1126 | if (!in_array('pecl.php.net', $channellist)) { |
1127 | $channellist[] = 'pecl.php.net'; |
1127 | $channellist[] = 'pecl.php.net'; |
1128 | }
|
1128 | }
|
1129 | if (!in_array('__uri', $channellist)) { |
1129 | if (!in_array('__uri', $channellist)) { |
1130 | $channellist[] = '__uri'; |
1130 | $channellist[] = '__uri'; |
1131 | }
|
1131 | }
|
1132 | 1132 | ||
1133 | natsort($channellist); |
1133 | natsort($channellist); |
1134 | return $channellist; |
1134 | return $channellist; |
1135 | }
|
1135 | }
|
1136 | 1136 | ||
1137 | // }}}
|
1137 | // }}}
|
1138 | // {{{ _listPackages()
|
1138 | // {{{ _listPackages()
|
1139 | 1139 | ||
1140 | function _listPackages($channel = false) |
1140 | function _listPackages($channel = false) |
1141 | {
|
1141 | {
|
1142 | if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { |
1142 | if ($channel && $this->_getChannelFromAlias($channel) != 'pear.php.net') { |
1143 | return $this->_listChannelPackages($channel); |
1143 | return $this->_listChannelPackages($channel); |
1144 | }
|
1144 | }
|
1145 | if (!file_exists($this->statedir) || !is_dir($this->statedir)) { |
1145 | if (!file_exists($this->statedir) || !is_dir($this->statedir)) { |
1146 | return array(); |
1146 | return array(); |
1147 | }
|
1147 | }
|
1148 | $pkglist = array(); |
1148 | $pkglist = array(); |
1149 | $dp = opendir($this->statedir); |
1149 | $dp = opendir($this->statedir); |
1150 | if (!$dp) { |
1150 | if (!$dp) { |
1151 | return $pkglist; |
1151 | return $pkglist; |
1152 | }
|
1152 | }
|
1153 | while ($ent = readdir($dp)) { |
1153 | while ($ent = readdir($dp)) { |
1154 | if ($ent{0} == '.' || substr($ent, -4) != '.reg') { |
1154 | if ($ent{0} == '.' || substr($ent, -4) != '.reg') { |
1155 | continue; |
1155 | continue; |
1156 | }
|
1156 | }
|
1157 | $pkglist[] = substr($ent, 0, -4); |
1157 | $pkglist[] = substr($ent, 0, -4); |
1158 | }
|
1158 | }
|
1159 | closedir($dp); |
1159 | closedir($dp); |
1160 | return $pkglist; |
1160 | return $pkglist; |
1161 | }
|
1161 | }
|
1162 | 1162 | ||
1163 | // }}}
|
1163 | // }}}
|
1164 | // {{{ _listChannelPackages()
|
1164 | // {{{ _listChannelPackages()
|
1165 | 1165 | ||
1166 | function _listChannelPackages($channel) |
1166 | function _listChannelPackages($channel) |
1167 | {
|
1167 | {
|
1168 | $pkglist = array(); |
1168 | $pkglist = array(); |
1169 | if (!file_exists($this->_channelDirectoryName($channel)) || |
1169 | if (!file_exists($this->_channelDirectoryName($channel)) || |
1170 | !is_dir($this->_channelDirectoryName($channel))) { |
1170 | !is_dir($this->_channelDirectoryName($channel))) { |
1171 | return array(); |
1171 | return array(); |
1172 | }
|
1172 | }
|
1173 | $dp = opendir($this->_channelDirectoryName($channel)); |
1173 | $dp = opendir($this->_channelDirectoryName($channel)); |
1174 | if (!$dp) { |
1174 | if (!$dp) { |
1175 | return $pkglist; |
1175 | return $pkglist; |
1176 | }
|
1176 | }
|
1177 | while ($ent = readdir($dp)) { |
1177 | while ($ent = readdir($dp)) { |
1178 | if ($ent{0} == '.' || substr($ent, -4) != '.reg') { |
1178 | if ($ent{0} == '.' || substr($ent, -4) != '.reg') { |
1179 | continue; |
1179 | continue; |
1180 | }
|
1180 | }
|
1181 | $pkglist[] = substr($ent, 0, -4); |
1181 | $pkglist[] = substr($ent, 0, -4); |
1182 | }
|
1182 | }
|
1183 | closedir($dp); |
1183 | closedir($dp); |
1184 | return $pkglist; |
1184 | return $pkglist; |
1185 | }
|
1185 | }
|
1186 | 1186 | ||
1187 | // }}}
|
1187 | // }}}
|
1188 | 1188 | ||
1189 | function _listAllPackages() |
1189 | function _listAllPackages() |
1190 | {
|
1190 | {
|
1191 | $ret = array(); |
1191 | $ret = array(); |
1192 | foreach ($this->_listChannels() as $channel) { |
1192 | foreach ($this->_listChannels() as $channel) { |
1193 | $ret[$channel] = $this->_listPackages($channel); |
1193 | $ret[$channel] = $this->_listPackages($channel); |
1194 | }
|
1194 | }
|
1195 | return $ret; |
1195 | return $ret; |
1196 | }
|
1196 | }
|
1197 | 1197 | ||
1198 | /**
|
1198 | /**
|
1199 | * Add an installed package to the registry
|
1199 | * Add an installed package to the registry
|
1200 | * @param string package name
|
1200 | * @param string package name
|
1201 | * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
|
1201 | * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
|
1202 | * @return bool success of saving
|
1202 | * @return bool success of saving
|
1203 | * @access private
|
1203 | * @access private
|
1204 | */
|
1204 | */
|
1205 | function _addPackage($package, $info) |
1205 | function _addPackage($package, $info) |
1206 | {
|
1206 | {
|
1207 | if ($this->_packageExists($package)) { |
1207 | if ($this->_packageExists($package)) { |
1208 | return false; |
1208 | return false; |
1209 | }
|
1209 | }
|
1210 | $fp = $this->_openPackageFile($package, 'wb'); |
1210 | $fp = $this->_openPackageFile($package, 'wb'); |
1211 | if ($fp === null) { |
1211 | if ($fp === null) { |
1212 | return false; |
1212 | return false; |
1213 | }
|
1213 | }
|
1214 | $info['_lastmodified'] = time(); |
1214 | $info['_lastmodified'] = time(); |
1215 | fwrite($fp, serialize($info)); |
1215 | fwrite($fp, serialize($info)); |
1216 | $this->_closePackageFile($fp); |
1216 | $this->_closePackageFile($fp); |
1217 | if (isset($info['filelist'])) { |
1217 | if (isset($info['filelist'])) { |
1218 | $this->_rebuildFileMap(); |
1218 | $this->_rebuildFileMap(); |
1219 | }
|
1219 | }
|
1220 | return true; |
1220 | return true; |
1221 | }
|
1221 | }
|
1222 | 1222 | ||
1223 | /**
|
1223 | /**
|
1224 | * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
|
1224 | * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
|
1225 | * @return bool
|
1225 | * @return bool
|
1226 | * @access private
|
1226 | * @access private
|
1227 | */
|
1227 | */
|
1228 | function _addPackage2($info) |
1228 | function _addPackage2($info) |
1229 | {
|
1229 | {
|
1230 | if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) { |
1230 | if (!is_a($info, 'PEAR_PackageFile_v1') && !is_a($info, 'PEAR_PackageFile_v2')) { |
1231 | return false; |
1231 | return false; |
1232 | }
|
1232 | }
|
1233 | 1233 | ||
1234 | if (!$info->validate()) { |
1234 | if (!$info->validate()) { |
1235 | if (class_exists('PEAR_Common')) { |
1235 | if (class_exists('PEAR_Common')) { |
1236 | $ui = PEAR_Frontend::singleton(); |
1236 | $ui = PEAR_Frontend::singleton(); |
1237 | if ($ui) { |
1237 | if ($ui) { |
1238 | foreach ($info->getValidationWarnings() as $err) { |
1238 | foreach ($info->getValidationWarnings() as $err) { |
1239 | $ui->log($err['message'], true); |
1239 | $ui->log($err['message'], true); |
1240 | }
|
1240 | }
|
1241 | }
|
1241 | }
|
1242 | }
|
1242 | }
|
1243 | return false; |
1243 | return false; |
1244 | }
|
1244 | }
|
1245 | $channel = $info->getChannel(); |
1245 | $channel = $info->getChannel(); |
1246 | $package = $info->getPackage(); |
1246 | $package = $info->getPackage(); |
1247 | $save = $info; |
1247 | $save = $info; |
1248 | if ($this->_packageExists($package, $channel)) { |
1248 | if ($this->_packageExists($package, $channel)) { |
1249 | return false; |
1249 | return false; |
1250 | }
|
1250 | }
|
1251 | if (!$this->_channelExists($channel, true)) { |
1251 | if (!$this->_channelExists($channel, true)) { |
1252 | return false; |
1252 | return false; |
1253 | }
|
1253 | }
|
1254 | $info = $info->toArray(true); |
1254 | $info = $info->toArray(true); |
1255 | if (!$info) { |
1255 | if (!$info) { |
1256 | return false; |
1256 | return false; |
1257 | }
|
1257 | }
|
1258 | $fp = $this->_openPackageFile($package, 'wb', $channel); |
1258 | $fp = $this->_openPackageFile($package, 'wb', $channel); |
1259 | if ($fp === null) { |
1259 | if ($fp === null) { |
1260 | return false; |
1260 | return false; |
1261 | }
|
1261 | }
|
1262 | $info['_lastmodified'] = time(); |
1262 | $info['_lastmodified'] = time(); |
1263 | fwrite($fp, serialize($info)); |
1263 | fwrite($fp, serialize($info)); |
1264 | $this->_closePackageFile($fp); |
1264 | $this->_closePackageFile($fp); |
1265 | $this->_rebuildFileMap(); |
1265 | $this->_rebuildFileMap(); |
1266 | return true; |
1266 | return true; |
1267 | }
|
1267 | }
|
1268 | 1268 | ||
1269 | /**
|
1269 | /**
|
1270 | * @param string Package name
|
1270 | * @param string Package name
|
1271 | * @param array parsed package.xml 1.0
|
1271 | * @param array parsed package.xml 1.0
|
1272 | * @param bool this parameter is only here for BC. Don't use it.
|
1272 | * @param bool this parameter is only here for BC. Don't use it.
|
1273 | * @access private
|
1273 | * @access private
|
1274 | */
|
1274 | */
|
1275 | function _updatePackage($package, $info, $merge = true) |
1275 | function _updatePackage($package, $info, $merge = true) |
1276 | {
|
1276 | {
|
1277 | $oldinfo = $this->_packageInfo($package); |
1277 | $oldinfo = $this->_packageInfo($package); |
1278 | if (empty($oldinfo)) { |
1278 | if (empty($oldinfo)) { |
1279 | return false; |
1279 | return false; |
1280 | }
|
1280 | }
|
1281 | $fp = $this->_openPackageFile($package, 'w'); |
1281 | $fp = $this->_openPackageFile($package, 'w'); |
1282 | if ($fp === null) { |
1282 | if ($fp === null) { |
1283 | return false; |
1283 | return false; |
1284 | }
|
1284 | }
|
1285 | if (is_object($info)) { |
1285 | if (is_object($info)) { |
1286 | $info = $info->toArray(); |
1286 | $info = $info->toArray(); |
1287 | }
|
1287 | }
|
1288 | $info['_lastmodified'] = time(); |
1288 | $info['_lastmodified'] = time(); |
1289 | $newinfo = $info; |
1289 | $newinfo = $info; |
1290 | if ($merge) { |
1290 | if ($merge) { |
1291 | $info = array_merge($oldinfo, $info); |
1291 | $info = array_merge($oldinfo, $info); |
1292 | } else { |
1292 | } else { |
1293 | $diff = $info; |
1293 | $diff = $info; |
1294 | }
|
1294 | }
|
1295 | fwrite($fp, serialize($info)); |
1295 | fwrite($fp, serialize($info)); |
1296 | $this->_closePackageFile($fp); |
1296 | $this->_closePackageFile($fp); |
1297 | if (isset($newinfo['filelist'])) { |
1297 | if (isset($newinfo['filelist'])) { |
1298 | $this->_rebuildFileMap(); |
1298 | $this->_rebuildFileMap(); |
1299 | }
|
1299 | }
|
1300 | return true; |
1300 | return true; |
1301 | }
|
1301 | }
|
1302 | 1302 | ||
1303 | /**
|
1303 | /**
|
1304 | * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
|
1304 | * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
|
1305 | * @return bool
|
1305 | * @return bool
|
1306 | * @access private
|
1306 | * @access private
|
1307 | */
|
1307 | */
|
1308 | function _updatePackage2($info) |
1308 | function _updatePackage2($info) |
1309 | {
|
1309 | {
|
1310 | if (!$this->_packageExists($info->getPackage(), $info->getChannel())) { |
1310 | if (!$this->_packageExists($info->getPackage(), $info->getChannel())) { |
1311 | return false; |
1311 | return false; |
1312 | }
|
1312 | }
|
1313 | $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel()); |
1313 | $fp = $this->_openPackageFile($info->getPackage(), 'w', $info->getChannel()); |
1314 | if ($fp === null) { |
1314 | if ($fp === null) { |
1315 | return false; |
1315 | return false; |
1316 | }
|
1316 | }
|
1317 | $save = $info; |
1317 | $save = $info; |
1318 | $info = $save->getArray(true); |
1318 | $info = $save->getArray(true); |
1319 | $info['_lastmodified'] = time(); |
1319 | $info['_lastmodified'] = time(); |
1320 | fwrite($fp, serialize($info)); |
1320 | fwrite($fp, serialize($info)); |
1321 | $this->_closePackageFile($fp); |
1321 | $this->_closePackageFile($fp); |
1322 | $this->_rebuildFileMap(); |
1322 | $this->_rebuildFileMap(); |
1323 | return true; |
1323 | return true; |
1324 | }
|
1324 | }
|
1325 | 1325 | ||
1326 | /**
|
1326 | /**
|
1327 | * @param string Package name
|
1327 | * @param string Package name
|
1328 | * @param string Channel name
|
1328 | * @param string Channel name
|
1329 | * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
|
1329 | * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
|
1330 | * @access private
|
1330 | * @access private
|
1331 | */
|
1331 | */
|
1332 | function &_getPackage($package, $channel = 'pear.php.net') |
1332 | function &_getPackage($package, $channel = 'pear.php.net') |
1333 | {
|
1333 | {
|
1334 | $info = $this->_packageInfo($package, null, $channel); |
1334 | $info = $this->_packageInfo($package, null, $channel); |
1335 | if ($info === null) { |
1335 | if ($info === null) { |
1336 | return $info; |
1336 | return $info; |
1337 | }
|
1337 | }
|
1338 | $a = $this->_config; |
1338 | $a = $this->_config; |
1339 | if (!$a) { |
1339 | if (!$a) { |
1340 | $this->_config = &new PEAR_Config; |
1340 | $this->_config = &new PEAR_Config; |
1341 | $this->_config->set('php_dir', $this->statedir); |
1341 | $this->_config->set('php_dir', $this->statedir); |
1342 | }
|
1342 | }
|
1343 | if (!class_exists('PEAR_PackageFile')) { |
1343 | if (!class_exists('PEAR_PackageFile')) { |
1344 | require_once 'PEAR/PackageFile.php'; |
1344 | require_once 'PEAR/PackageFile.php'; |
1345 | }
|
1345 | }
|
1346 | $pkg = &new PEAR_PackageFile($this->_config); |
1346 | $pkg = &new PEAR_PackageFile($this->_config); |
1347 | $pf = &$pkg->fromArray($info); |
1347 | $pf = &$pkg->fromArray($info); |
1348 | return $pf; |
1348 | return $pf; |
1349 | }
|
1349 | }
|
1350 | 1350 | ||
1351 | /**
|
1351 | /**
|
1352 | * @param string channel name
|
1352 | * @param string channel name
|
1353 | * @param bool whether to strictly retrieve channel names
|
1353 | * @param bool whether to strictly retrieve channel names
|
1354 | * @return PEAR_ChannelFile|PEAR_Error
|
1354 | * @return PEAR_ChannelFile|PEAR_Error
|
1355 | * @access private
|
1355 | * @access private
|
1356 | */
|
1356 | */
|
1357 | function &_getChannel($channel, $noaliases = false) |
1357 | function &_getChannel($channel, $noaliases = false) |
1358 | {
|
1358 | {
|
1359 | $ch = false; |
1359 | $ch = false; |
1360 | if ($this->_channelExists($channel, $noaliases)) { |
1360 | if ($this->_channelExists($channel, $noaliases)) { |
1361 | $chinfo = $this->_channelInfo($channel, $noaliases); |
1361 | $chinfo = $this->_channelInfo($channel, $noaliases); |
1362 | if ($chinfo) { |
1362 | if ($chinfo) { |
1363 | if (!class_exists('PEAR_ChannelFile')) { |
1363 | if (!class_exists('PEAR_ChannelFile')) { |
1364 | require_once 'PEAR/ChannelFile.php'; |
1364 | require_once 'PEAR/ChannelFile.php'; |
1365 | }
|
1365 | }
|
1366 | $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo); |
1366 | $ch = &PEAR_ChannelFile::fromArrayWithErrors($chinfo); |
1367 | }
|
1367 | }
|
1368 | }
|
1368 | }
|
1369 | if ($ch) { |
1369 | if ($ch) { |
1370 | if ($ch->validate()) { |
1370 | if ($ch->validate()) { |
1371 | return $ch; |
1371 | return $ch; |
1372 | }
|
1372 | }
|
1373 | foreach ($ch->getErrors(true) as $err) { |
1373 | foreach ($ch->getErrors(true) as $err) { |
1374 | $message = $err['message'] . "\n"; |
1374 | $message = $err['message'] . "\n"; |
1375 | }
|
1375 | }
|
1376 | $ch = PEAR::raiseError($message); |
1376 | $ch = PEAR::raiseError($message); |
1377 | return $ch; |
1377 | return $ch; |
1378 | }
|
1378 | }
|
1379 | if ($this->_getChannelFromAlias($channel) == 'pear.php.net') { |
1379 | if ($this->_getChannelFromAlias($channel) == 'pear.php.net') { |
1380 | // the registry is not properly set up, so use defaults
|
1380 | // the registry is not properly set up, so use defaults
|
1381 | if (!class_exists('PEAR_ChannelFile')) { |
1381 | if (!class_exists('PEAR_ChannelFile')) { |
1382 | require_once 'PEAR/ChannelFile.php'; |
1382 | require_once 'PEAR/ChannelFile.php'; |
1383 | }
|
1383 | }
|
1384 | $pear_channel = new PEAR_ChannelFile; |
1384 | $pear_channel = new PEAR_ChannelFile; |
1385 | $pear_channel->setName('pear.php.net'); |
1385 | $pear_channel->setName('pear.php.net'); |
1386 | $pear_channel->setAlias('pear'); |
1386 | $pear_channel->setAlias('pear'); |
1387 | $pear_channel->setSummary('PHP Extension and Application Repository'); |
1387 | $pear_channel->setSummary('PHP Extension and Application Repository'); |
1388 | $pear_channel->setDefaultPEARProtocols(); |
1388 | $pear_channel->setDefaultPEARProtocols(); |
1389 | $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); |
1389 | $pear_channel->setBaseURL('REST1.0', 'http://pear.php.net/rest/'); |
1390 | $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); |
1390 | $pear_channel->setBaseURL('REST1.1', 'http://pear.php.net/rest/'); |
1391 | return $pear_channel; |
1391 | return $pear_channel; |
1392 | }
|
1392 | }
|
1393 | if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { |
1393 | if ($this->_getChannelFromAlias($channel) == 'pecl.php.net') { |
1394 | // the registry is not properly set up, so use defaults
|
1394 | // the registry is not properly set up, so use defaults
|
1395 | if (!class_exists('PEAR_ChannelFile')) { |
1395 | if (!class_exists('PEAR_ChannelFile')) { |
1396 | require_once 'PEAR/ChannelFile.php'; |
1396 | require_once 'PEAR/ChannelFile.php'; |
1397 | }
|
1397 | }
|
1398 | $pear_channel = new PEAR_ChannelFile; |
1398 | $pear_channel = new PEAR_ChannelFile; |
1399 | $pear_channel->setName('pecl.php.net'); |
1399 | $pear_channel->setName('pecl.php.net'); |
1400 | $pear_channel->setAlias('pecl'); |
1400 | $pear_channel->setAlias('pecl'); |
1401 | $pear_channel->setSummary('PHP Extension Community Library'); |
1401 | $pear_channel->setSummary('PHP Extension Community Library'); |
1402 | $pear_channel->setDefaultPEARProtocols(); |
1402 | $pear_channel->setDefaultPEARProtocols(); |
1403 | $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); |
1403 | $pear_channel->setBaseURL('REST1.0', 'http://pecl.php.net/rest/'); |
1404 | $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); |
1404 | $pear_channel->setBaseURL('REST1.1', 'http://pecl.php.net/rest/'); |
1405 | $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); |
1405 | $pear_channel->setValidationPackage('PEAR_Validator_PECL', '1.0'); |
1406 | return $pear_channel; |
1406 | return $pear_channel; |
1407 | }
|
1407 | }
|
1408 | if ($this->_getChannelFromAlias($channel) == '__uri') { |
1408 | if ($this->_getChannelFromAlias($channel) == '__uri') { |
1409 | // the registry is not properly set up, so use defaults
|
1409 | // the registry is not properly set up, so use defaults
|
1410 | if (!class_exists('PEAR_ChannelFile')) { |
1410 | if (!class_exists('PEAR_ChannelFile')) { |
1411 | require_once 'PEAR/ChannelFile.php'; |
1411 | require_once 'PEAR/ChannelFile.php'; |
1412 | }
|
1412 | }
|
1413 | $private = new PEAR_ChannelFile; |
1413 | $private = new PEAR_ChannelFile; |
1414 | $private->setName('__uri'); |
1414 | $private->setName('__uri'); |
1415 | $private->addFunction('xmlrpc', '1.0', '****'); |
1415 | $private->addFunction('xmlrpc', '1.0', '****'); |
1416 | $private->setSummary('Pseudo-channel for static packages'); |
1416 | $private->setSummary('Pseudo-channel for static packages'); |
1417 | return $private; |
1417 | return $private; |
1418 | }
|
1418 | }
|
1419 | return $ch; |
1419 | return $ch; |
1420 | }
|
1420 | }
|
1421 | 1421 | ||
1422 | // {{{ packageExists()
|
1422 | // {{{ packageExists()
|
1423 | 1423 | ||
1424 | /**
|
1424 | /**
|
1425 | * @param string Package name
|
1425 | * @param string Package name
|
1426 | * @param string Channel name
|
1426 | * @param string Channel name
|
1427 | * @return bool
|
1427 | * @return bool
|
1428 | */
|
1428 | */
|
1429 | function packageExists($package, $channel = 'pear.php.net') |
1429 | function packageExists($package, $channel = 'pear.php.net') |
1430 | {
|
1430 | {
|
1431 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1431 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1432 | return $e; |
1432 | return $e; |
1433 | }
|
1433 | }
|
1434 | $ret = $this->_packageExists($package, $channel); |
1434 | $ret = $this->_packageExists($package, $channel); |
1435 | $this->_unlock(); |
1435 | $this->_unlock(); |
1436 | return $ret; |
1436 | return $ret; |
1437 | }
|
1437 | }
|
1438 | 1438 | ||
1439 | // }}}
|
1439 | // }}}
|
1440 | 1440 | ||
1441 | // {{{ channelExists()
|
1441 | // {{{ channelExists()
|
1442 | 1442 | ||
1443 | /**
|
1443 | /**
|
1444 | * @param string channel name
|
1444 | * @param string channel name
|
1445 | * @param bool if true, then aliases will be ignored
|
1445 | * @param bool if true, then aliases will be ignored
|
1446 | * @return bool
|
1446 | * @return bool
|
1447 | */
|
1447 | */
|
1448 | function channelExists($channel, $noaliases = false) |
1448 | function channelExists($channel, $noaliases = false) |
1449 | {
|
1449 | {
|
1450 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1450 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1451 | return $e; |
1451 | return $e; |
1452 | }
|
1452 | }
|
1453 | $ret = $this->_channelExists($channel, $noaliases); |
1453 | $ret = $this->_channelExists($channel, $noaliases); |
1454 | $this->_unlock(); |
1454 | $this->_unlock(); |
1455 | return $ret; |
1455 | return $ret; |
1456 | }
|
1456 | }
|
1457 | 1457 | ||
1458 | // }}}
|
1458 | // }}}
|
1459 | 1459 | ||
1460 | // {{{ isAlias()
|
1460 | // {{{ isAlias()
|
1461 | 1461 | ||
1462 | /**
|
1462 | /**
|
1463 | * Determines whether the parameter is an alias of a channel
|
1463 | * Determines whether the parameter is an alias of a channel
|
1464 | * @param string
|
1464 | * @param string
|
1465 | * @return bool
|
1465 | * @return bool
|
1466 | */
|
1466 | */
|
1467 | function isAlias($alias) |
1467 | function isAlias($alias) |
1468 | {
|
1468 | {
|
1469 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1469 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1470 | return $e; |
1470 | return $e; |
1471 | }
|
1471 | }
|
1472 | $ret = $this->_isChannelAlias($alias); |
1472 | $ret = $this->_isChannelAlias($alias); |
1473 | $this->_unlock(); |
1473 | $this->_unlock(); |
1474 | return $ret; |
1474 | return $ret; |
1475 | }
|
1475 | }
|
1476 | 1476 | ||
1477 | // }}}
|
1477 | // }}}
|
1478 | // {{{ packageInfo()
|
1478 | // {{{ packageInfo()
|
1479 | 1479 | ||
1480 | /**
|
1480 | /**
|
1481 | * @param string|null
|
1481 | * @param string|null
|
1482 | * @param string|null
|
1482 | * @param string|null
|
1483 | * @param string
|
1483 | * @param string
|
1484 | * @return array|null
|
1484 | * @return array|null
|
1485 | */
|
1485 | */
|
1486 | function packageInfo($package = null, $key = null, $channel = 'pear.php.net') |
1486 | function packageInfo($package = null, $key = null, $channel = 'pear.php.net') |
1487 | {
|
1487 | {
|
1488 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1488 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1489 | return $e; |
1489 | return $e; |
1490 | }
|
1490 | }
|
1491 | $ret = $this->_packageInfo($package, $key, $channel); |
1491 | $ret = $this->_packageInfo($package, $key, $channel); |
1492 | $this->_unlock(); |
1492 | $this->_unlock(); |
1493 | return $ret; |
1493 | return $ret; |
1494 | }
|
1494 | }
|
1495 | 1495 | ||
1496 | // }}}
|
1496 | // }}}
|
1497 | // {{{ channelInfo()
|
1497 | // {{{ channelInfo()
|
1498 | 1498 | ||
1499 | /**
|
1499 | /**
|
1500 | * Retrieve a raw array of channel data.
|
1500 | * Retrieve a raw array of channel data.
|
1501 | *
|
1501 | *
|
1502 | * Do not use this, instead use {@link getChannel()} for normal
|
1502 | * Do not use this, instead use {@link getChannel()} for normal
|
1503 | * operations. Array structure is undefined in this method
|
1503 | * operations. Array structure is undefined in this method
|
1504 | * @param string channel name
|
1504 | * @param string channel name
|
1505 | * @param bool whether to strictly retrieve information only on non-aliases
|
1505 | * @param bool whether to strictly retrieve information only on non-aliases
|
1506 | * @return array|null|PEAR_Error
|
1506 | * @return array|null|PEAR_Error
|
1507 | */
|
1507 | */
|
1508 | function channelInfo($channel = null, $noaliases = false) |
1508 | function channelInfo($channel = null, $noaliases = false) |
1509 | {
|
1509 | {
|
1510 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1510 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1511 | return $e; |
1511 | return $e; |
1512 | }
|
1512 | }
|
1513 | $ret = $this->_channelInfo($channel, $noaliases); |
1513 | $ret = $this->_channelInfo($channel, $noaliases); |
1514 | $this->_unlock(); |
1514 | $this->_unlock(); |
1515 | return $ret; |
1515 | return $ret; |
1516 | }
|
1516 | }
|
1517 | 1517 | ||
1518 | // }}}
|
1518 | // }}}
|
1519 | 1519 | ||
1520 | /**
|
1520 | /**
|
1521 | * @param string
|
1521 | * @param string
|
1522 | */
|
1522 | */
|
1523 | function channelName($channel) |
1523 | function channelName($channel) |
1524 | {
|
1524 | {
|
1525 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1525 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1526 | return $e; |
1526 | return $e; |
1527 | }
|
1527 | }
|
1528 | $ret = $this->_getChannelFromAlias($channel); |
1528 | $ret = $this->_getChannelFromAlias($channel); |
1529 | $this->_unlock(); |
1529 | $this->_unlock(); |
1530 | return $ret; |
1530 | return $ret; |
1531 | }
|
1531 | }
|
1532 | 1532 | ||
1533 | /**
|
1533 | /**
|
1534 | * @param string
|
1534 | * @param string
|
1535 | */
|
1535 | */
|
1536 | function channelAlias($channel) |
1536 | function channelAlias($channel) |
1537 | {
|
1537 | {
|
1538 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1538 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1539 | return $e; |
1539 | return $e; |
1540 | }
|
1540 | }
|
1541 | $ret = $this->_getAlias($channel); |
1541 | $ret = $this->_getAlias($channel); |
1542 | $this->_unlock(); |
1542 | $this->_unlock(); |
1543 | return $ret; |
1543 | return $ret; |
1544 | }
|
1544 | }
|
1545 | // {{{ listPackages()
|
1545 | // {{{ listPackages()
|
1546 | 1546 | ||
1547 | function listPackages($channel = false) |
1547 | function listPackages($channel = false) |
1548 | {
|
1548 | {
|
1549 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1549 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1550 | return $e; |
1550 | return $e; |
1551 | }
|
1551 | }
|
1552 | $ret = $this->_listPackages($channel); |
1552 | $ret = $this->_listPackages($channel); |
1553 | $this->_unlock(); |
1553 | $this->_unlock(); |
1554 | return $ret; |
1554 | return $ret; |
1555 | }
|
1555 | }
|
1556 | 1556 | ||
1557 | // }}}
|
1557 | // }}}
|
1558 | // {{{ listAllPackages()
|
1558 | // {{{ listAllPackages()
|
1559 | 1559 | ||
1560 | function listAllPackages() |
1560 | function listAllPackages() |
1561 | {
|
1561 | {
|
1562 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1562 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1563 | return $e; |
1563 | return $e; |
1564 | }
|
1564 | }
|
1565 | $ret = $this->_listAllPackages(); |
1565 | $ret = $this->_listAllPackages(); |
1566 | $this->_unlock(); |
1566 | $this->_unlock(); |
1567 | return $ret; |
1567 | return $ret; |
1568 | }
|
1568 | }
|
1569 | 1569 | ||
1570 | // }}}
|
1570 | // }}}
|
1571 | // {{{ listChannel()
|
1571 | // {{{ listChannel()
|
1572 | 1572 | ||
1573 | function listChannels() |
1573 | function listChannels() |
1574 | {
|
1574 | {
|
1575 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1575 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1576 | return $e; |
1576 | return $e; |
1577 | }
|
1577 | }
|
1578 | $ret = $this->_listChannels(); |
1578 | $ret = $this->_listChannels(); |
1579 | $this->_unlock(); |
1579 | $this->_unlock(); |
1580 | return $ret; |
1580 | return $ret; |
1581 | }
|
1581 | }
|
1582 | 1582 | ||
1583 | // }}}
|
1583 | // }}}
|
1584 | // {{{ addPackage()
|
1584 | // {{{ addPackage()
|
1585 | 1585 | ||
1586 | /**
|
1586 | /**
|
1587 | * Add an installed package to the registry
|
1587 | * Add an installed package to the registry
|
1588 | * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
|
1588 | * @param string|PEAR_PackageFile_v1|PEAR_PackageFile_v2 package name or object
|
1589 | * that will be passed to {@link addPackage2()}
|
1589 | * that will be passed to {@link addPackage2()}
|
1590 | * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
|
1590 | * @param array package info (parsed by PEAR_Common::infoFrom*() methods)
|
1591 | * @return bool success of saving
|
1591 | * @return bool success of saving
|
1592 | */
|
1592 | */
|
1593 | function addPackage($package, $info) |
1593 | function addPackage($package, $info) |
1594 | {
|
1594 | {
|
1595 | if (is_object($info)) { |
1595 | if (is_object($info)) { |
1596 | return $this->addPackage2($info); |
1596 | return $this->addPackage2($info); |
1597 | }
|
1597 | }
|
1598 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1598 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1599 | return $e; |
1599 | return $e; |
1600 | }
|
1600 | }
|
1601 | $ret = $this->_addPackage($package, $info); |
1601 | $ret = $this->_addPackage($package, $info); |
1602 | $this->_unlock(); |
1602 | $this->_unlock(); |
1603 | if ($ret) { |
1603 | if ($ret) { |
1604 | if (!class_exists('PEAR_PackageFile_v1')) { |
1604 | if (!class_exists('PEAR_PackageFile_v1')) { |
1605 | require_once 'PEAR/PackageFile/v1.php'; |
1605 | require_once 'PEAR/PackageFile/v1.php'; |
1606 | }
|
1606 | }
|
1607 | $pf = new PEAR_PackageFile_v1; |
1607 | $pf = new PEAR_PackageFile_v1; |
1608 | $pf->setConfig($this->_config); |
1608 | $pf->setConfig($this->_config); |
1609 | $pf->fromArray($info); |
1609 | $pf->fromArray($info); |
1610 | $this->_dependencyDB->uninstallPackage($pf); |
1610 | $this->_dependencyDB->uninstallPackage($pf); |
1611 | $this->_dependencyDB->installPackage($pf); |
1611 | $this->_dependencyDB->installPackage($pf); |
1612 | }
|
1612 | }
|
1613 | return $ret; |
1613 | return $ret; |
1614 | }
|
1614 | }
|
1615 | 1615 | ||
1616 | // }}}
|
1616 | // }}}
|
1617 | // {{{ addPackage2()
|
1617 | // {{{ addPackage2()
|
1618 | 1618 | ||
1619 | function addPackage2($info) |
1619 | function addPackage2($info) |
1620 | {
|
1620 | {
|
1621 | if (!is_object($info)) { |
1621 | if (!is_object($info)) { |
1622 | return $this->addPackage($info['package'], $info); |
1622 | return $this->addPackage($info['package'], $info); |
1623 | }
|
1623 | }
|
1624 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1624 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1625 | return $e; |
1625 | return $e; |
1626 | }
|
1626 | }
|
1627 | $ret = $this->_addPackage2($info); |
1627 | $ret = $this->_addPackage2($info); |
1628 | $this->_unlock(); |
1628 | $this->_unlock(); |
1629 | if ($ret) { |
1629 | if ($ret) { |
1630 | $this->_dependencyDB->uninstallPackage($info); |
1630 | $this->_dependencyDB->uninstallPackage($info); |
1631 | $this->_dependencyDB->installPackage($info); |
1631 | $this->_dependencyDB->installPackage($info); |
1632 | }
|
1632 | }
|
1633 | return $ret; |
1633 | return $ret; |
1634 | }
|
1634 | }
|
1635 | 1635 | ||
1636 | // }}}
|
1636 | // }}}
|
1637 | // {{{ updateChannel()
|
1637 | // {{{ updateChannel()
|
1638 | 1638 | ||
1639 | /**
|
1639 | /**
|
1640 | * For future expandibility purposes, separate this
|
1640 | * For future expandibility purposes, separate this
|
1641 | * @param PEAR_ChannelFile
|
1641 | * @param PEAR_ChannelFile
|
1642 | */
|
1642 | */
|
1643 | function updateChannel($channel, $lastmodified = null) |
1643 | function updateChannel($channel, $lastmodified = null) |
1644 | {
|
1644 | {
|
1645 | if ($channel->getName() == '__uri') { |
1645 | if ($channel->getName() == '__uri') { |
1646 | return false; |
1646 | return false; |
1647 | }
|
1647 | }
|
1648 | return $this->addChannel($channel, $lastmodified, true); |
1648 | return $this->addChannel($channel, $lastmodified, true); |
1649 | }
|
1649 | }
|
1650 | 1650 | ||
1651 | // }}}
|
1651 | // }}}
|
1652 | // {{{ deleteChannel()
|
1652 | // {{{ deleteChannel()
|
1653 | 1653 | ||
1654 | /**
|
1654 | /**
|
1655 | * Deletion fails if there are any packages installed from the channel
|
1655 | * Deletion fails if there are any packages installed from the channel
|
1656 | * @param string|PEAR_ChannelFile channel name
|
1656 | * @param string|PEAR_ChannelFile channel name
|
1657 | * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
|
1657 | * @return boolean|PEAR_Error True on deletion, false if it doesn't exist
|
1658 | */
|
1658 | */
|
1659 | function deleteChannel($channel) |
1659 | function deleteChannel($channel) |
1660 | {
|
1660 | {
|
1661 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1661 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1662 | return $e; |
1662 | return $e; |
1663 | }
|
1663 | }
|
1664 | $ret = $this->_deleteChannel($channel); |
1664 | $ret = $this->_deleteChannel($channel); |
1665 | $this->_unlock(); |
1665 | $this->_unlock(); |
1666 | if ($ret && is_a($this->_config, 'PEAR_Config')) { |
1666 | if ($ret && is_a($this->_config, 'PEAR_Config')) { |
1667 | $this->_config->setChannels($this->listChannels()); |
1667 | $this->_config->setChannels($this->listChannels()); |
1668 | }
|
1668 | }
|
1669 | return $ret; |
1669 | return $ret; |
1670 | }
|
1670 | }
|
1671 | 1671 | ||
1672 | // }}}
|
1672 | // }}}
|
1673 | // {{{ addChannel()
|
1673 | // {{{ addChannel()
|
1674 | 1674 | ||
1675 | /**
|
1675 | /**
|
1676 | * @param PEAR_ChannelFile Channel object
|
1676 | * @param PEAR_ChannelFile Channel object
|
1677 | * @param string Last-Modified header from HTTP for caching
|
1677 | * @param string Last-Modified header from HTTP for caching
|
1678 | * @return boolean|PEAR_Error True on creation, false if it already exists
|
1678 | * @return boolean|PEAR_Error True on creation, false if it already exists
|
1679 | */
|
1679 | */
|
1680 | function addChannel($channel, $lastmodified = false, $update = false) |
1680 | function addChannel($channel, $lastmodified = false, $update = false) |
1681 | {
|
1681 | {
|
1682 | if (!is_a($channel, 'PEAR_ChannelFile')) { |
1682 | if (!is_a($channel, 'PEAR_ChannelFile')) { |
1683 | return false; |
1683 | return false; |
1684 | }
|
1684 | }
|
1685 | if (!$channel->validate()) { |
1685 | if (!$channel->validate()) { |
1686 | return false; |
1686 | return false; |
1687 | }
|
1687 | }
|
1688 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1688 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1689 | return $e; |
1689 | return $e; |
1690 | }
|
1690 | }
|
1691 | $ret = $this->_addChannel($channel, $update, $lastmodified); |
1691 | $ret = $this->_addChannel($channel, $update, $lastmodified); |
1692 | $this->_unlock(); |
1692 | $this->_unlock(); |
1693 | if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) { |
1693 | if (!$update && $ret && is_a($this->_config, 'PEAR_Config')) { |
1694 | $this->_config->setChannels($this->listChannels()); |
1694 | $this->_config->setChannels($this->listChannels()); |
1695 | }
|
1695 | }
|
1696 | return $ret; |
1696 | return $ret; |
1697 | }
|
1697 | }
|
1698 | 1698 | ||
1699 | // }}}
|
1699 | // }}}
|
1700 | // {{{ deletePackage()
|
1700 | // {{{ deletePackage()
|
1701 | 1701 | ||
1702 | function deletePackage($package, $channel = 'pear.php.net') |
1702 | function deletePackage($package, $channel = 'pear.php.net') |
1703 | {
|
1703 | {
|
1704 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1704 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1705 | return $e; |
1705 | return $e; |
1706 | }
|
1706 | }
|
1707 | $file = $this->_packageFileName($package, $channel); |
1707 | $file = $this->_packageFileName($package, $channel); |
1708 | if (file_exists($file)) { |
1708 | if (file_exists($file)) { |
1709 | $ret = @unlink($file); |
1709 | $ret = @unlink($file); |
1710 | } else { |
1710 | } else { |
1711 | $ret = false; |
1711 | $ret = false; |
1712 | }
|
1712 | }
|
1713 | $this->_rebuildFileMap(); |
1713 | $this->_rebuildFileMap(); |
1714 | $this->_unlock(); |
1714 | $this->_unlock(); |
1715 | $p = array('channel' => $channel, 'package' => $package); |
1715 | $p = array('channel' => $channel, 'package' => $package); |
1716 | $this->_dependencyDB->uninstallPackage($p); |
1716 | $this->_dependencyDB->uninstallPackage($p); |
1717 | return $ret; |
1717 | return $ret; |
1718 | }
|
1718 | }
|
1719 | 1719 | ||
1720 | // }}}
|
1720 | // }}}
|
1721 | // {{{ updatePackage()
|
1721 | // {{{ updatePackage()
|
1722 | 1722 | ||
1723 | function updatePackage($package, $info, $merge = true) |
1723 | function updatePackage($package, $info, $merge = true) |
1724 | {
|
1724 | {
|
1725 | if (is_object($info)) { |
1725 | if (is_object($info)) { |
1726 | return $this->updatePackage2($info, $merge); |
1726 | return $this->updatePackage2($info, $merge); |
1727 | }
|
1727 | }
|
1728 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1728 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1729 | return $e; |
1729 | return $e; |
1730 | }
|
1730 | }
|
1731 | $ret = $this->_updatePackage($package, $info, $merge); |
1731 | $ret = $this->_updatePackage($package, $info, $merge); |
1732 | $this->_unlock(); |
1732 | $this->_unlock(); |
1733 | if ($ret) { |
1733 | if ($ret) { |
1734 | if (!class_exists('PEAR_PackageFile_v1')) { |
1734 | if (!class_exists('PEAR_PackageFile_v1')) { |
1735 | require_once 'PEAR/PackageFile/v1.php'; |
1735 | require_once 'PEAR/PackageFile/v1.php'; |
1736 | }
|
1736 | }
|
1737 | $pf = new PEAR_PackageFile_v1; |
1737 | $pf = new PEAR_PackageFile_v1; |
1738 | $pf->setConfig($this->_config); |
1738 | $pf->setConfig($this->_config); |
1739 | $pf->fromArray($this->packageInfo($package)); |
1739 | $pf->fromArray($this->packageInfo($package)); |
1740 | $this->_dependencyDB->uninstallPackage($pf); |
1740 | $this->_dependencyDB->uninstallPackage($pf); |
1741 | $this->_dependencyDB->installPackage($pf); |
1741 | $this->_dependencyDB->installPackage($pf); |
1742 | }
|
1742 | }
|
1743 | return $ret; |
1743 | return $ret; |
1744 | }
|
1744 | }
|
1745 | 1745 | ||
1746 | // }}}
|
1746 | // }}}
|
1747 | // {{{ updatePackage2()
|
1747 | // {{{ updatePackage2()
|
1748 | 1748 | ||
1749 | function updatePackage2($info) |
1749 | function updatePackage2($info) |
1750 | {
|
1750 | {
|
1751 | if (!is_object($info)) { |
1751 | if (!is_object($info)) { |
1752 | return $this->updatePackage($info['package'], $info, $merge); |
1752 | return $this->updatePackage($info['package'], $info, $merge); |
1753 | }
|
1753 | }
|
1754 | if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) { |
1754 | if (!$info->validate(PEAR_VALIDATE_DOWNLOADING)) { |
1755 | return false; |
1755 | return false; |
1756 | }
|
1756 | }
|
1757 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1757 | if (PEAR::isError($e = $this->_lock(LOCK_EX))) { |
1758 | return $e; |
1758 | return $e; |
1759 | }
|
1759 | }
|
1760 | $ret = $this->_updatePackage2($info); |
1760 | $ret = $this->_updatePackage2($info); |
1761 | $this->_unlock(); |
1761 | $this->_unlock(); |
1762 | if ($ret) { |
1762 | if ($ret) { |
1763 | $this->_dependencyDB->uninstallPackage($info); |
1763 | $this->_dependencyDB->uninstallPackage($info); |
1764 | $this->_dependencyDB->installPackage($info); |
1764 | $this->_dependencyDB->installPackage($info); |
1765 | }
|
1765 | }
|
1766 | return $ret; |
1766 | return $ret; |
1767 | }
|
1767 | }
|
1768 | 1768 | ||
1769 | // }}}
|
1769 | // }}}
|
1770 | // {{{ getChannel()
|
1770 | // {{{ getChannel()
|
1771 | /**
|
1771 | /**
|
1772 | * @param string channel name
|
1772 | * @param string channel name
|
1773 | * @param bool whether to strictly return raw channels (no aliases)
|
1773 | * @param bool whether to strictly return raw channels (no aliases)
|
1774 | * @return PEAR_ChannelFile|PEAR_Error
|
1774 | * @return PEAR_ChannelFile|PEAR_Error
|
1775 | */
|
1775 | */
|
1776 | function &getChannel($channel, $noaliases = false) |
1776 | function &getChannel($channel, $noaliases = false) |
1777 | {
|
1777 | {
|
1778 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1778 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1779 | return $e; |
1779 | return $e; |
1780 | }
|
1780 | }
|
1781 | $ret = &$this->_getChannel($channel, $noaliases); |
1781 | $ret = &$this->_getChannel($channel, $noaliases); |
1782 | $this->_unlock(); |
1782 | $this->_unlock(); |
1783 | if (!$ret) { |
1783 | if (!$ret) { |
1784 | return PEAR::raiseError('Unknown channel: ' . $channel); |
1784 | return PEAR::raiseError('Unknown channel: ' . $channel); |
1785 | }
|
1785 | }
|
1786 | return $ret; |
1786 | return $ret; |
1787 | }
|
1787 | }
|
1788 | 1788 | ||
1789 | // }}}
|
1789 | // }}}
|
1790 | // {{{ getPackage()
|
1790 | // {{{ getPackage()
|
1791 | /**
|
1791 | /**
|
1792 | * @param string package name
|
1792 | * @param string package name
|
1793 | * @param string channel name
|
1793 | * @param string channel name
|
1794 | * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
|
1794 | * @return PEAR_PackageFile_v1|PEAR_PackageFile_v2|null
|
1795 | */
|
1795 | */
|
1796 | function &getPackage($package, $channel = 'pear.php.net') |
1796 | function &getPackage($package, $channel = 'pear.php.net') |
1797 | {
|
1797 | {
|
1798 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1798 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1799 | return $e; |
1799 | return $e; |
1800 | }
|
1800 | }
|
1801 | $pf = &$this->_getPackage($package, $channel); |
1801 | $pf = &$this->_getPackage($package, $channel); |
1802 | $this->_unlock(); |
1802 | $this->_unlock(); |
1803 | return $pf; |
1803 | return $pf; |
1804 | }
|
1804 | }
|
1805 | 1805 | ||
1806 | // }}}
|
1806 | // }}}
|
1807 | 1807 | ||
1808 | /**
|
1808 | /**
|
1809 | * Get PEAR_PackageFile_v[1/2] objects representing the contents of
|
1809 | * Get PEAR_PackageFile_v[1/2] objects representing the contents of
|
1810 | * a dependency group that are installed.
|
1810 | * a dependency group that are installed.
|
1811 | *
|
1811 | *
|
1812 | * This is used at uninstall-time
|
1812 | * This is used at uninstall-time
|
1813 | * @param array
|
1813 | * @param array
|
1814 | * @return array|false
|
1814 | * @return array|false
|
1815 | */
|
1815 | */
|
1816 | function getInstalledGroup($group) |
1816 | function getInstalledGroup($group) |
1817 | {
|
1817 | {
|
1818 | $ret = array(); |
1818 | $ret = array(); |
1819 | if (isset($group['package'])) { |
1819 | if (isset($group['package'])) { |
1820 | if (!isset($group['package'][0])) { |
1820 | if (!isset($group['package'][0])) { |
1821 | $group['package'] = array($group['package']); |
1821 | $group['package'] = array($group['package']); |
1822 | }
|
1822 | }
|
1823 | foreach ($group['package'] as $package) { |
1823 | foreach ($group['package'] as $package) { |
1824 | $depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; |
1824 | $depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; |
1825 | $p = &$this->getPackage($package['name'], $depchannel); |
1825 | $p = &$this->getPackage($package['name'], $depchannel); |
1826 | if ($p) { |
1826 | if ($p) { |
1827 | $save = &$p; |
1827 | $save = &$p; |
1828 | $ret[] = &$save; |
1828 | $ret[] = &$save; |
1829 | }
|
1829 | }
|
1830 | }
|
1830 | }
|
1831 | }
|
1831 | }
|
1832 | if (isset($group['subpackage'])) { |
1832 | if (isset($group['subpackage'])) { |
1833 | if (!isset($group['subpackage'][0])) { |
1833 | if (!isset($group['subpackage'][0])) { |
1834 | $group['subpackage'] = array($group['subpackage']); |
1834 | $group['subpackage'] = array($group['subpackage']); |
1835 | }
|
1835 | }
|
1836 | foreach ($group['subpackage'] as $package) { |
1836 | foreach ($group['subpackage'] as $package) { |
1837 | $depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; |
1837 | $depchannel = isset($package['channel']) ? $package['channel'] : '__uri'; |
1838 | $p = &$this->getPackage($package['name'], $depchannel); |
1838 | $p = &$this->getPackage($package['name'], $depchannel); |
1839 | if ($p) { |
1839 | if ($p) { |
1840 | $save = &$p; |
1840 | $save = &$p; |
1841 | $ret[] = &$save; |
1841 | $ret[] = &$save; |
1842 | }
|
1842 | }
|
1843 | }
|
1843 | }
|
1844 | }
|
1844 | }
|
1845 | if (!count($ret)) { |
1845 | if (!count($ret)) { |
1846 | return false; |
1846 | return false; |
1847 | }
|
1847 | }
|
1848 | return $ret; |
1848 | return $ret; |
1849 | }
|
1849 | }
|
1850 | 1850 | ||
1851 | // {{{ getChannelValidator()
|
1851 | // {{{ getChannelValidator()
|
1852 | /**
|
1852 | /**
|
1853 | * @param string channel name
|
1853 | * @param string channel name
|
1854 | * @return PEAR_Validate|false
|
1854 | * @return PEAR_Validate|false
|
1855 | */
|
1855 | */
|
1856 | function &getChannelValidator($channel) |
1856 | function &getChannelValidator($channel) |
1857 | {
|
1857 | {
|
1858 | $chan = $this->getChannel($channel); |
1858 | $chan = $this->getChannel($channel); |
1859 | if (PEAR::isError($chan)) { |
1859 | if (PEAR::isError($chan)) { |
1860 | return $chan; |
1860 | return $chan; |
1861 | }
|
1861 | }
|
1862 | $val = $chan->getValidationObject(); |
1862 | $val = $chan->getValidationObject(); |
1863 | return $val; |
1863 | return $val; |
1864 | }
|
1864 | }
|
1865 | // }}}
|
1865 | // }}}
|
1866 | // {{{ getChannels()
|
1866 | // {{{ getChannels()
|
1867 | /**
|
1867 | /**
|
1868 | * @param string channel name
|
1868 | * @param string channel name
|
1869 | * @return array an array of PEAR_ChannelFile objects representing every installed channel
|
1869 | * @return array an array of PEAR_ChannelFile objects representing every installed channel
|
1870 | */
|
1870 | */
|
1871 | function &getChannels() |
1871 | function &getChannels() |
1872 | {
|
1872 | {
|
1873 | $ret = array(); |
1873 | $ret = array(); |
1874 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1874 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1875 | return $e; |
1875 | return $e; |
1876 | }
|
1876 | }
|
1877 | foreach ($this->_listChannels() as $channel) { |
1877 | foreach ($this->_listChannels() as $channel) { |
1878 | $e = &$this->_getChannel($channel); |
1878 | $e = &$this->_getChannel($channel); |
1879 | if (!$e || PEAR::isError($e)) { |
1879 | if (!$e || PEAR::isError($e)) { |
1880 | continue; |
1880 | continue; |
1881 | }
|
1881 | }
|
1882 | $ret[] = $e; |
1882 | $ret[] = $e; |
1883 | }
|
1883 | }
|
1884 | $this->_unlock(); |
1884 | $this->_unlock(); |
1885 | return $ret; |
1885 | return $ret; |
1886 | }
|
1886 | }
|
1887 | 1887 | ||
1888 | // }}}
|
1888 | // }}}
|
1889 | // {{{ checkFileMap()
|
1889 | // {{{ checkFileMap()
|
1890 | 1890 | ||
1891 | /**
|
1891 | /**
|
1892 | * Test whether a file or set of files belongs to a package.
|
1892 | * Test whether a file or set of files belongs to a package.
|
1893 | *
|
1893 | *
|
1894 | * If an array is passed in
|
1894 | * If an array is passed in
|
1895 | * @param string|array file path, absolute or relative to the pear
|
1895 | * @param string|array file path, absolute or relative to the pear
|
1896 | * install dir
|
1896 | * install dir
|
1897 | * @param string|array name of PEAR package or array('package' => name, 'channel' =>
|
1897 | * @param string|array name of PEAR package or array('package' => name, 'channel' =>
|
1898 | * channel) of a package that will be ignored
|
1898 | * channel) of a package that will be ignored
|
1899 | * @param string API version - 1.1 will exclude any files belonging to a package
|
1899 | * @param string API version - 1.1 will exclude any files belonging to a package
|
1900 | * @param array private recursion variable
|
1900 | * @param array private recursion variable
|
1901 | * @return array|false which package and channel the file belongs to, or an empty
|
1901 | * @return array|false which package and channel the file belongs to, or an empty
|
1902 | * string if the file does not belong to an installed package,
|
1902 | * string if the file does not belong to an installed package,
|
1903 | * or belongs to the second parameter's package
|
1903 | * or belongs to the second parameter's package
|
1904 | */
|
1904 | */
|
1905 | function checkFileMap($path, $package = false, $api = '1.0', $attrs = false) |
1905 | function checkFileMap($path, $package = false, $api = '1.0', $attrs = false) |
1906 | {
|
1906 | {
|
1907 | if (is_array($path)) { |
1907 | if (is_array($path)) { |
1908 | static $notempty; |
1908 | static $notempty; |
1909 | if (empty($notempty)) { |
1909 | if (empty($notempty)) { |
1910 | if (!class_exists('PEAR_Installer_Role')) { |
1910 | if (!class_exists('PEAR_Installer_Role')) { |
1911 | require_once 'PEAR/Installer/Role.php'; |
1911 | require_once 'PEAR/Installer/Role.php'; |
1912 | }
|
1912 | }
|
1913 | $notempty = create_function('$a','return !empty($a);'); |
1913 | $notempty = create_function('$a','return !empty($a);'); |
1914 | }
|
1914 | }
|
1915 | $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1])) |
1915 | $package = is_array($package) ? array(strtolower($package[0]), strtolower($package[1])) |
1916 | : strtolower($package); |
1916 | : strtolower($package); |
1917 | $pkgs = array(); |
1917 | $pkgs = array(); |
1918 | foreach ($path as $name => $attrs) { |
1918 | foreach ($path as $name => $attrs) { |
1919 | if (is_array($attrs)) { |
1919 | if (is_array($attrs)) { |
1920 | if (isset($attrs['install-as'])) { |
1920 | if (isset($attrs['install-as'])) { |
1921 | $name = $attrs['install-as']; |
1921 | $name = $attrs['install-as']; |
1922 | }
|
1922 | }
|
1923 | if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) { |
1923 | if (!in_array($attrs['role'], PEAR_Installer_Role::getInstallableRoles())) { |
1924 | // these are not installed
|
1924 | // these are not installed
|
1925 | continue; |
1925 | continue; |
1926 | }
|
1926 | }
|
1927 | if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) { |
1927 | if (!in_array($attrs['role'], PEAR_Installer_Role::getBaseinstallRoles())) { |
1928 | $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package; |
1928 | $attrs['baseinstalldir'] = is_array($package) ? $package[1] : $package; |
1929 | }
|
1929 | }
|
1930 | if (isset($attrs['baseinstalldir'])) { |
1930 | if (isset($attrs['baseinstalldir'])) { |
1931 | $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name; |
1931 | $name = $attrs['baseinstalldir'] . DIRECTORY_SEPARATOR . $name; |
1932 | }
|
1932 | }
|
1933 | }
|
1933 | }
|
1934 | $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs); |
1934 | $pkgs[$name] = $this->checkFileMap($name, $package, $api, $attrs); |
1935 | if (PEAR::isError($pkgs[$name])) { |
1935 | if (PEAR::isError($pkgs[$name])) { |
1936 | return $pkgs[$name]; |
1936 | return $pkgs[$name]; |
1937 | }
|
1937 | }
|
1938 | }
|
1938 | }
|
1939 | return array_filter($pkgs, $notempty); |
1939 | return array_filter($pkgs, $notempty); |
1940 | }
|
1940 | }
|
1941 | if (empty($this->filemap_cache)) { |
1941 | if (empty($this->filemap_cache)) { |
1942 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1942 | if (PEAR::isError($e = $this->_lock(LOCK_SH))) { |
1943 | return $e; |
1943 | return $e; |
1944 | }
|
1944 | }
|
1945 | $err = $this->_readFileMap(); |
1945 | $err = $this->_readFileMap(); |
1946 | $this->_unlock(); |
1946 | $this->_unlock(); |
1947 | if (PEAR::isError($err)) { |
1947 | if (PEAR::isError($err)) { |
1948 | return $err; |
1948 | return $err; |
1949 | }
|
1949 | }
|
1950 | }
|
1950 | }
|
1951 | if (!$attrs) { |
1951 | if (!$attrs) { |
1952 | $attrs = array('role' => 'php'); // any old call would be for PHP role only |
1952 | $attrs = array('role' => 'php'); // any old call would be for PHP role only |
1953 | }
|
1953 | }
|
1954 | if (isset($this->filemap_cache[$attrs['role']][$path])) { |
1954 | if (isset($this->filemap_cache[$attrs['role']][$path])) { |
1955 | if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { |
1955 | if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { |
1956 | return false; |
1956 | return false; |
1957 | }
|
1957 | }
|
1958 | return $this->filemap_cache[$attrs['role']][$path]; |
1958 | return $this->filemap_cache[$attrs['role']][$path]; |
1959 | }
|
1959 | }
|
1960 | $l = strlen($this->install_dir); |
1960 | $l = strlen($this->install_dir); |
1961 | if (substr($path, 0, $l) == $this->install_dir) { |
1961 | if (substr($path, 0, $l) == $this->install_dir) { |
1962 | $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l)); |
1962 | $path = preg_replace('!^'.DIRECTORY_SEPARATOR.'+!', '', substr($path, $l)); |
1963 | }
|
1963 | }
|
1964 | if (isset($this->filemap_cache[$attrs['role']][$path])) { |
1964 | if (isset($this->filemap_cache[$attrs['role']][$path])) { |
1965 | if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { |
1965 | if ($api >= '1.1' && $this->filemap_cache[$attrs['role']][$path] == $package) { |
1966 | return false; |
1966 | return false; |
1967 | }
|
1967 | }
|
1968 | return $this->filemap_cache[$attrs['role']][$path]; |
1968 | return $this->filemap_cache[$attrs['role']][$path]; |
1969 | }
|
1969 | }
|
1970 | return false; |
1970 | return false; |
1971 | }
|
1971 | }
|
1972 | 1972 | ||
1973 | // }}}
|
1973 | // }}}
|
1974 | // {{{ flush()
|
1974 | // {{{ flush()
|
1975 | /**
|
1975 | /**
|
1976 | * Force a reload of the filemap
|
1976 | * Force a reload of the filemap
|
1977 | * @since 1.5.0RC3
|
1977 | * @since 1.5.0RC3
|
1978 | */
|
1978 | */
|
1979 | function flushFileMap() |
1979 | function flushFileMap() |
1980 | {
|
1980 | {
|
1981 | $this->filemap_cache = null; |
1981 | $this->filemap_cache = null; |
1982 | clearstatcache(); // ensure that the next read gets the full, current filemap |
1982 | clearstatcache(); // ensure that the next read gets the full, current filemap |
1983 | }
|
1983 | }
|
1984 | 1984 | ||
1985 | // }}}
|
1985 | // }}}
|
1986 | // {{{ apiVersion()
|
1986 | // {{{ apiVersion()
|
1987 | /**
|
1987 | /**
|
1988 | * Get the expected API version. Channels API is version 1.1, as it is backwards
|
1988 | * Get the expected API version. Channels API is version 1.1, as it is backwards
|
1989 | * compatible with 1.0
|
1989 | * compatible with 1.0
|
1990 | * @return string
|
1990 | * @return string
|
1991 | */
|
1991 | */
|
1992 | function apiVersion() |
1992 | function apiVersion() |
1993 | {
|
1993 | {
|
1994 | return '1.1'; |
1994 | return '1.1'; |
1995 | }
|
1995 | }
|
1996 | // }}}
|
1996 | // }}}
|
1997 | 1997 | ||
1998 | 1998 | ||
1999 | /**
|
1999 | /**
|
2000 | * Parse a package name, or validate a parsed package name array
|
2000 | * Parse a package name, or validate a parsed package name array
|
2001 | * @param string|array pass in an array of format
|
2001 | * @param string|array pass in an array of format
|
2002 | * array(
|
2002 | * array(
|
2003 | * 'package' => 'pname',
|
2003 | * 'package' => 'pname',
|
2004 | * ['channel' => 'channame',]
|
2004 | * ['channel' => 'channame',]
|
2005 | * ['version' => 'version',]
|
2005 | * ['version' => 'version',]
|
2006 | * ['state' => 'state',]
|
2006 | * ['state' => 'state',]
|
2007 | * ['group' => 'groupname'])
|
2007 | * ['group' => 'groupname'])
|
2008 | * or a string of format
|
2008 | * or a string of format
|
2009 | * [channel://][channame/]pname[-version|-state][/group=groupname]
|
2009 | * [channel://][channame/]pname[-version|-state][/group=groupname]
|
2010 | * @return array|PEAR_Error
|
2010 | * @return array|PEAR_Error
|
2011 | */
|
2011 | */
|
2012 | function parsePackageName($param, $defaultchannel = 'pear.php.net') |
2012 | function parsePackageName($param, $defaultchannel = 'pear.php.net') |
2013 | {
|
2013 | {
|
2014 | $saveparam = $param; |
2014 | $saveparam = $param; |
2015 | if (is_array($param)) { |
2015 | if (is_array($param)) { |
2016 | // convert to string for error messages
|
2016 | // convert to string for error messages
|
2017 | $saveparam = $this->parsedPackageNameToString($param); |
2017 | $saveparam = $this->parsedPackageNameToString($param); |
2018 | // process the array
|
2018 | // process the array
|
2019 | if (!isset($param['package'])) { |
2019 | if (!isset($param['package'])) { |
2020 | return PEAR::raiseError('parsePackageName(): array $param ' . |
2020 | return PEAR::raiseError('parsePackageName(): array $param ' . |
2021 | 'must contain a valid package name in index "param"', |
2021 | 'must contain a valid package name in index "param"', |
2022 | 'package', null, null, $param); |
2022 | 'package', null, null, $param); |
2023 | }
|
2023 | }
|
2024 | if (!isset($param['uri'])) { |
2024 | if (!isset($param['uri'])) { |
2025 | if (!isset($param['channel'])) { |
2025 | if (!isset($param['channel'])) { |
2026 | $param['channel'] = $defaultchannel; |
2026 | $param['channel'] = $defaultchannel; |
2027 | }
|
2027 | }
|
2028 | } else { |
2028 | } else { |
2029 | $param['channel'] = '__uri'; |
2029 | $param['channel'] = '__uri'; |
2030 | }
|
2030 | }
|
2031 | } else { |
2031 | } else { |
2032 | $components = @parse_url((string) $param); |
2032 | $components = @parse_url((string) $param); |
2033 | if (isset($components['scheme'])) { |
2033 | if (isset($components['scheme'])) { |
2034 | if ($components['scheme'] == 'http') { |
2034 | if ($components['scheme'] == 'http') { |
2035 | // uri package
|
2035 | // uri package
|
2036 | $param = array('uri' => $param, 'channel' => '__uri'); |
2036 | $param = array('uri' => $param, 'channel' => '__uri'); |
2037 | } elseif($components['scheme'] != 'channel') { |
2037 | } elseif($components['scheme'] != 'channel') { |
2038 | return PEAR::raiseError('parsePackageName(): only channel:// uris may ' . |
2038 | return PEAR::raiseError('parsePackageName(): only channel:// uris may ' . |
2039 | 'be downloaded, not "' . $param . '"', 'invalid', null, null, $param); |
2039 | 'be downloaded, not "' . $param . '"', 'invalid', null, null, $param); |
2040 | }
|
2040 | }
|
2041 | }
|
2041 | }
|
2042 | if (!isset($components['path'])) { |
2042 | if (!isset($components['path'])) { |
2043 | return PEAR::raiseError('parsePackageName(): array $param ' . |
2043 | return PEAR::raiseError('parsePackageName(): array $param ' . |
2044 | 'must contain a valid package name in "' . $param . '"', |
2044 | 'must contain a valid package name in "' . $param . '"', |
2045 | 'package', null, null, $param); |
2045 | 'package', null, null, $param); |
2046 | }
|
2046 | }
|
2047 | if (isset($components['host'])) { |
2047 | if (isset($components['host'])) { |
2048 | // remove the leading "/"
|
2048 | // remove the leading "/"
|
2049 | $components['path'] = substr($components['path'], 1); |
2049 | $components['path'] = substr($components['path'], 1); |
2050 | }
|
2050 | }
|
2051 | if (!isset($components['scheme'])) { |
2051 | if (!isset($components['scheme'])) { |
2052 | if (strpos($components['path'], '/') !== false) { |
2052 | if (strpos($components['path'], '/') !== false) { |
2053 | if ($components['path']{0} == '/') { |
2053 | if ($components['path']{0} == '/') { |
2054 | return PEAR::raiseError('parsePackageName(): this is not ' . |
2054 | return PEAR::raiseError('parsePackageName(): this is not ' . |
2055 | 'a package name, it begins with "/" in "' . $param . '"', |
2055 | 'a package name, it begins with "/" in "' . $param . '"', |
2056 | 'invalid', null, null, $param); |
2056 | 'invalid', null, null, $param); |
2057 | }
|
2057 | }
|
2058 | $parts = explode('/', $components['path']); |
2058 | $parts = explode('/', $components['path']); |
2059 | $components['host'] = array_shift($parts); |
2059 | $components['host'] = array_shift($parts); |
2060 | if (count($parts) > 1) { |
2060 | if (count($parts) > 1) { |
2061 | $components['path'] = array_pop($parts); |
2061 | $components['path'] = array_pop($parts); |
2062 | $components['host'] .= '/' . implode('/', $parts); |
2062 | $components['host'] .= '/' . implode('/', $parts); |
2063 | } else { |
2063 | } else { |
2064 | $components['path'] = implode('/', $parts); |
2064 | $components['path'] = implode('/', $parts); |
2065 | }
|
2065 | }
|
2066 | } else { |
2066 | } else { |
2067 | $components['host'] = $defaultchannel; |
2067 | $components['host'] = $defaultchannel; |
2068 | }
|
2068 | }
|
2069 | } else { |
2069 | } else { |
2070 | if (strpos($components['path'], '/')) { |
2070 | if (strpos($components['path'], '/')) { |
2071 | $parts = explode('/', $components['path']); |
2071 | $parts = explode('/', $components['path']); |
2072 | $components['path'] = array_pop($parts); |
2072 | $components['path'] = array_pop($parts); |
2073 | $components['host'] .= '/' . implode('/', $parts); |
2073 | $components['host'] .= '/' . implode('/', $parts); |
2074 | }
|
2074 | }
|
2075 | }
|
2075 | }
|
2076 | 2076 | ||
2077 | if (is_array($param)) { |
2077 | if (is_array($param)) { |
2078 | $param['package'] = $components['path']; |
2078 | $param['package'] = $components['path']; |
2079 | } else { |
2079 | } else { |
2080 | $param = array( |
2080 | $param = array( |
2081 | 'package' => $components['path'] |
2081 | 'package' => $components['path'] |
2082 | ); |
2082 | ); |
2083 | if (isset($components['host'])) { |
2083 | if (isset($components['host'])) { |
2084 | $param['channel'] = $components['host']; |
2084 | $param['channel'] = $components['host']; |
2085 | }
|
2085 | }
|
2086 | }
|
2086 | }
|
2087 | if (isset($components['fragment'])) { |
2087 | if (isset($components['fragment'])) { |
2088 | $param['group'] = $components['fragment']; |
2088 | $param['group'] = $components['fragment']; |
2089 | }
|
2089 | }
|
2090 | if (isset($components['user'])) { |
2090 | if (isset($components['user'])) { |
2091 | $param['user'] = $components['user']; |
2091 | $param['user'] = $components['user']; |
2092 | }
|
2092 | }
|
2093 | if (isset($components['pass'])) { |
2093 | if (isset($components['pass'])) { |
2094 | $param['pass'] = $components['pass']; |
2094 | $param['pass'] = $components['pass']; |
2095 | }
|
2095 | }
|
2096 | if (isset($components['query'])) { |
2096 | if (isset($components['query'])) { |
2097 | parse_str($components['query'], $param['opts']); |
2097 | parse_str($components['query'], $param['opts']); |
2098 | }
|
2098 | }
|
2099 | // check for extension
|
2099 | // check for extension
|
2100 | $pathinfo = pathinfo($param['package']); |
2100 | $pathinfo = pathinfo($param['package']); |
2101 | if (isset($pathinfo['extension']) && |
2101 | if (isset($pathinfo['extension']) && |
2102 | in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) { |
2102 | in_array(strtolower($pathinfo['extension']), array('tgz', 'tar'))) { |
2103 | $param['extension'] = $pathinfo['extension']; |
2103 | $param['extension'] = $pathinfo['extension']; |
2104 | $param['package'] = substr($pathinfo['basename'], 0, |
2104 | $param['package'] = substr($pathinfo['basename'], 0, |
2105 | strlen($pathinfo['basename']) - 4); |
2105 | strlen($pathinfo['basename']) - 4); |
2106 | }
|
2106 | }
|
2107 | // check for version
|
2107 | // check for version
|
2108 | if (strpos($param['package'], '-')) { |
2108 | if (strpos($param['package'], '-')) { |
2109 | $test = explode('-', $param['package']); |
2109 | $test = explode('-', $param['package']); |
2110 | if (count($test) != 2) { |
2110 | if (count($test) != 2) { |
2111 | return PEAR::raiseError('parsePackageName(): only one version/state ' . |
2111 | return PEAR::raiseError('parsePackageName(): only one version/state ' . |
2112 | 'delimiter "-" is allowed in "' . $saveparam . '"', |
2112 | 'delimiter "-" is allowed in "' . $saveparam . '"', |
2113 | 'version', null, null, $param); |
2113 | 'version', null, null, $param); |
2114 | }
|
2114 | }
|
2115 | list($param['package'], $param['version']) = $test; |
2115 | list($param['package'], $param['version']) = $test; |
2116 | }
|
2116 | }
|
2117 | }
|
2117 | }
|
2118 | // validation
|
2118 | // validation
|
2119 | $info = $this->channelExists($param['channel']); |
2119 | $info = $this->channelExists($param['channel']); |
2120 | if (PEAR::isError($info)) { |
2120 | if (PEAR::isError($info)) { |
2121 | return $info; |
2121 | return $info; |
2122 | }
|
2122 | }
|
2123 | if (!$info) { |
2123 | if (!$info) { |
2124 | return PEAR::raiseError('unknown channel "' . $param['channel'] . |
2124 | return PEAR::raiseError('unknown channel "' . $param['channel'] . |
2125 | '" in "' . $saveparam . '"', 'channel', null, null, $param); |
2125 | '" in "' . $saveparam . '"', 'channel', null, null, $param); |
2126 | }
|
2126 | }
|
2127 | $chan = $this->getChannel($param['channel']); |
2127 | $chan = $this->getChannel($param['channel']); |
2128 | if (PEAR::isError($chan)) { |
2128 | if (PEAR::isError($chan)) { |
2129 | return $chan; |
2129 | return $chan; |
2130 | }
|
2130 | }
|
2131 | if (!$chan) { |
2131 | if (!$chan) { |
2132 | return PEAR::raiseError("Exception: corrupt registry, could not " . |
2132 | return PEAR::raiseError("Exception: corrupt registry, could not " . |
2133 | "retrieve channel " . $param['channel'] . " information", |
2133 | "retrieve channel " . $param['channel'] . " information", |
2134 | 'registry', null, null, $param); |
2134 | 'registry', null, null, $param); |
2135 | }
|
2135 | }
|
2136 | $param['channel'] = $chan->getName(); |
2136 | $param['channel'] = $chan->getName(); |
2137 | $validate = $chan->getValidationObject(); |
2137 | $validate = $chan->getValidationObject(); |
2138 | $vpackage = $chan->getValidationPackage(); |
2138 | $vpackage = $chan->getValidationPackage(); |
2139 | // validate package name
|
2139 | // validate package name
|
2140 | if (!$validate->validPackageName($param['package'], $vpackage['_content'])) { |
2140 | if (!$validate->validPackageName($param['package'], $vpackage['_content'])) { |
2141 | return PEAR::raiseError('parsePackageName(): invalid package name "' . |
2141 | return PEAR::raiseError('parsePackageName(): invalid package name "' . |
2142 | $param['package'] . '" in "' . $saveparam . '"', |
2142 | $param['package'] . '" in "' . $saveparam . '"', |
2143 | 'package', null, null, $param); |
2143 | 'package', null, null, $param); |
2144 | }
|
2144 | }
|
2145 | if (isset($param['group'])) { |
2145 | if (isset($param['group'])) { |
2146 | if (!PEAR_Validate::validGroupName($param['group'])) { |
2146 | if (!PEAR_Validate::validGroupName($param['group'])) { |
2147 | return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] . |
2147 | return PEAR::raiseError('parsePackageName(): dependency group "' . $param['group'] . |
2148 | '" is not a valid group name in "' . $saveparam . '"', 'group', null, null, |
2148 | '" is not a valid group name in "' . $saveparam . '"', 'group', null, null, |
2149 | $param); |
2149 | $param); |
2150 | }
|
2150 | }
|
2151 | }
|
2151 | }
|
2152 | if (isset($param['state'])) { |
2152 | if (isset($param['state'])) { |
2153 | if (!in_array(strtolower($param['state']), $validate->getValidStates())) { |
2153 | if (!in_array(strtolower($param['state']), $validate->getValidStates())) { |
2154 | return PEAR::raiseError('parsePackageName(): state "' . $param['state'] |
2154 | return PEAR::raiseError('parsePackageName(): state "' . $param['state'] |
2155 | . '" is not a valid state in "' . $saveparam . '"', |
2155 | . '" is not a valid state in "' . $saveparam . '"', |
2156 | 'state', null, null, $param); |
2156 | 'state', null, null, $param); |
2157 | }
|
2157 | }
|
2158 | }
|
2158 | }
|
2159 | if (isset($param['version'])) { |
2159 | if (isset($param['version'])) { |
2160 | if (isset($param['state'])) { |
2160 | if (isset($param['state'])) { |
2161 | return PEAR::raiseError('parsePackageName(): cannot contain both ' . |
2161 | return PEAR::raiseError('parsePackageName(): cannot contain both ' . |
2162 | 'a version and a stability (state) in "' . $saveparam . '"', |
2162 | 'a version and a stability (state) in "' . $saveparam . '"', |
2163 | 'version/state', null, null, $param); |
2163 | 'version/state', null, null, $param); |
2164 | }
|
2164 | }
|
2165 | // check whether version is actually a state
|
2165 | // check whether version is actually a state
|
2166 | if (in_array(strtolower($param['version']), $validate->getValidStates())) { |
2166 | if (in_array(strtolower($param['version']), $validate->getValidStates())) { |
2167 | $param['state'] = strtolower($param['version']); |
2167 | $param['state'] = strtolower($param['version']); |
2168 | unset($param['version']); |
2168 | unset($param['version']); |
2169 | } else { |
2169 | } else { |
2170 | if (!$validate->validVersion($param['version'])) { |
2170 | if (!$validate->validVersion($param['version'])) { |
2171 | return PEAR::raiseError('parsePackageName(): "' . $param['version'] . |
2171 | return PEAR::raiseError('parsePackageName(): "' . $param['version'] . |
2172 | '" is neither a valid version nor a valid state in "' . |
2172 | '" is neither a valid version nor a valid state in "' . |
2173 | $saveparam . '"', 'version/state', null, null, $param); |
2173 | $saveparam . '"', 'version/state', null, null, $param); |
2174 | }
|
2174 | }
|
2175 | }
|
2175 | }
|
2176 | }
|
2176 | }
|
2177 | return $param; |
2177 | return $param; |
2178 | }
|
2178 | }
|
2179 | 2179 | ||
2180 | /**
|
2180 | /**
|
2181 | * @param array
|
2181 | * @param array
|
2182 | * @return string
|
2182 | * @return string
|
2183 | */
|
2183 | */
|
2184 | function parsedPackageNameToString($parsed, $brief = false) |
2184 | function parsedPackageNameToString($parsed, $brief = false) |
2185 | {
|
2185 | {
|
2186 | if (is_string($parsed)) { |
2186 | if (is_string($parsed)) { |
2187 | return $parsed; |
2187 | return $parsed; |
2188 | }
|
2188 | }
|
2189 | if (is_object($parsed)) { |
2189 | if (is_object($parsed)) { |
2190 | $p = $parsed; |
2190 | $p = $parsed; |
2191 | $parsed = array( |
2191 | $parsed = array( |
2192 | 'package' => $p->getPackage(), |
2192 | 'package' => $p->getPackage(), |
2193 | 'channel' => $p->getChannel(), |
2193 | 'channel' => $p->getChannel(), |
2194 | 'version' => $p->getVersion(), |
2194 | 'version' => $p->getVersion(), |
2195 | ); |
2195 | ); |
2196 | }
|
2196 | }
|
2197 | if (isset($parsed['uri'])) { |
2197 | if (isset($parsed['uri'])) { |
2198 | return $parsed['uri']; |
2198 | return $parsed['uri']; |
2199 | }
|
2199 | }
|
2200 | if ($brief) { |
2200 | if ($brief) { |
2201 | if ($channel = $this->channelAlias($parsed['channel'])) { |
2201 | if ($channel = $this->channelAlias($parsed['channel'])) { |
2202 | return $channel . '/' . $parsed['package']; |
2202 | return $channel . '/' . $parsed['package']; |
2203 | }
|
2203 | }
|
2204 | }
|
2204 | }
|
2205 | $upass = ''; |
2205 | $upass = ''; |
2206 | if (isset($parsed['user'])) { |
2206 | if (isset($parsed['user'])) { |
2207 | $upass = $parsed['user']; |
2207 | $upass = $parsed['user']; |
2208 | if (isset($parsed['pass'])) { |
2208 | if (isset($parsed['pass'])) { |
2209 | $upass .= ':' . $parsed['pass']; |
2209 | $upass .= ':' . $parsed['pass']; |
2210 | }
|
2210 | }
|
2211 | $upass = "$upass@"; |
2211 | $upass = "$upass@"; |
2212 | }
|
2212 | }
|
2213 | $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package']; |
2213 | $ret = 'channel://' . $upass . $parsed['channel'] . '/' . $parsed['package']; |
2214 | if (isset($parsed['version']) || isset($parsed['state'])) { |
2214 | if (isset($parsed['version']) || isset($parsed['state'])) { |
2215 | $ver = isset($parsed['version']) ? $parsed['version'] : ''; |
2215 | $ver = isset($parsed['version']) ? $parsed['version'] : ''; |
2216 | $ver .= isset($parsed['state']) ? $parsed['state'] : ''; |
2216 | $ver .= isset($parsed['state']) ? $parsed['state'] : ''; |
2217 | $ret .= '-' . $ver; |
2217 | $ret .= '-' . $ver; |
2218 | }
|
2218 | }
|
2219 | if (isset($parsed['extension'])) { |
2219 | if (isset($parsed['extension'])) { |
2220 | $ret .= '.' . $parsed['extension']; |
2220 | $ret .= '.' . $parsed['extension']; |
2221 | }
|
2221 | }
|
2222 | if (isset($parsed['opts'])) { |
2222 | if (isset($parsed['opts'])) { |
2223 | $ret .= '?'; |
2223 | $ret .= '?'; |
2224 | foreach ($parsed['opts'] as $name => $value) { |
2224 | foreach ($parsed['opts'] as $name => $value) { |
2225 | $parsed['opts'][$name] = "$name=$value"; |
2225 | $parsed['opts'][$name] = "$name=$value"; |
2226 | }
|
2226 | }
|
2227 | $ret .= implode('&', $parsed['opts']); |
2227 | $ret .= implode('&', $parsed['opts']); |
2228 | }
|
2228 | }
|
2229 | if (isset($parsed['group'])) { |
2229 | if (isset($parsed['group'])) { |
2230 | $ret .= '#' . $parsed['group']; |
2230 | $ret .= '#' . $parsed['group']; |
2231 | }
|
2231 | }
|
2232 | return $ret; |
2232 | return $ret; |
2233 | }
|
2233 | }
|
2234 | }
|
2234 | }
|
2235 | 2235 | ||
2236 | ?>
|
2236 | ?>
|
2237 | 2237 |