Merge remote-tracking branch 'origin/pycurl' into planetlab-4_0-branch
[plcapi.git] / php / header.php
1 <?php
2 //
3 // PlanetLab Central Slice API (PLCAPI) PHP interface
4 //
5 // DO NOT EDIT. This file was automatically generated at
6 // @DATE@.
7 //
8 // Mark Huang <mlhuang@cs.princeton.edu>
9 // Copyright (C) 2005-2006 The Trustees of Princeton University
10 //
11 // $Id: header.php,v 1.5 2007/09/13 18:12:54 tmack Exp $
12 //
13 //
14
15 require_once 'plc_config.php';
16
17 class PLCAPI
18 {
19   var $auth;
20   var $server;
21   var $port;
22   var $path;
23   var $errors;
24   var $trace;
25   var $calls;
26   var $multicall;
27
28   function PLCAPI($auth = NULL,
29                   $server = PLC_API_HOST,
30                   $port = PLC_API_PORT,
31                   $path = PLC_API_PATH,
32                   $cainfo = NULL)
33   {
34     $this->auth = $auth;
35     $this->server = $server;
36     $this->port = $port;
37     $this->path = $path;
38     $this->cainfo = $cainfo;
39     $this->errors = array();
40     $this->trace = array();
41     $this->calls = array();
42     $this->multicall = false;
43   }
44
45   function error_log($error_msg, $backtrace_level = 1)
46   {
47     $backtrace = debug_backtrace();
48     $file = $backtrace[$backtrace_level]['file'];
49     $line = $backtrace[$backtrace_level]['line'];
50
51     $this->errors[] = 'PLCAPI error:  ' . $error_msg . ' in ' . $file . ' on line ' . $line;
52     error_log(end($this->errors));
53   }
54
55   function error()
56   {
57     if (empty($this->trace)) {
58       return NULL;
59     } else {
60       $last_trace = end($this->trace);
61       return implode("\\n", $last_trace['errors']);
62     }
63   }
64
65   function trace()
66   {
67     return $this->trace;
68   }
69
70   function microtime_float()
71   {
72     list($usec, $sec) = explode(" ", microtime());
73     return ((float) $usec + (float) $sec);
74   }
75
76   function call($method, $args = NULL)
77   {
78     if ($this->multicall) {
79       $this->calls[] = array ('methodName' => $method,
80                                 'params' => $args);
81       return NULL;
82     } else {
83       return $this->internal_call ($method, $args, 3);
84     }
85   }
86
87   function internal_call($method, $args = NULL, $backtrace_level = 2)
88   {
89     $curl = curl_init();
90
91     // Verify peer certificate if talking over SSL
92     if ($this->port == 443) {
93       curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 2);
94       if (!empty($this->cainfo)) {
95         curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo);
96       } elseif (defined('PLC_API_CA_SSL_CRT')) {
97         curl_setopt($curl, CURLOPT_CAINFO, PLC_API_CA_SSL_CRT);
98       }
99       $url = 'https://';
100     } else {
101       $url = 'http://';
102     }
103
104     // Set the URL for the request
105     $url .= $this->server . ':' . $this->port . '/' . $this->path;
106     curl_setopt($curl, CURLOPT_URL, $url);
107
108     // Marshal the XML-RPC request as a POST variable. <nil/> is an
109     // extension to the XML-RPC spec that is supported in our custom
110     // version of xmlrpc.so via the 'allow_null' output_encoding key.
111     $request = xmlrpc_encode_request($method, $args, array('allow_null' => TRUE));
112     curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
113
114     // Construct the HTTP header
115     $header[] = 'Content-type: text/xml';
116     $header[] = 'Content-length: ' . strlen($request);
117     curl_setopt($curl, CURLOPT_HTTPHEADER, $header);
118
119     // Set some miscellaneous options
120     curl_setopt($curl, CURLOPT_TIMEOUT, 30);
121
122     // Get the output of the request
123     curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
124     $t0 = $this->microtime_float();
125     $output = curl_exec($curl);
126     $t1 = $this->microtime_float();
127
128     if (curl_errno($curl)) {
129       $this->error_log('curl: ' . curl_error($curl), true);
130       $ret = NULL;
131     } else {
132       $ret = xmlrpc_decode($output);
133       if (is_array($ret) && xmlrpc_is_fault($ret)) {
134         $this->error_log('Fault Code ' . $ret['faultCode'] . ': ' .
135                          $ret['faultString'], $backtrace_level, true);
136         $ret = NULL;
137       }
138     }
139
140     curl_close($curl);
141
142     $this->trace[] = array('method' => $method,
143                            'args' => $args,
144                            'runtime' => $t1 - $t0,
145                            'return' => $ret,
146                            'errors' => $this->errors);
147     $this->errors = array();
148
149     return $ret;
150   }
151
152   function begin()
153   {
154     if (!empty($this->calls)) {
155       $this->error_log ('Warning: multicall already in progress');
156     }
157
158     $this->multicall = true;
159   }
160
161   function commit()
162   {
163     if (!empty ($this->calls)) {
164       $ret = array();
165       $results = $this->internal_call ('system.multicall', array ($this->calls));
166       foreach ($results as $result) {
167         if (is_array($result)) {
168           if (xmlrpc_is_fault($result)) {
169             $this->error_log('Fault Code ' . $result['faultCode'] . ': ' .
170                              $result['faultString'], 1, true);
171             $ret[] = NULL;
172             // Thierry - march 30 2007 
173             // using $adm->error() is broken with begin/commit style 
174             // this is because error() uses last item in trace and checks for ['errors']
175             // when using begin/commit we do run internal_call BUT internal_call checks for 
176             // multicall's result globally, not individual results, so ['errors'] comes empty
177             // I considered hacking internal_call 
178             // to *NOT* maintain this->trace at all when invoked with multicall
179             // but it is too complex to get all values right
180             // so let's go for the hacky way, and just record individual errors at the right place
181             $this->trace[count($this->trace)-1]['errors'][] = end($this->errors);
182           } else {
183             $ret[] = $result[0];
184           }
185         } else {
186           $ret[] = $result;
187         }
188       }
189     } else {
190       $ret = NULL;
191     }
192
193     $this->calls = array();
194     $this->multicall = false;
195
196     return $ret;
197   }
198
199   //
200   // PLCAPI Methods
201   //
202