PageRenderTime 26ms CodeModel.GetById 11ms RepoModel.GetById 0ms app.codeStats 0ms

/gulliver/thirdparty/pear/PEAR/Remote.php

https://bitbucket.org/ferOnti/processmaker
PHP | 367 lines | 305 code | 24 blank | 38 comment | 31 complexity | 715da0e6748179e1385f1f02732ebf45 MD5 | raw file
  1. <?php
  2. //
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4 |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license, |
  9. // | that is bundled with this package in the file LICENSE, and is |
  10. // | available at through the world-wide-web at |
  11. // | http://www.php.net/license/2_02.txt. |
  12. // | If you did not receive a copy of the PHP license and are unable to |
  13. // | obtain it through the world-wide-web, please send a note to |
  14. // | license@php.net so we can mail you a copy immediately. |
  15. // +----------------------------------------------------------------------+
  16. // | Author: Stig Bakken <ssb@php.net> |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Remote.php,v 1.39 2003/03/18 12:06:06 ssb Exp $
  20. require_once 'PEAR.php';
  21. require_once 'PEAR/Config.php';
  22. /**
  23. * This is a class for doing remote operations against the central
  24. * PEAR database.
  25. *
  26. * @nodep XML_RPC_Value
  27. * @nodep XML_RPC_Message
  28. * @nodep XML_RPC_Client
  29. */
  30. class PEAR_Remote extends PEAR
  31. {
  32. // {{{ properties
  33. var $config = null;
  34. var $cache = null;
  35. // }}}
  36. // {{{ PEAR_Remote(config_object)
  37. function PEAR_Remote(&$config)
  38. {
  39. $this->PEAR();
  40. $this->config = &$config;
  41. }
  42. // }}}
  43. // {{{ getCache()
  44. function getCache($args)
  45. {
  46. $id = md5(serialize($args));
  47. $cachedir = $this->config->get('cache_dir');
  48. if (!file_exists($cachedir)) {
  49. System::mkdir('-p '.$cachedir);
  50. }
  51. $filename = $cachedir . DIRECTORY_SEPARATOR . 'xmlrpc_cache_' . $id;
  52. if (!file_exists($filename)) {
  53. return null;
  54. };
  55. $fp = fopen($filename, "rb");
  56. if ($fp === null) {
  57. return null;
  58. }
  59. $content = fread($fp, filesize($filename));
  60. fclose($fp);
  61. $result = array(
  62. 'age' => time() - filemtime($filename),
  63. 'lastChange' => filemtime($filename),
  64. 'content' => unserialize($content),
  65. );
  66. return $result;
  67. }
  68. // }}}
  69. // {{{ saveCache()
  70. function saveCache($args, $data)
  71. {
  72. $id = md5(serialize($args));
  73. $cachedir = $this->config->get('cache_dir');
  74. if (!file_exists($cachedir)) {
  75. System::mkdir('-p '.$cachedir);
  76. }
  77. $filename = $cachedir.'/xmlrpc_cache_'.$id;
  78. $fp = @fopen($filename, "wb");
  79. if ($fp !== null) {
  80. fwrite($fp, serialize($data));
  81. fclose($fp);
  82. };
  83. }
  84. // }}}
  85. // {{{ call(method, [args...])
  86. function call($method)
  87. {
  88. $_args = $args = func_get_args();
  89. $this->cache = $this->getCache($args);
  90. $cachettl = $this->config->get('cache_ttl');
  91. // If cache is newer than $cachettl seconds, we use the cache!
  92. if ($this->cache !== null && $this->cache['age'] < $cachettl) {
  93. return $this->cache['content'];
  94. };
  95. if (extension_loaded("xmlrpc")) {
  96. $result = call_user_func_array(array(&$this, 'call_epi'), $args);
  97. if (!PEAR::isError($result)) {
  98. $this->saveCache($_args, $result);
  99. };
  100. return $result;
  101. }
  102. if (!@include_once("XML/RPC.php")) {
  103. return $this->raiseError("For this remote PEAR operation you need to install the XML_RPC package");
  104. }
  105. array_shift($args);
  106. $server_host = $this->config->get('master_server');
  107. $username = $this->config->get('username');
  108. $password = $this->config->get('password');
  109. $eargs = array();
  110. foreach($args as $arg) $eargs[] = $this->_encode($arg);
  111. $f = new XML_RPC_Message($method, $eargs);
  112. if ($this->cache !== null) {
  113. $maxAge = '?maxAge='.$this->cache['lastChange'];
  114. } else {
  115. $maxAge = '';
  116. };
  117. $proxy_host = $proxy_port = $proxy_user = $proxy_pass = '';
  118. if ($proxy = parse_url($this->config->get('http_proxy'))) {
  119. $proxy_host = @$proxy['host'];
  120. $proxy_port = @$proxy['port'];
  121. $proxy_user = @$proxy['user'];
  122. $proxy_pass = @$proxy['pass'];
  123. }
  124. $c = new XML_RPC_Client('/xmlrpc.php'.$maxAge, $server_host, 80, $proxy_host, $proxy_port, $proxy_user, $proxy_pass);
  125. if ($username && $password) {
  126. $c->setCredentials($username, $password);
  127. }
  128. if ($this->config->get('verbose') >= 3) {
  129. $c->setDebug(1);
  130. }
  131. $r = $c->send($f);
  132. if (!$r) {
  133. return $this->raiseError("XML_RPC send failed");
  134. }
  135. $v = $r->value();
  136. if ($e = $r->faultCode()) {
  137. if ($e == $GLOBALS['XML_RPC_err']['http_error'] && strstr($r->faultString(), '304 Not Modified') !== false) {
  138. return $this->cache['content'];
  139. }
  140. return $this->raiseError($r->faultString(), $e);
  141. }
  142. $result = XML_RPC_decode($v);
  143. $this->saveCache($_args, $result);
  144. return $result;
  145. }
  146. // }}}
  147. // {{{ call_epi(method, [args...])
  148. function call_epi($method)
  149. {
  150. do {
  151. if (extension_loaded("xmlrpc")) {
  152. break;
  153. }
  154. if (OS_WINDOWS) {
  155. $ext = 'dll';
  156. } elseif (PHP_OS == 'HP-UX') {
  157. $ext = 'sl';
  158. } elseif (PHP_OS == 'AIX') {
  159. $ext = 'a';
  160. } else {
  161. $ext = 'so';
  162. }
  163. $ext = OS_WINDOWS ? 'dll' : 'so';
  164. @dl("xmlrpc-epi.$ext");
  165. if (extension_loaded("xmlrpc")) {
  166. break;
  167. }
  168. @dl("xmlrpc.$ext");
  169. if (extension_loaded("xmlrpc")) {
  170. break;
  171. }
  172. return $this->raiseError("unable to load xmlrpc extension");
  173. } while (false);
  174. $params = func_get_args();
  175. array_shift($params);
  176. $method = str_replace("_", ".", $method);
  177. $request = xmlrpc_encode_request($method, $params);
  178. $server_host = $this->config->get("master_server");
  179. if (empty($server_host)) {
  180. return $this->raiseError("PEAR_Remote::call: no master_server configured");
  181. }
  182. $server_port = 80;
  183. $fp = @fsockopen($server_host, $server_port);
  184. if (!$fp) {
  185. return $this->raiseError("PEAR_Remote::call: fsockopen(`$server_host', $server_port) failed");
  186. }
  187. $len = strlen($request);
  188. $req_headers = "Host: $server_host:$server_port\r\n" .
  189. "Content-type: text/xml\r\n" .
  190. "Content-length: $len\r\n";
  191. $username = $this->config->get('username');
  192. $password = $this->config->get('password');
  193. if ($username && $password) {
  194. $req_headers .= "Cookie: PEAR_USER=$username; PEAR_PW=$password\r\n";
  195. $tmp = base64_encode("$username:$password");
  196. $req_headers .= "Authorization: Basic $tmp\r\n";
  197. }
  198. if ($this->cache !== null) {
  199. $maxAge = '?maxAge='.$this->cache['lastChange'];
  200. } else {
  201. $maxAge = '';
  202. };
  203. if ($this->config->get('verbose') > 3) {
  204. print "XMLRPC REQUEST HEADERS:\n";
  205. var_dump($req_headers);
  206. print "XMLRPC REQUEST BODY:\n";
  207. var_dump($request);
  208. }
  209. fwrite($fp, ("POST /xmlrpc.php$maxAge HTTP/1.0\r\n$req_headers\r\n$request"));
  210. $response = '';
  211. $line1 = fgets($fp, 2048);
  212. if (!preg_match('!^HTTP/[0-9\.]+ (\d+) (.*)!', $line1, $matches)) {
  213. return $this->raiseError("PEAR_Remote: invalid HTTP response from XML-RPC server");
  214. }
  215. switch ($matches[1]) {
  216. case "200": // OK
  217. break;
  218. case "304": // Not Modified
  219. return $this->cache['content'];
  220. case "401": // Unauthorized
  221. if ($username && $password) {
  222. return $this->raiseError("PEAR_Remote: authorization failed", 401);
  223. } else {
  224. return $this->raiseError("PEAR_Remote: authorization required, please log in first", 401);
  225. }
  226. default:
  227. return $this->raiseError("PEAR_Remote: unexpected HTTP response", (int)$matches[1], null, null, "$matches[1] $matches[2]");
  228. }
  229. while (trim(fgets($fp, 2048)) != ''); // skip rest of headers
  230. while ($chunk = fread($fp, 10240)) {
  231. $response .= $chunk;
  232. }
  233. fclose($fp);
  234. if ($this->config->get('verbose') > 3) {
  235. print "XMLRPC RESPONSE:\n";
  236. var_dump($response);
  237. }
  238. $ret = xmlrpc_decode($response);
  239. if (is_array($ret) && isset($ret['__PEAR_TYPE__'])) {
  240. if ($ret['__PEAR_TYPE__'] == 'error') {
  241. if (isset($ret['__PEAR_CLASS__'])) {
  242. $class = $ret['__PEAR_CLASS__'];
  243. } else {
  244. $class = "PEAR_Error";
  245. }
  246. if ($ret['code'] === '') $ret['code'] = null;
  247. if ($ret['message'] === '') $ret['message'] = null;
  248. if ($ret['userinfo'] === '') $ret['userinfo'] = null;
  249. if (strtolower($class) == 'db_error') {
  250. $ret = $this->raiseError(PEAR::errorMessage($ret['code']),
  251. $ret['code'], null, null,
  252. $ret['userinfo']);
  253. } else {
  254. $ret = $this->raiseError($ret['message'], $ret['code'],
  255. null, null, $ret['userinfo']);
  256. }
  257. }
  258. } elseif (is_array($ret) && sizeof($ret) == 1 && is_array($ret[0]) &&
  259. !empty($ret[0]['faultString']) &&
  260. !empty($ret[0]['faultCode'])) {
  261. extract($ret[0]);
  262. $faultString = "XML-RPC Server Fault: " .
  263. str_replace("\n", " ", $faultString);
  264. return $this->raiseError($faultString, $faultCode);
  265. }
  266. return $ret;
  267. }
  268. // }}}
  269. // {{{ _encode
  270. // a slightly extended version of XML_RPC_encode
  271. function _encode($php_val)
  272. {
  273. global $XML_RPC_Boolean, $XML_RPC_Int, $XML_RPC_Double;
  274. global $XML_RPC_String, $XML_RPC_Array, $XML_RPC_Struct;
  275. $type = gettype($php_val);
  276. $xmlrpcval = new XML_RPC_Value;
  277. switch($type) {
  278. case "array":
  279. reset($php_val);
  280. $firstkey = key($php_val);
  281. end($php_val);
  282. $lastkey = key($php_val);
  283. if ($firstkey === 0 && is_int($lastkey) &&
  284. ($lastkey + 1) == count($php_val)) {
  285. $is_continuous = true;
  286. reset($php_val);
  287. $size = count($php_val);
  288. for ($expect = 0; $expect < $size; $expect++, next($php_val)) {
  289. if (key($php_val) !== $expect) {
  290. $is_continuous = false;
  291. break;
  292. }
  293. }
  294. if ($is_continuous) {
  295. reset($php_val);
  296. $arr = array();
  297. while (list($k, $v) = each($php_val)) {
  298. $arr[$k] = $this->_encode($v);
  299. }
  300. $xmlrpcval->addArray($arr);
  301. break;
  302. }
  303. }
  304. // fall though if not numerical and continuous
  305. case "object":
  306. $arr = array();
  307. while (list($k, $v) = each($php_val)) {
  308. $arr[$k] = $this->_encode($v);
  309. }
  310. $xmlrpcval->addStruct($arr);
  311. break;
  312. case "integer":
  313. $xmlrpcval->addScalar($php_val, $XML_RPC_Int);
  314. break;
  315. case "double":
  316. $xmlrpcval->addScalar($php_val, $XML_RPC_Double);
  317. break;
  318. case "string":
  319. case "NULL":
  320. $xmlrpcval->addScalar($php_val, $XML_RPC_String);
  321. break;
  322. case "boolean":
  323. $xmlrpcval->addScalar($php_val, $XML_RPC_Boolean);
  324. break;
  325. case "unknown type":
  326. default:
  327. return null;
  328. }
  329. return $xmlrpcval;
  330. }
  331. // }}}
  332. }
  333. ?>