Редакция 69 | Только различия | Учитывать пробелы | Содержимое файла | Авторство | Последнее изменение | Открыть журнал | RSS
Редакция 69 | Редакция 87 | ||
---|---|---|---|
1 | <?php
|
1 | <?php
|
2 | /**
|
2 | /**
|
3 | * PEAR_Remote
|
3 | * PEAR_Remote
|
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 Greg Beaver <cellog@php.net>
|
16 | * @author Greg Beaver <cellog@php.net>
|
17 | * @copyright 1997-2008 The PHP Group
|
17 | * @copyright 1997-2008 The PHP Group
|
18 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
18 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
19 | * @version CVS: $Id: Remote.php,v 1.80 2008/01/03 20:26:36 cellog Exp $
|
19 | * @version CVS: $Id: Remote.php,v 1.80 2008/01/03 20:26:36 cellog Exp $
|
20 | * @link http://pear.php.net/package/PEAR
|
20 | * @link http://pear.php.net/package/PEAR
|
21 | * @since File available since Release 0.1
|
21 | * @since File available since Release 0.1
|
22 | */
|
22 | */
|
23 | 23 | ||
24 | /**
|
24 | /**
|
25 | * needed for PEAR_Error
|
25 | * needed for PEAR_Error
|
26 | */
|
26 | */
|
27 | require_once 'PEAR.php'; |
27 | require_once 'PEAR.php'; |
28 | require_once 'PEAR/Config.php'; |
28 | require_once 'PEAR/Config.php'; |
29 | 29 | ||
30 | /**
|
30 | /**
|
31 | * This is a class for doing remote operations against the central
|
31 | * This is a class for doing remote operations against the central
|
32 | * PEAR database.
|
32 | * PEAR database.
|
33 | *
|
33 | *
|
34 | * @nodep XML_RPC_Value
|
34 | * @nodep XML_RPC_Value
|
35 | * @nodep XML_RPC_Message
|
35 | * @nodep XML_RPC_Message
|
36 | * @nodep XML_RPC_Client
|
36 | * @nodep XML_RPC_Client
|
37 | * @category pear
|
37 | * @category pear
|
38 | * @package PEAR
|
38 | * @package PEAR
|
39 | * @author Stig Bakken <ssb@php.net>
|
39 | * @author Stig Bakken <ssb@php.net>
|
40 | * @author Greg Beaver <cellog@php.net>
|
40 | * @author Greg Beaver <cellog@php.net>
|
41 | * @copyright 1997-2008 The PHP Group
|
41 | * @copyright 1997-2008 The PHP Group
|
42 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
42 | * @license http://www.php.net/license/3_0.txt PHP License 3.0
|
43 | * @version Release: 1.7.2
|
43 | * @version Release: 1.7.2
|
44 | * @link http://pear.php.net/package/PEAR
|
44 | * @link http://pear.php.net/package/PEAR
|
45 | * @since Class available since Release 0.1
|
45 | * @since Class available since Release 0.1
|
46 | */
|
46 | */
|
47 | class PEAR_Remote extends PEAR |
47 | class PEAR_Remote extends PEAR |
48 | {
|
48 | {
|
49 | // {{{ properties
|
49 | // {{{ properties
|
50 | 50 | ||
51 | var $config = null; |
51 | var $config = null; |
52 | var $cache = null; |
52 | var $cache = null; |
53 | /**
|
53 | /**
|
54 | * @var PEAR_Registry
|
54 | * @var PEAR_Registry
|
55 | * @access private
|
55 | * @access private
|
56 | */
|
56 | */
|
57 | var $_registry; |
57 | var $_registry; |
58 | 58 | ||
59 | // }}}
|
59 | // }}}
|
60 | 60 | ||
61 | // {{{ PEAR_Remote(config_object)
|
61 | // {{{ PEAR_Remote(config_object)
|
62 | 62 | ||
63 | function PEAR_Remote(&$config) |
63 | function PEAR_Remote(&$config) |
64 | {
|
64 | {
|
65 | $this->PEAR(); |
65 | $this->PEAR(); |
66 | $this->config = &$config; |
66 | $this->config = &$config; |
67 | $this->_registry = &$this->config->getRegistry(); |
67 | $this->_registry = &$this->config->getRegistry(); |
68 | }
|
68 | }
|
69 | 69 | ||
70 | // }}}
|
70 | // }}}
|
71 | // {{{ setRegistry()
|
71 | // {{{ setRegistry()
|
72 | 72 | ||
73 | function setRegistry(&$reg) |
73 | function setRegistry(&$reg) |
74 | {
|
74 | {
|
75 | $this->_registry = &$reg; |
75 | $this->_registry = &$reg; |
76 | }
|
76 | }
|
77 | // }}}
|
77 | // }}}
|
78 | // {{{ getCache()
|
78 | // {{{ getCache()
|
79 | 79 | ||
80 | 80 | ||
81 | function getCache($args) |
81 | function getCache($args) |
82 | {
|
82 | {
|
83 | $id = md5(serialize($args)); |
83 | $id = md5(serialize($args)); |
84 | $cachedir = $this->config->get('cache_dir'); |
84 | $cachedir = $this->config->get('cache_dir'); |
85 | $filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id; |
85 | $filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id; |
86 | if (!file_exists($filename)) { |
86 | if (!file_exists($filename)) { |
87 | return null; |
87 | return null; |
88 | }
|
88 | }
|
89 | 89 | ||
90 | $fp = fopen($filename, 'rb'); |
90 | $fp = fopen($filename, 'rb'); |
91 | if (!$fp) { |
91 | if (!$fp) { |
92 | return null; |
92 | return null; |
93 | }
|
93 | }
|
94 | fclose($fp); |
94 | fclose($fp); |
95 | $content = file_get_contents($filename); |
95 | $content = file_get_contents($filename); |
96 | $result = array( |
96 | $result = array( |
97 | 'age' => time() - filemtime($filename), |
97 | 'age' => time() - filemtime($filename), |
98 | 'lastChange' => filemtime($filename), |
98 | 'lastChange' => filemtime($filename), |
99 | 'content' => unserialize($content), |
99 | 'content' => unserialize($content), |
100 | ); |
100 | ); |
101 | return $result; |
101 | return $result; |
102 | }
|
102 | }
|
103 | 103 | ||
104 | // }}}
|
104 | // }}}
|
105 | 105 | ||
106 | // {{{ saveCache()
|
106 | // {{{ saveCache()
|
107 | 107 | ||
108 | function saveCache($args, $data) |
108 | function saveCache($args, $data) |
109 | {
|
109 | {
|
110 | $id = md5(serialize($args)); |
110 | $id = md5(serialize($args)); |
111 | $cachedir = $this->config->get('cache_dir'); |
111 | $cachedir = $this->config->get('cache_dir'); |
112 | if (!file_exists($cachedir)) { |
112 | if (!file_exists($cachedir)) { |
113 | System::mkdir(array('-p', $cachedir)); |
113 | System::mkdir(array('-p', $cachedir)); |
114 | }
|
114 | }
|
115 | $filename = $cachedir.'/xmlrpc_cache_'.$id; |
115 | $filename = $cachedir.'/xmlrpc_cache_'.$id; |
116 | 116 | ||
117 | $fp = @fopen($filename, "wb"); |
117 | $fp = @fopen($filename, "wb"); |
118 | if ($fp) { |
118 | if ($fp) { |
119 | fwrite($fp, serialize($data)); |
119 | fwrite($fp, serialize($data)); |
120 | fclose($fp); |
120 | fclose($fp); |
121 | }
|
121 | }
|
122 | }
|
122 | }
|
123 | 123 | ||
124 | // }}}
|
124 | // }}}
|
125 | 125 | ||
126 | // {{{ clearCache()
|
126 | // {{{ clearCache()
|
127 | 127 | ||
128 | function clearCache($method, $args) |
128 | function clearCache($method, $args) |
129 | {
|
129 | {
|
130 | array_unshift($args, $method); |
130 | array_unshift($args, $method); |
131 | array_unshift($args, $this->config->get('default_channel')); // cache by channel |
131 | array_unshift($args, $this->config->get('default_channel')); // cache by channel |
132 | $id = md5(serialize($args)); |
132 | $id = md5(serialize($args)); |
133 | $cachedir = $this->config->get('cache_dir'); |
133 | $cachedir = $this->config->get('cache_dir'); |
134 | $filename = $cachedir.'/xmlrpc_cache_'.$id; |
134 | $filename = $cachedir.'/xmlrpc_cache_'.$id; |
135 | if (file_exists($filename)) { |
135 | if (file_exists($filename)) { |
136 | @unlink($filename); |
136 | @unlink($filename); |
137 | }
|
137 | }
|
138 | }
|
138 | }
|
139 | 139 | ||
140 | // }}}
|
140 | // }}}
|
141 | // {{{ call(method, [args...])
|
141 | // {{{ call(method, [args...])
|
142 | 142 | ||
143 | function call($method) |
143 | function call($method) |
144 | {
|
144 | {
|
145 | $_args = $args = func_get_args(); |
145 | $_args = $args = func_get_args(); |
146 | 146 | ||
147 | $server_channel = $this->config->get('default_channel'); |
147 | $server_channel = $this->config->get('default_channel'); |
148 | $channel = $this->_registry->getChannel($server_channel); |
148 | $channel = $this->_registry->getChannel($server_channel); |
149 | if (!PEAR::isError($channel)) { |
149 | if (!PEAR::isError($channel)) { |
150 | $mirror = $this->config->get('preferred_mirror'); |
150 | $mirror = $this->config->get('preferred_mirror'); |
151 | if ($channel->getMirror($mirror)) { |
151 | if ($channel->getMirror($mirror)) { |
152 | if ($channel->supports('xmlrpc', $method, $mirror)) { |
152 | if ($channel->supports('xmlrpc', $method, $mirror)) { |
153 | $server_channel = $server_host = $mirror; // use the preferred mirror |
153 | $server_channel = $server_host = $mirror; // use the preferred mirror |
154 | $server_port = $channel->getPort($mirror); |
154 | $server_port = $channel->getPort($mirror); |
155 | } elseif (!$channel->supports('xmlrpc', $method)) { |
155 | } elseif (!$channel->supports('xmlrpc', $method)) { |
156 | return $this->raiseError("Channel $server_channel does not " . |
156 | return $this->raiseError("Channel $server_channel does not " . |
157 | "support xml-rpc method $method"); |
157 | "support xml-rpc method $method"); |
158 | }
|
158 | }
|
159 | }
|
159 | }
|
160 | if (!isset($server_host)) { |
160 | if (!isset($server_host)) { |
161 | if (!$channel->supports('xmlrpc', $method)) { |
161 | if (!$channel->supports('xmlrpc', $method)) { |
162 | return $this->raiseError("Channel $server_channel does not support " . |
162 | return $this->raiseError("Channel $server_channel does not support " . |
163 | "xml-rpc method $method"); |
163 | "xml-rpc method $method"); |
164 | } else { |
164 | } else { |
165 | $server_host = $server_channel; |
165 | $server_host = $server_channel; |
166 | $server_port = $channel->getPort(); |
166 | $server_port = $channel->getPort(); |
167 | }
|
167 | }
|
168 | }
|
168 | }
|
169 | } else { |
169 | } else { |
170 | return $this->raiseError("Unknown channel '$server_channel'"); |
170 | return $this->raiseError("Unknown channel '$server_channel'"); |
171 | }
|
171 | }
|
172 | 172 | ||
173 | array_unshift($_args, $server_channel); // cache by channel |
173 | array_unshift($_args, $server_channel); // cache by channel |
174 | $this->cache = $this->getCache($_args); |
174 | $this->cache = $this->getCache($_args); |
175 | $cachettl = $this->config->get('cache_ttl'); |
175 | $cachettl = $this->config->get('cache_ttl'); |
176 | // If cache is newer than $cachettl seconds, we use the cache!
|
176 | // If cache is newer than $cachettl seconds, we use the cache!
|
177 | if ($this->cache !== null && $this->cache['age'] < $cachettl) { |
177 | if ($this->cache !== null && $this->cache['age'] < $cachettl) { |
178 | return $this->cache['content']; |
178 | return $this->cache['content']; |
179 | }
|
179 | }
|
180 | $fp = false; |
180 | $fp = false; |
181 | if (extension_loaded("xmlrpc")) { |
181 | if (extension_loaded("xmlrpc")) { |
182 | $result = call_user_func_array(array(&$this, 'call_epi'), $args); |
182 | $result = call_user_func_array(array(&$this, 'call_epi'), $args); |
183 | if (!PEAR::isError($result)) { |
183 | if (!PEAR::isError($result)) { |
184 | $this->saveCache($_args, $result); |
184 | $this->saveCache($_args, $result); |
185 | }
|
185 | }
|
186 | return $result; |
186 | return $result; |
187 | } elseif (!($fp = fopen('XML/RPC.php', 'r', true))) { |
187 | } elseif (!($fp = fopen('XML/RPC.php', 'r', true))) { |
188 | return $this->raiseError("For this remote PEAR operation you need to load the xmlrpc extension or install XML_RPC"); |
188 | return $this->raiseError("For this remote PEAR operation you need to load the xmlrpc extension or install XML_RPC"); |
189 | }
|
189 | }
|
190 | include_once 'XML/RPC.php'; |
190 | include_once 'XML/RPC.php'; |
191 | if ($fp) { |
191 | if ($fp) { |
192 | fclose($fp); |
192 | fclose($fp); |
193 | }
|
193 | }
|
194 | 194 | ||
195 | array_shift($args); |
195 | array_shift($args); |
196 | $username = $this->config->get('username'); |
196 | $username = $this->config->get('username'); |
197 | $password = $this->config->get('password'); |
197 | $password = $this->config->get('password'); |
198 | $eargs = array(); |
198 | $eargs = array(); |
199 | foreach($args as $arg) { |
199 | foreach($args as $arg) { |
200 | $eargs[] = $this->_encode($arg); |
200 | $eargs[] = $this->_encode($arg); |
201 | }
|
201 | }
|
202 | $f = new XML_RPC_Message($method, $eargs); |
202 | $f = new XML_RPC_Message($method, $eargs); |
203 | if ($this->cache !== null) { |
203 | if ($this->cache !== null) { |
204 | $maxAge = '?maxAge='.$this->cache['lastChange']; |
204 | $maxAge = '?maxAge='.$this->cache['lastChange']; |
205 | } else { |
205 | } else { |
206 | $maxAge = ''; |
206 | $maxAge = ''; |
207 | }
|
207 | }
|
208 | $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; |
208 | $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; |
209 | if ($proxy = parse_url($this->config->get('http_proxy'))) { |
209 | if ($proxy = parse_url($this->config->get('http_proxy'))) { |
210 | $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; |
210 | $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; |
211 | if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { |
211 | if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { |
212 | $proxy_host = 'https://' . $proxy_host; |
212 | $proxy_host = 'https://' . $proxy_host; |
213 | }
|
213 | }
|
214 | $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; |
214 | $proxy_port = isset($proxy['port']) ? $proxy['port'] : 8080; |
215 | $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; |
215 | $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; |
216 | $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; |
216 | $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; |
217 | }
|
217 | }
|
218 | $shost = $server_host; |
218 | $shost = $server_host; |
219 | if ($channel->getSSL()) { |
219 | if ($channel->getSSL()) { |
220 | $shost = "https://$shost"; |
220 | $shost = "https://$shost"; |
221 | }
|
221 | }
|
222 | $c = new XML_RPC_Client('/' . $channel->getPath('xmlrpc') |
222 | $c = new XML_RPC_Client('/' . $channel->getPath('xmlrpc') |
223 | . $maxAge, $shost, $server_port, $proxy_host, $proxy_port, |
223 | . $maxAge, $shost, $server_port, $proxy_host, $proxy_port, |
224 | $proxy_user, $proxy_pass); |
224 | $proxy_user, $proxy_pass); |
225 | if ($username && $password) { |
225 | if ($username && $password) { |
226 | $c->setCredentials($username, $password); |
226 | $c->setCredentials($username, $password); |
227 | }
|
227 | }
|
228 | if ($this->config->get('verbose') >= 3) { |
228 | if ($this->config->get('verbose') >= 3) { |
229 | $c->setDebug(1); |
229 | $c->setDebug(1); |
230 | }
|
230 | }
|
231 | $r = $c->send($f); |
231 | $r = $c->send($f); |
232 | if (!$r) { |
232 | if (!$r) { |
233 | return $this->raiseError("XML_RPC send failed"); |
233 | return $this->raiseError("XML_RPC send failed"); |
234 | }
|
234 | }
|
235 | $v = $r->value(); |
235 | $v = $r->value(); |
236 | if ($e = $r->faultCode()) { |
236 | if ($e = $r->faultCode()) { |
237 | if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) { |
237 | if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) { |
238 | return $this->cache['content']; |
238 | return $this->cache['content']; |
239 | }
|
239 | }
|
240 | return $this->raiseError($r->faultString(), $e); |
240 | return $this->raiseError($r->faultString(), $e); |
241 | }
|
241 | }
|
242 | 242 | ||
243 | $result = XML_RPC_decode($v); |
243 | $result = XML_RPC_decode($v); |
244 | $this->saveCache($_args, $result); |
244 | $this->saveCache($_args, $result); |
245 | return $result; |
245 | return $result; |
246 | }
|
246 | }
|
247 | 247 | ||
248 | // }}}
|
248 | // }}}
|
249 | 249 | ||
250 | // {{{ call_epi(method, [args...])
|
250 | // {{{ call_epi(method, [args...])
|
251 | 251 | ||
252 | function call_epi($method) |
252 | function call_epi($method) |
253 | {
|
253 | {
|
254 | if (!extension_loaded("xmlrpc")) { |
254 | if (!extension_loaded("xmlrpc")) { |
255 | return $this->raiseError("xmlrpc extension is not loaded"); |
255 | return $this->raiseError("xmlrpc extension is not loaded"); |
256 | }
|
256 | }
|
257 | $server_channel = $this->config->get('default_channel'); |
257 | $server_channel = $this->config->get('default_channel'); |
258 | $channel = $this->_registry->getChannel($server_channel); |
258 | $channel = $this->_registry->getChannel($server_channel); |
259 | if (!PEAR::isError($channel)) { |
259 | if (!PEAR::isError($channel)) { |
260 | $mirror = $this->config->get('preferred_mirror'); |
260 | $mirror = $this->config->get('preferred_mirror'); |
261 | if ($channel->getMirror($mirror)) { |
261 | if ($channel->getMirror($mirror)) { |
262 | if ($channel->supports('xmlrpc', $method, $mirror)) { |
262 | if ($channel->supports('xmlrpc', $method, $mirror)) { |
263 | $server_channel = $server_host = $mirror; // use the preferred mirror |
263 | $server_channel = $server_host = $mirror; // use the preferred mirror |
264 | $server_port = $channel->getPort($mirror); |
264 | $server_port = $channel->getPort($mirror); |
265 | } elseif (!$channel->supports('xmlrpc', $method)) { |
265 | } elseif (!$channel->supports('xmlrpc', $method)) { |
266 | return $this->raiseError("Channel $server_channel does not " . |
266 | return $this->raiseError("Channel $server_channel does not " . |
267 | "support xml-rpc method $method"); |
267 | "support xml-rpc method $method"); |
268 | }
|
268 | }
|
269 | }
|
269 | }
|
270 | if (!isset($server_host)) { |
270 | if (!isset($server_host)) { |
271 | if (!$channel->supports('xmlrpc', $method)) { |
271 | if (!$channel->supports('xmlrpc', $method)) { |
272 | return $this->raiseError("Channel $server_channel does not support " . |
272 | return $this->raiseError("Channel $server_channel does not support " . |
273 | "xml-rpc method $method"); |
273 | "xml-rpc method $method"); |
274 | } else { |
274 | } else { |
275 | $server_host = $server_channel; |
275 | $server_host = $server_channel; |
276 | $server_port = $channel->getPort(); |
276 | $server_port = $channel->getPort(); |
277 | }
|
277 | }
|
278 | }
|
278 | }
|
279 | } else { |
279 | } else { |
280 | return $this->raiseError("Unknown channel '$server_channel'"); |
280 | return $this->raiseError("Unknown channel '$server_channel'"); |
281 | }
|
281 | }
|
282 | $params = func_get_args(); |
282 | $params = func_get_args(); |
283 | array_shift($params); |
283 | array_shift($params); |
284 | $method = str_replace("_", ".", $method); |
284 | $method = str_replace("_", ".", $method); |
285 | $request = xmlrpc_encode_request($method, $params); |
285 | $request = xmlrpc_encode_request($method, $params); |
286 | if ($http_proxy = $this->config->get('http_proxy')) { |
286 | if ($http_proxy = $this->config->get('http_proxy')) { |
287 | $proxy = parse_url($http_proxy); |
287 | $proxy = parse_url($http_proxy); |
288 | $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; |
288 | $proxy_host = $proxy_port = $proxy_user = $proxy_pass = ''; |
289 | $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; |
289 | $proxy_host = isset($proxy['host']) ? $proxy['host'] : null; |
290 | if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { |
290 | if (isset($proxy['scheme']) && $proxy['scheme'] == 'https') { |
291 | $proxy_host = 'https://' . $proxy_host; |
291 | $proxy_host = 'https://' . $proxy_host; |
292 | }
|
292 | }
|
293 | $proxy_port = isset($proxy['port']) ? $proxy['port'] : null; |
293 | $proxy_port = isset($proxy['port']) ? $proxy['port'] : null; |
294 | $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; |
294 | $proxy_user = isset($proxy['user']) ? urldecode($proxy['user']) : null; |
295 | $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; |
295 | $proxy_pass = isset($proxy['pass']) ? urldecode($proxy['pass']) : null; |
296 | $fp = @fsockopen($proxy_host, $proxy_port); |
296 | $fp = @fsockopen($proxy_host, $proxy_port); |
297 | $use_proxy = true; |
297 | $use_proxy = true; |
298 | if ($channel->getSSL()) { |
298 | if ($channel->getSSL()) { |
299 | $server_host = "https://$server_host"; |
299 | $server_host = "https://$server_host"; |
300 | }
|
300 | }
|
301 | } else { |
301 | } else { |
302 | $use_proxy = false; |
302 | $use_proxy = false; |
303 | $ssl = $channel->getSSL(); |
303 | $ssl = $channel->getSSL(); |
304 | $fp = @fsockopen(($ssl ? 'ssl://' : '') . $server_host, $server_port); |
304 | $fp = @fsockopen(($ssl ? 'ssl://' : '') . $server_host, $server_port); |
305 | if (!$fp) { |
305 | if (!$fp) { |
306 | $server_host = "$ssl$server_host"; // for error-reporting |
306 | $server_host = "$ssl$server_host"; // for error-reporting |
307 | }
|
307 | }
|
308 | }
|
308 | }
|
309 | if (!$fp && $http_proxy) { |
309 | if (!$fp && $http_proxy) { |
310 | return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed"); |
310 | return $this->raiseError("PEAR_Remote::call: fsockopen(`$proxy_host', $proxy_port) failed"); |
311 | } elseif (!$fp) { |
311 | } elseif (!$fp) { |
312 | return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed"); |
312 | return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed"); |
313 | }
|
313 | }
|
314 | $len = strlen($request); |
314 | $len = strlen($request); |
315 | $req_headers = "Host: $server_host:$server_port\r\n" . |
315 | $req_headers = "Host: $server_host:$server_port\r\n" . |
316 | "Content-type: text/xml\r\n" . |
316 | "Content-type: text/xml\r\n" . |
317 | "Content-length: $len\r\n"; |
317 | "Content-length: $len\r\n"; |
318 | $username = $this->config->get('username'); |
318 | $username = $this->config->get('username'); |
319 | $password = $this->config->get('password'); |
319 | $password = $this->config->get('password'); |
320 | if ($username && $password) { |
320 | if ($username && $password) { |
321 | $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n"; |
321 | $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n"; |
322 | $tmp = base64_encode("$username:$password"); |
322 | $tmp = base64_encode("$username:$password"); |
323 | $req_headers .= "Authorization: Basic $tmp\r\n"; |
323 | $req_headers .= "Authorization: Basic $tmp\r\n"; |
324 | }
|
324 | }
|
325 | if ($this->cache !== null) { |
325 | if ($this->cache !== null) { |
326 | $maxAge = '?maxAge='.$this->cache['lastChange']; |
326 | $maxAge = '?maxAge='.$this->cache['lastChange']; |
327 | } else { |
327 | } else { |
328 | $maxAge = ''; |
328 | $maxAge = ''; |
329 | }
|
329 | }
|
330 | 330 | ||
331 | if ($use_proxy && $proxy_host != '' && $proxy_user != '') { |
331 | if ($use_proxy && $proxy_host != '' && $proxy_user != '') { |
332 | $req_headers .= 'Proxy-Authorization: Basic ' |
332 | $req_headers .= 'Proxy-Authorization: Basic ' |
333 | .base64_encode($proxy_user.':'.$proxy_pass) |
333 | .base64_encode($proxy_user.':'.$proxy_pass) |
334 | ."\r\n"; |
334 | ."\r\n"; |
335 | }
|
335 | }
|
336 | 336 | ||
337 | if ($this->config->get('verbose') > 3) { |
337 | if ($this->config->get('verbose') > 3) { |
338 | print "XMLRPC REQUEST HEADERS:\n"; |
338 | print "XMLRPC REQUEST HEADERS:\n"; |
339 | var_dump($req_headers); |
339 | var_dump($req_headers); |
340 | print "XMLRPC REQUEST BODY:\n"; |
340 | print "XMLRPC REQUEST BODY:\n"; |
341 | var_dump($request); |
341 | var_dump($request); |
342 | }
|
342 | }
|
343 | 343 | ||
344 | if ($use_proxy && $proxy_host != '') { |
344 | if ($use_proxy && $proxy_host != '') { |
345 | $post_string = "POST http://".$server_host; |
345 | $post_string = "POST http://".$server_host; |
346 | if ($proxy_port > '') { |
346 | if ($proxy_port > '') { |
347 | $post_string .= ':'.$server_port; |
347 | $post_string .= ':'.$server_port; |
348 | }
|
348 | }
|
349 | } else { |
349 | } else { |
350 | $post_string = "POST "; |
350 | $post_string = "POST "; |
351 | }
|
351 | }
|
352 | 352 | ||
353 | $path = '/' . $channel->getPath('xmlrpc'); |
353 | $path = '/' . $channel->getPath('xmlrpc'); |
354 | fwrite($fp, ($post_string . $path . "$maxAge HTTP/1.0\r\n$req_headers\r\n$request")); |
354 | fwrite($fp, ($post_string . $path . "$maxAge HTTP/1.0\r\n$req_headers\r\n$request")); |
355 | $response = ''; |
355 | $response = ''; |
356 | $line1 = fgets($fp, 2048); |
356 | $line1 = fgets($fp, 2048); |
357 | if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) { |
357 | if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) { |
358 | return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server"); |
358 | return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server"); |
359 | }
|
359 | }
|
360 | switch ($matches[1]) { |
360 | switch ($matches[1]) { |
361 | case "200": // OK |
361 | case "200": // OK |
362 | break; |
362 | break; |
363 | case "304": // Not Modified |
363 | case "304": // Not Modified |
364 | return $this->cache['content']; |
364 | return $this->cache['content']; |
365 | case "401": // Unauthorized |
365 | case "401": // Unauthorized |
366 | if ($username && $password) { |
366 | if ($username && $password) { |
367 | return $this->raiseError("PEAR_Remote ($server_host:$server_port) " . |
367 | return $this->raiseError("PEAR_Remote ($server_host:$server_port) " . |
368 | ": authorization failed", 401); |
368 | ": authorization failed", 401); |
369 | } else { |
369 | } else { |
370 | return $this->raiseError("PEAR_Remote ($server_host:$server_port) " . |
370 | return $this->raiseError("PEAR_Remote ($server_host:$server_port) " . |
371 | ": authorization required, please log in first", 401); |
371 | ": authorization required, please log in first", 401); |
372 | }
|
372 | }
|
373 | default: |
373 | default: |
374 | return $this->raiseError("PEAR_Remote ($server_host:$server_port) : " . |
374 | return $this->raiseError("PEAR_Remote ($server_host:$server_port) : " . |
375 | "unexpected HTTP response", (int)$matches[1], null, null, |
375 | "unexpected HTTP response", (int)$matches[1], null, null, |
376 | "$matches[1] $matches[2]"); |
376 | "$matches[1] $matches[2]"); |
377 | }
|
377 | }
|
378 | while (trim(fgets($fp, 2048)) != ''); // skip rest of headers |
378 | while (trim(fgets($fp, 2048)) != ''); // skip rest of headers |
379 | while ($chunk = fread($fp, 10240)) { |
379 | while ($chunk = fread($fp, 10240)) { |
380 | $response .= $chunk; |
380 | $response .= $chunk; |
381 | }
|
381 | }
|
382 | fclose($fp); |
382 | fclose($fp); |
383 | if ($this->config->get('verbose') > 3) { |
383 | if ($this->config->get('verbose') > 3) { |
384 | print "XMLRPC RESPONSE:\n"; |
384 | print "XMLRPC RESPONSE:\n"; |
385 | var_dump($response); |
385 | var_dump($response); |
386 | }
|
386 | }
|
387 | $ret = xmlrpc_decode($response); |
387 | $ret = xmlrpc_decode($response); |
388 | if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) { |
388 | if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) { |
389 | if ($ret['__PEAR_TYPE__'] == 'error') { |
389 | if ($ret['__PEAR_TYPE__'] == 'error') { |
390 | if (isset($ret['__PEAR_CLASS__'])) { |
390 | if (isset($ret['__PEAR_CLASS__'])) { |
391 | $class = $ret['__PEAR_CLASS__']; |
391 | $class = $ret['__PEAR_CLASS__']; |
392 | } else { |
392 | } else { |
393 | $class = "PEAR_Error"; |
393 | $class = "PEAR_Error"; |
394 | }
|
394 | }
|
395 | if ($ret['code'] === '') $ret['code'] = null; |
395 | if ($ret['code'] === '') $ret['code'] = null; |
396 | if ($ret['message'] === '') $ret['message'] = null; |
396 | if ($ret['message'] === '') $ret['message'] = null; |
397 | if ($ret['userinfo'] === '') $ret['userinfo'] = null; |
397 | if ($ret['userinfo'] === '') $ret['userinfo'] = null; |
398 | if (strtolower($class) == 'db_error') { |
398 | if (strtolower($class) == 'db_error') { |
399 | $ret = $this->raiseError(PEAR::errorMessage($ret['code']), |
399 | $ret = $this->raiseError(PEAR::errorMessage($ret['code']), |
400 | $ret['code'], null, null, |
400 | $ret['code'], null, null, |
401 | $ret['userinfo']); |
401 | $ret['userinfo']); |
402 | } else { |
402 | } else { |
403 | $ret = $this->raiseError($ret['message'], $ret['code'], |
403 | $ret = $this->raiseError($ret['message'], $ret['code'], |
404 | null, null, $ret['userinfo']); |
404 | null, null, $ret['userinfo']); |
405 | }
|
405 | }
|
406 | }
|
406 | }
|
407 | } elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0]) |
407 | } elseif (is_array($ret) && sizeof($ret) == 1 && isset($ret[0]) |
408 | && is_array($ret[0]) && |
408 | && is_array($ret[0]) && |
409 | !empty($ret[0]['faultString']) && |
409 | !empty($ret[0]['faultString']) && |
410 | !empty($ret[0]['faultCode'])) { |
410 | !empty($ret[0]['faultCode'])) { |
411 | extract($ret[0]); |
411 | extract($ret[0]); |
412 | $faultString = "XML-RPC Server Fault: " . |
412 | $faultString = "XML-RPC Server Fault: " . |
413 | str_replace("\n", " ", $faultString); |
413 | str_replace("\n", " ", $faultString); |
414 | return $this->raiseError($faultString, $faultCode); |
414 | return $this->raiseError($faultString, $faultCode); |
415 | } elseif (is_array($ret) && sizeof($ret) == 2 && !empty($ret['faultString']) && |
415 | } elseif (is_array($ret) && sizeof($ret) == 2 && !empty($ret['faultString']) && |
416 | !empty($ret['faultCode'])) { |
416 | !empty($ret['faultCode'])) { |
417 | extract($ret); |
417 | extract($ret); |
418 | $faultString = "XML-RPC Server Fault: " . |
418 | $faultString = "XML-RPC Server Fault: " . |
419 | str_replace("\n", " ", $faultString); |
419 | str_replace("\n", " ", $faultString); |
420 | return $this->raiseError($faultString, $faultCode); |
420 | return $this->raiseError($faultString, $faultCode); |
421 | }
|
421 | }
|
422 | return $ret; |
422 | return $ret; |
423 | }
|
423 | }
|
424 | 424 | ||
425 | // }}}
|
425 | // }}}
|
426 | 426 | ||
427 | // {{{ _encode
|
427 | // {{{ _encode
|
428 | 428 | ||
429 | // a slightly extended version of XML_RPC_encode
|
429 | // a slightly extended version of XML_RPC_encode
|
430 | function _encode($php_val) |
430 | function _encode($php_val) |
431 | {
|
431 | {
|
432 | global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double; |
432 | global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double; |
433 | global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct; |
433 | global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct; |
434 | 434 | ||
435 | $type = gettype($php_val); |
435 | $type = gettype($php_val); |
436 | $xmlrpcval = new XML_RPC_Value; |
436 | $xmlrpcval = new XML_RPC_Value; |
437 | 437 | ||
438 | switch($type) { |
438 | switch($type) { |
439 | case "array": |
439 | case "array": |
440 | reset($php_val); |
440 | reset($php_val); |
441 | $firstkey = key($php_val); |
441 | $firstkey = key($php_val); |
442 | end($php_val); |
442 | end($php_val); |
443 | $lastkey = key($php_val); |
443 | $lastkey = key($php_val); |
444 | reset($php_val); |
444 | reset($php_val); |
445 | if ($firstkey === 0 && is_int($lastkey) && |
445 | if ($firstkey === 0 && is_int($lastkey) && |
446 | ($lastkey + 1) == count($php_val)) { |
446 | ($lastkey + 1) == count($php_val)) { |
447 | $is_continuous = true; |
447 | $is_continuous = true; |
448 | reset($php_val); |
448 | reset($php_val); |
449 | $size = count($php_val); |
449 | $size = count($php_val); |
450 | for ($expect = 0; $expect < $size; $expect++, next($php_val)) { |
450 | for ($expect = 0; $expect < $size; $expect++, next($php_val)) { |
451 | if (key($php_val) !== $expect) { |
451 | if (key($php_val) !== $expect) { |
452 | $is_continuous = false; |
452 | $is_continuous = false; |
453 | break; |
453 | break; |
454 | }
|
454 | }
|
455 | }
|
455 | }
|
456 | if ($is_continuous) { |
456 | if ($is_continuous) { |
457 | reset($php_val); |
457 | reset($php_val); |
458 | $arr = array(); |
458 | $arr = array(); |
459 | while (list($k, $v) = each($php_val)) { |
459 | while (list($k, $v) = each($php_val)) { |
460 | $arr[$k] = $this->_encode($v); |
460 | $arr[$k] = $this->_encode($v); |
461 | }
|
461 | }
|
462 | $xmlrpcval->addArray($arr); |
462 | $xmlrpcval->addArray($arr); |
463 | break; |
463 | break; |
464 | }
|
464 | }
|
465 | }
|
465 | }
|
466 | // fall though if not numerical and continuous
|
466 | // fall though if not numerical and continuous
|
467 | case "object": |
467 | case "object": |
468 | $arr = array(); |
468 | $arr = array(); |
469 | while (list($k, $v) = each($php_val)) { |
469 | while (list($k, $v) = each($php_val)) { |
470 | $arr[$k] = $this->_encode($v); |
470 | $arr[$k] = $this->_encode($v); |
471 | }
|
471 | }
|
472 | $xmlrpcval->addStruct($arr); |
472 | $xmlrpcval->addStruct($arr); |
473 | break; |
473 | break; |
474 | case "integer": |
474 | case "integer": |
475 | $xmlrpcval->addScalar($php_val, $XML_RPC_Int); |
475 | $xmlrpcval->addScalar($php_val, $XML_RPC_Int); |
476 | break; |
476 | break; |
477 | case "double": |
477 | case "double": |
478 | $xmlrpcval->addScalar($php_val, $XML_RPC_Double); |
478 | $xmlrpcval->addScalar($php_val, $XML_RPC_Double); |
479 | break; |
479 | break; |
480 | case "string": |
480 | case "string": |
481 | case "NULL": |
481 | case "NULL": |
482 | $xmlrpcval->addScalar($php_val, $XML_RPC_String); |
482 | $xmlrpcval->addScalar($php_val, $XML_RPC_String); |
483 | break; |
483 | break; |
484 | case "boolean": |
484 | case "boolean": |
485 | $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean); |
485 | $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean); |
486 | break; |
486 | break; |
487 | case "unknown type": |
487 | case "unknown type": |
488 | default: |
488 | default: |
489 | return null; |
489 | return null; |
490 | }
|
490 | }
|
491 | return $xmlrpcval; |
491 | return $xmlrpcval; |
492 | }
|
492 | }
|
493 | 493 | ||
494 | // }}}
|
494 | // }}}
|
495 | 495 | ||
496 | }
|
496 | }
|
497 | 497 | ||
498 | ?>
|
498 | ?>
|
499 | 499 |