1 <?php
4 class jsonRPC {
6 private $curlHandler = NULL;
7 private $config;
8 private $id;
9 private $lastStats = array();
10 private $lastResult = array();
11 private $lastAction = "none";
14 private $connectUrl = "";
15 private $username = "";
16 private $userPassword = "";
17 private $authModeDigest = FALSE;
20 /*! \brief Constructs a new jsonRPC handle which is connected to a given URL.
21 * It can either connect using a rpc method or via auth method digest.
22 * @param object The gosa configuration object (class_config)
23 * @param string The url to connect to.
24 * @param string The username for authentication
25 * @param string The password to use for authentication
26 * @param boolean Whether to use DIGEST authentication or not.
27 * @return
28 */
29 public function __construct($config, $connectUrl, $username, $userPassword, $authModeDigest=FALSE)
30 {
31 $this->config = $config;
32 $this->id = 0;
34 // Get connection data
35 $this->connectUrl = $connectUrl;
36 $this->username = $username;
37 $this->userPassword = $userPassword;
38 $this->authModeDigest = $authModeDigest;
40 // Put some usefull info in the logs
41 DEBUG (DEBUG_RPC, __LINE__, __FUNCTION__, __FILE__,bold($this->connectUrl), "Initiated RPC ");
42 DEBUG (DEBUG_RPC, __LINE__, __FUNCTION__, __FILE__,bold($this->username), "RPC user: ");
43 DEBUG (DEBUG_RPC, __LINE__, __FUNCTION__, __FILE__,bold($this->userPassword),"RPC password: ");
44 DEBUG (DEBUG_RPC, __LINE__, __FUNCTION__, __FILE__,bold($this->authModeDigest),"Digest Auth (0: No, 1: Yes): ");
46 $this->__login();
47 }
50 /*! \brief
51 * @param
52 * @return
53 */
54 private function __login()
55 {
56 // Init Curl handler
57 $this->curlHandler = curl_init($this->connectUrl);
59 // Set curl options
60 curl_setopt($this->curlHandler, CURLOPT_URL , $this->connectUrl);
61 curl_setopt($this->curlHandler, CURLOPT_POST , TRUE);
62 curl_setopt($this->curlHandler, CURLOPT_RETURNTRANSFER ,TRUE);
63 curl_setopt($this->curlHandler, CURLOPT_HTTPHEADER , array('Content-Type: application/json'));
64 curl_setopt($this->curlHandler, CURLOPT_SSL_VERIFYPEER, FALSE);
66 // Try to login
67 if($this->authModeDigest){
68 curl_setopt($this->curlHandler, CURLOPT_USERPWD , "{$this->username}:{$this->userPassword}");
69 curl_setopt($this->curlHandler, CURLOPT_HTTPAUTH , CURLAUTH_ANYSAFE);
70 }else{
71 curl_setopt($this->curlHandler, CURLOPT_COOKIESESSION , TRUE);
72 curl_setopt($this->curlHandler, CURLOPT_COOKIEFILE, 'cookiefile.txt');
73 $this->login($this->username, $this->userPassword);
74 }
75 }
78 /*! \brief Returns the last HTTP status code.
79 * @return int The last status code.
80 */
81 public function getHTTPstatusCode()
82 {
83 return((isset($this->lastStats['http_code']))? $this->lastStats['http_code'] : -1 );
84 }
87 /*! \brief Returns the last error string.
88 * @return string The last error message.
89 */
90 public function get_error()
91 {
92 if($this->lastStats['http_code'] != 200){
93 $error = $this->getHttpStatusCodeMessage($this->lastStats['http_code']);
94 if(isset($this->lastResult['error']['message'])){
95 $error .= ": ".$this->lastResult['error']['message'];
96 }
97 return($error);
98 }else{
99 return(curl_error($this->curlHandler));
100 }
101 }
105 /*! \brief Returns TRUE if the last action was successfull else FALSE.
106 * @return boolean TRUE on success else FALSE.
107 */
108 public function success()
109 {
110 return(curl_errno($this->curlHandler) == 0 && $this->lastStats['http_code'] == 200);
111 }
114 /*! \brief The class destructor, it destroys open rpc handles if needed.
115 */
116 public function __destruct()
117 {
118 if($this->curlHandler){
119 curl_close($this->curlHandler);
120 }
121 }
124 /*! \brief This is some kind of catch-all method, all unknown method names will
125 * will be interpreted as rpc request.
126 * If you call "$this->blafasel" this method will initiate an rpc request
127 * for method 'blafasel'.
128 * @param string method The rpc method to execute.
129 * @param params array The parameter to use.
130 * @return mixed The request result.
131 */
132 public function __call($method,$params)
133 {
134 // Check if handle is still valid!
135 if(!$this->curlHandler && $this->lastAction != 'login'){
136 $this->__login();
137 }
139 // Start request
140 DEBUG (DEBUG_RPC, __LINE__, __FUNCTION__, __FILE__,"{$method}", "Calling: ");
141 $response = $this->request($method,$params);
142 if($this->success()){
143 DEBUG (DEBUG_RPC, __LINE__, __FUNCTION__, __FILE__,
144 (is_array($response['result']))?$response['result']:bold($response['result']), "Result: ");
145 }else{
146 DEBUG (DEBUG_RPC, __LINE__, __FUNCTION__, __FILE__,bold($this->get_error())."<br>".$response, "Result (FAILED): ");
147 }
149 global $config;
150 $debugLevel = $config->get_cfg_value('core', 'debugLevel');
151 if($debugLevel & DEBUG_RPC){
152 print_a(array('CALLED:' => array($method => $params)));
153 print_a(array('RESPONSE' => $response));
154 }
155 return($response['result']);
156 }
159 /*! \brief This method finally initiates the real RPC requests and handles
160 * the result from the server.
161 * @param string method The method to call
162 * @param array params The paramter to use.
163 * @return mixed The server response.
164 */
165 private function request($method, $params)
166 {
167 // Set last action
168 $this->lastAction = $method;
170 // Reset stats of last request.
171 $this->lastStats = array();
173 // Validate input values
174 if (!is_scalar($method)) trigger_error('jsonRPC::__call requires a scalar value as first parameter!');
175 if (is_array($params)) {
176 $params = array_values($params);
177 } else {
178 trigger_error('jsonRPC::__call requires an array value as second parameter!');
179 }
181 // prepares the request
182 $this->id ++;
183 $request = json_encode(array('method' => $method,'params' => $params,'id' => $this->id));
185 // Set curl options
186 curl_setopt($this->curlHandler, CURLOPT_POSTFIELDS , $request);
187 $response = curl_exec($this->curlHandler);
188 $response = json_decode($response,true);
190 // Set current result stats.
191 $this->lastStats = curl_getinfo($this->curlHandler);
192 $this->lastResult = $response;
194 return($response);
195 }
198 /*! \brief Returns the HTTP status message for a given HTTP status code.
199 * @param int code The status to code to return a message for.
200 * @return string The corresponding status message.
201 */
202 public static function getHttpStatusCodeMessage($code)
203 {
204 $codes = array(
205 '100' => 'Continue',
206 '101' => 'Switching Protocols',
207 '102' => 'Processing',
208 '200' => 'OK',
209 '201' => 'Created',
210 '202' => 'Accepted',
211 '203' => 'Non-Authoritative Information',
212 '204' => 'No Content',
213 '205' => 'Reset Content',
214 '206' => 'Partial Content',
215 '207' => 'Multi-Status',
216 '300' => 'Multiple Choice',
217 '301' => 'Moved Permanently',
218 '302' => 'Found',
219 '303' => 'See Other',
220 '304' => 'Not Modified',
221 '305' => 'Use Proxy',
222 '306' => 'reserved',
223 '307' => 'Temporary Redirect',
224 '400' => 'Bad Request',
225 '401' => 'Unauthorized',
226 '402' => 'Payment Required',
227 '403' => 'Forbidden',
228 '404' => 'Not Found',
229 '405' => 'Method Not Allowed',
230 '406' => 'Not Acceptable',
231 '407' => 'Proxy Authentication Required',
232 '408' => 'Request Time-out',
233 '409' => 'Conflict',
234 '410' => 'Gone',
235 '411' => 'Length Required',
236 '412' => 'Precondition Failed',
237 '413' => 'Request Entity Too Large',
238 '414' => 'Request-URI Too Long',
239 '415' => 'Unsupported Media Type',
240 '416' => 'Requested range not satisfiable',
241 '417' => 'Expectation Failed',
242 '421' => 'There are too many connections from your internet address',
243 '422' => 'Unprocessable Entity',
244 '423' => 'Locked',
245 '424' => 'Failed Dependency',
246 '425' => 'Unordered Collection',
247 '426' => 'Upgrade Required',
248 '500' => 'Internal Server Error',
249 '501' => 'Not Implemented',
250 '502' => 'Bad Gateway',
251 '503' => 'Service Unavailable',
252 '504' => 'Gateway Time-out',
253 '505' => 'HTTP Version not supported',
254 '506' => 'Variant Also Negotiates',
255 '507' => 'Insufficient Storage',
256 '509' => 'Bandwidth Limit Exceeded',
257 '510' => 'Not Extended');
258 return((isset($codes[$code]))? $codes[$code] : sprintf(_("Unknown HTTP status code '%s'!"), $code));
259 }
260 }
261 ?>