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