3 // TopHat API PHP interface
6 // TODO add tophat_api in the php default path in /etc/plc.d/httpd
7 // TODO occurences to PLC
9 define('TOPHAT_API_HOST', 'www.top-hat.info');
10 define('TOPHAT_API_PATH', '/API/');
11 define('TOPHAT_API_PORT', 443);
24 function TopHatAPI($auth = NULL,
25 $server = TOPHAT_API_HOST,
26 $port = TOPHAT_API_PORT,
27 $path = TOPHAT_API_PATH,
31 $this->server = $server;
34 $this->cainfo = $cainfo;
35 $this->errors = array();
36 $this->trace = array();
37 $this->calls = array();
38 $this->multicall = false;
41 function error_log($error_msg, $backtrace_level = 1)
43 $backtrace = debug_backtrace();
44 $file = $backtrace[$backtrace_level]['file'];
45 $line = $backtrace[$backtrace_level]['line'];
47 $this->errors[] = 'TopHatAPI error: ' . $error_msg . ' in ' . $file . ' on line ' . $line;
48 error_log(end($this->errors));
53 if (empty($this->trace)) {
56 $last_trace = end($this->trace);
57 return implode("\\n", $last_trace['errors']);
66 function microtime_float()
68 list($usec, $sec) = explode(" ", microtime());
69 return ((float) $usec + (float) $sec);
72 function call($method, $args = NULL)
74 if ($this->multicall) {
75 $this->calls[] = array ('methodName' => $method,
79 return $this->internal_call ($method, $args, 3);
83 function internal_call($method, $args = NULL, $backtrace_level = 2)
87 // Verify peer certificate if talking over SSL
88 if ($this->port == 443) {
89 curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // XXX 2
90 if (!empty($this->cainfo)) {
91 curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo);
92 } elseif (defined('PLC_API_CA_SSL_CRT')) {
93 curl_setopt($curl, CURLOPT_CAINFO, PLC_API_CA_SSL_CRT);
100 // Set the URL for the request
101 $url .= $this->server . ':' . $this->port . '/' . $this->path;
102 curl_setopt($curl, CURLOPT_URL, $url);
104 // Marshal the XML-RPC request as a POST variable. <nil/> is an
105 // extension to the XML-RPC spec that is supported in our custom
106 // version of xmlrpc.so via the 'allow_null' output_encoding key.
107 $request = xmlrpc_encode_request($method, $args, array('allow_null' => TRUE));
108 curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
110 // Construct the HTTP header
111 $header[] = 'Content-type: text/xml';
112 $header[] = 'Content-length: ' . strlen($request);
113 curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
115 // Set some miscellaneous options
116 curl_setopt($curl, CURLOPT_TIMEOUT, 180);
118 // Get the output of the request
119 curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
120 $t0 = $this->microtime_float();
121 $output = curl_exec($curl);
122 $t1 = $this->microtime_float();
124 if (curl_errno($curl)) {
125 $this->error_log('curl: ' . curl_error($curl), true);
128 $ret = xmlrpc_decode($output);
129 if (is_array($ret) && xmlrpc_is_fault($ret)) {
130 $this->error_log('Fault Code ' . $ret['faultCode'] . ': ' .
131 $ret['faultString'], $backtrace_level, true);
138 $this->trace[] = array('method' => $method,
140 'runtime' => $t1 - $t0,
142 'errors' => $this->errors);
143 $this->errors = array();
150 if (!empty($this->calls)) {
151 $this->error_log ('Warning: multicall already in progress');
154 $this->multicall = true;
159 if (!empty ($this->calls)) {
161 $results = $this->internal_call ('system.multicall', array ($this->calls));
162 foreach ($results as $result) {
163 if (is_array($result)) {
164 if (xmlrpc_is_fault($result)) {
165 $this->error_log('Fault Code ' . $result['faultCode'] . ': ' .
166 $result['faultString'], 1, true);
168 // Thierry - march 30 2007
169 // using $adm->error() is broken with begin/commit style
170 // this is because error() uses last item in trace and checks for ['errors']
171 // when using begin/commit we do run internal_call BUT internal_call checks for
172 // multicall's result globally, not individual results, so ['errors'] comes empty
173 // I considered hacking internal_call
174 // to *NOT* maintain this->trace at all when invoked with multicall
175 // but it is too complex to get all values right
176 // so let's go for the hacky way, and just record individual errors at the right place
177 $this->trace[count($this->trace)-1]['errors'][] = end($this->errors);
189 $this->calls = array();
190 $this->multicall = false;
199 // Gets measurement information.
201 // Returns the measurement (cf doc).
203 function Test($param = NULL)
205 $args[] = $this->auth;
206 if (func_num_args() > 0) $args[] = $param;
207 return $this->call('Test', $args);
210 function Get($method, $timestamp, $input_filter = NULL, $output_fields = NULL, $callback = NULL)
212 $args[] = $this->auth;
214 $args[] = $timestamp;
215 if (func_num_args() > 2) $args[] = $input_filter;
216 if (func_num_args() > 3) $args[] = $output_fields;
217 if (func_num_args() > 4) $args[] = $callback;
218 return $this->call('Get', $args);
223 function GetPlatforms($input_filter = NULL, $output_fields = NULL)
225 $args[] = $this->auth;
226 if (func_num_args() > 0) $args[] = $input_filter;
227 if (func_num_args() > 1) $args[] = $output_fields;
228 return $this->call('GetPlatforms', $args);
231 function GetTraceroutes($input_filter = NULL, $output_fields = NULL)
233 $args[] = $this->auth;
234 if (func_num_args() > 0) $args[] = $input_filter;
235 if (func_num_args() > 1) $args[] = $output_fields;
236 return $this->call('GetTraceroutes', $args);
239 // Imported PLC Methods
241 // Returns a new session key if a user or node authenticated
242 // successfully, faults otherwise.
244 function GetSession ()
246 $args[] = $this->auth;
247 return $this->call('GetSession', $args);
250 // Returns an array of structs containing details about users sessions. If
251 // session_filter is specified and is an array of user identifiers or
252 // session_keys, or a struct of session attributes, only sessions matching the
253 // filter will be returned. If return_fields is specified, only the
254 // specified details will be returned.
256 function GetSessions ($session_filter = NULL)
258 $args[] = $this->auth;
259 if (func_num_args() > 0) $args[] = $session_filter;
260 return $this->call('GetSessions', $args);
263 // Returns an array of structs containing details about users. If
264 // person_filter is specified and is an array of user identifiers or
265 // usernames, or a struct of user attributes, only users matching the
266 // filter will be returned. If return_fields is specified, only the
267 // specified details will be returned.
269 // Users and techs may only retrieve details about themselves. PIs
270 // may retrieve details about themselves and others at their
271 // sites. Admins and nodes may retrieve details about all accounts.
273 function GetPersons ($person_filter = NULL, $return_fields = NULL)
275 $args[] = $this->auth;
276 if (func_num_args() > 0) $args[] = $person_filter;
277 if (func_num_args() > 1) $args[] = $return_fields;
278 return $this->call('GetPersons', $args);
281 // Returns 1 if the user or node authenticated successfully, faults
284 function AuthCheck ()
286 $args[] = $this->auth;
287 return $this->call('AuthCheck', $args);