├── README.md └── webex.php /README.md: -------------------------------------------------------------------------------- 1 | php-webex 2 | ========= 3 | 4 | PHPebEx - A Unofficial WebEx PHP API 5 | -------------------------------------------------------------------------------- /webex.php: -------------------------------------------------------------------------------- 1 | 8 | * @copyright Copyright (c) 2013, RedRat Consultoria 9 | * @license GPL version 2 10 | * @see Github, animes and mangás, cute girls and PHP, much PHP 11 | * @link http://developer.cisco.com/documents/4733862/4736722/xml_api_5+9.pdf 12 | * @link https://github.com/joubertredrat/phpebex-php-webex 13 | */ 14 | 15 | class Webex { 16 | 17 | private $username; 18 | private $password; 19 | private $siteID; 20 | private $partnerID; 21 | 22 | private $url_prefix; 23 | private $url_host; 24 | 25 | private $send_mode; 26 | 27 | private $data; 28 | 29 | private $action; 30 | 31 | const SEND_CURL = 'curl'; 32 | const SEND_FSOCKS = 'fsocks'; 33 | const PREFIX_HTTP = 'http'; 34 | const PREFIX_HTTPS = 'https'; 35 | const SUFIX_XML_API = 'WBXService/XMLService'; 36 | const WEBEX_DOMAIN = 'webex.com'; 37 | const XML_VERSION = '1.0'; 38 | const XML_ENCODING = 'UTF-8'; 39 | const USER_AGENT = 'PHPebEx - WebEx PHP API (https://github.com/joubertredrat/phpebex-php-webex)'; 40 | 41 | const API_SCHEMA_MEETING = 'http://www.webex.com/schemas/2002/06/service/meeting'; 42 | const API_SCHEMA_SERVICE = 'http://www.webex.com/schemas/2002/06/service'; 43 | 44 | const DATA_SENDER = 'sender'; 45 | const DATA_SENDER_POST_HEADER = 'post_header'; 46 | const DATA_SENDER_POST_BODY = 'post_body'; 47 | const DATA_SENDER_XML = 'xml'; 48 | const DATA_RESPONSE = 'response'; 49 | const DATA_RESPONSE_XML = 'xml'; 50 | const DATA_RESPONSE_DATA = 'data'; 51 | 52 | /** 53 | * Constructor of class. 54 | * 55 | * @return void 56 | */ 57 | public function __construct() { 58 | $this->action = 0; 59 | $this->response = array(); 60 | $this->send_mode = in_array(self::SEND_CURL, get_loaded_extensions()) ? self::SEND_CURL : self::SEND_FSOCKS; 61 | } 62 | 63 | /** 64 | * Get a possible modes to send a POST data. 65 | * 66 | * @return array Returns a list of send modes. 67 | */ 68 | public static function get_sendmode() { 69 | return array(self::SEND_CURL, self::SEND_FSOCKS); 70 | } 71 | 72 | /** 73 | * Validates a customer webex domain. 74 | * 75 | * @param string $url Url to validate. 76 | * @return bool Return true if a valid url or false if not. 77 | */ 78 | public static function validate_url($url) { 79 | $regex = "/^(http|https):\/\/(([A-Z0-9][A-Z0-9_-]*)+.(" . self::WEBEX_DOMAIN . ")$)/i"; 80 | return (bool) preg_match($regex, $url); 81 | } 82 | 83 | /** 84 | * Get port used by API. 85 | * 86 | * @param string $prefix Prefix to get a port. 87 | * @return int Return a port. 88 | */ 89 | public static function get_port($prefix) { 90 | switch($prefix) { 91 | case self::PREFIX_HTTP: 92 | return 80; 93 | break; 94 | case self::PREFIX_HTTPS: 95 | return 443; 96 | break; 97 | default: 98 | exit(__CLASS__ . ' error report: Wrong prefix'); 99 | break; 100 | } 101 | } 102 | 103 | /** 104 | * Set a url to integrate to webex. 105 | * 106 | * @param string $url Customer url. 107 | * @return void 108 | */ 109 | public function set_url($url) { 110 | if(!self::validate_url($url)) 111 | exit(__CLASS__ . ' error report: Wrong webex url'); 112 | list($this->url_prefix, $this->url_host) = preg_split("$://$", $url); 113 | } 114 | 115 | /** 116 | * Mode to send data. 117 | * 118 | * @param string mode to send. 119 | * @return void 120 | */ 121 | public function set_sendmode($mode) { 122 | if(!in_array($mode, self::get_sendmode())) 123 | exit(__CLASS__ . ' error report: Wrong send mode'); 124 | $this->send_mode = $mode; 125 | } 126 | 127 | /** 128 | * Auth data to integrate with API. 129 | * 130 | * @param string $username Username to auth. 131 | * @param string $password Password to auth. 132 | * @param string $siteID Customer site id. 133 | * @param string $partnerID Customer partnerID id. 134 | * @return void 135 | */ 136 | public function set_auth($username, $password, $siteID, $partnerID) { 137 | $this->username = $username; 138 | $this->password = $password; 139 | $this->siteID = $siteID; 140 | $this->partnerID = $partnerID; 141 | } 142 | 143 | /** 144 | * Generates a XML to send a data to API. 145 | * 146 | * @param array $data Data to insert in XML in format: 147 | * $data['service'] = 'meeting'; 148 | * $data['xml_header'] = 'data'; 149 | * $data['xml_body'] = 'data'; 150 | * @return string Returns a XML generated. 151 | */ 152 | private function get_xml($data) { 153 | $xml = array(); 154 | $xml[] = ''; 155 | $xml[] = ''; 156 | $xml[] = '
'; 157 | $xml[] = ''; 158 | $xml[] = '' . $this->username . ''; 159 | $xml[] = '' . $this->password . ''; 160 | $xml[] = '' . $this->siteID . ''; 161 | $xml[] = '' . $this->partnerID . ''; 162 | if(isset($data['xml_header'])) 163 | $xml[] = $data['xml_header']; 164 | $xml[] = ''; 165 | $xml[] = '
'; 166 | $xml[] = ''; 167 | $xml[] = ''; 168 | $xml[] = $data['xml_body']; 169 | $xml[] = ''; 170 | $xml[] = ''; 171 | $xml[] = '
'; 172 | return implode('', $xml); 173 | } 174 | 175 | /** 176 | * Test if have a auth data to use a API. 177 | * 178 | * @return bool Returns true if have data and false if not. 179 | */ 180 | public function has_auth() { 181 | return (bool) $this->username && $this->password && $this->siteID && $this->partnerID; 182 | } 183 | 184 | /** 185 | * Generates a header and a body to send data to API. 186 | * 187 | * @return string Returns a response from API. 188 | */ 189 | private function send($xml) { 190 | $post_data['UID'] = $this->username; 191 | $post_data['PWD'] = $this->password; 192 | $post_data['SID'] = $this->siteID; 193 | $post_data['PID'] = $this->partnerID; 194 | $post_data['XML'] = $xml; 195 | 196 | // Really I dont know why xml api give a error on http_build_query :( 197 | $post_string = ''; 198 | foreach ($post_data as $variable => $value) { 199 | $post_string .= '' . $variable . '=' . urlencode($value) . '&'; 200 | } 201 | 202 | $post_header = array(); 203 | $post_header[] = 'POST /' . self::SUFIX_XML_API . ' HTTP/1.0'; 204 | $post_header[] = 'Host: ' . $this->url_host; 205 | $post_header[] = 'User-Agent: ' . self::USER_AGENT; 206 | if($this->send_mode == self::SEND_FSOCKS) { 207 | $post_header[] = 'Content-Type: application/xml'; 208 | $post_header[] = 'Content-Length: ' . strlen($xml); 209 | } 210 | $data = array(); 211 | $data['post_header'] = $post_header; 212 | $data['post_string'] = $post_string; 213 | 214 | $this->data[$this->action][self::DATA_SENDER][self::DATA_SENDER_POST_HEADER] = $post_header; 215 | $this->data[$this->action][self::DATA_SENDER][self::DATA_SENDER_POST_BODY] = $post_header; 216 | $this->data[$this->action][self::DATA_SENDER][self::DATA_SENDER_XML] = $xml; 217 | 218 | return $this->{'send_' . $this->send_mode}($data); 219 | } 220 | 221 | /** 222 | * Send a data to Webex API using PHP curl. 223 | * 224 | * @param array $data Data to send to API in format: 225 | * $data['post_header'] = "blablabla"; 226 | * $data['post_header'] = "post_string"; 227 | * @return string Returns a response from API. 228 | */ 229 | private function send_curl($data) { 230 | extract($data); 231 | $ch = curl_init(); 232 | curl_setopt($ch, CURLOPT_URL, $this->url_prefix . '://' . $this->url_host . '/' . self::SUFIX_XML_API); 233 | curl_setopt($ch, CURLOPT_PORT, self::get_port($this->url_prefix)); 234 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 235 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 236 | curl_setopt($ch, CURLOPT_HTTPHEADER, $post_header); 237 | curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string); 238 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 239 | $response = curl_exec($ch); 240 | if($response === false) 241 | exit(__CLASS__ . ' error report: Curl error - ' . curl_error($ch)); 242 | curl_close($ch); 243 | return $response; 244 | } 245 | 246 | /** 247 | * Send a data to Webex API using PHP file functions. 248 | * 249 | * @param array $data Data to send to API in format: 250 | * $data['post_header'] = "blablabla"; 251 | * $data['post_header'] = "post_string"; 252 | * @return string Returns a response from API. 253 | * @todo haha, I need to test this :) 254 | */ 255 | private function send_fsocks($data) { 256 | extract($data); 257 | $post_data = implode("\n", $post_header) . "\n\n" . $post_string . "\n"; 258 | $fp = fsockopen($this->url_host, self::get_port($this->url_prefix), $errno, $error); 259 | if($fp) { 260 | fwrite($fp, $post_data); 261 | $response = ''; 262 | while(!feof($fp)) { 263 | $response .= fgets($fp, 1024); 264 | } 265 | return $response; 266 | } 267 | else 268 | exit(__CLASS__ . ' error report: Fsocks error - (' . $errno . ') ' . $error); 269 | } 270 | 271 | /** 272 | * Get response from a API. 273 | * 274 | * @param string $type Type of data to be requested. 275 | * @param int $number number of sender to be requested. 276 | * @return string|object Return a response. 277 | */ 278 | public function get_response($type = self::DATA_RESPONSE_DATA, $number = null) { 279 | if(isset($number) && is_int($number)) { 280 | if($number < 1 || $number > ($this->action - 1)) 281 | exit(__CLASS__ . ' error report: Invalid response number'); 282 | $number--; 283 | } 284 | else 285 | $number = ($this->action - 1); 286 | var_dump($number); 287 | switch($type) { 288 | case self::DATA_RESPONSE_XML: 289 | case self::DATA_RESPONSE_DATA: 290 | return $this->data[$number][self::DATA_RESPONSE][$type]; 291 | break; 292 | default: 293 | exit(__CLASS__ . ' error report: I don\'t undestood that data you needs'); 294 | break; 295 | } 296 | } 297 | 298 | /** 299 | * @todo documentate in future. 300 | */ 301 | public function meeting_LstsummaryMeeting($maximumNum = 5) { 302 | if(!$this->has_auth()) 303 | exit(__CLASS__ . ' error report: Auth data not found'); 304 | $xml_body = array(); 305 | $xml_body[] = ''; 306 | $xml_body[] = ''; 307 | $xml_body[] = '' . $maximumNum . ''; 308 | $xml_body[] = ''; 309 | $xml_body[] = ''; 310 | $xml_body[] = 'STARTTIME'; 311 | $xml_body[] = ''; 312 | $xml_body[] = ''; 313 | $xml_body[] = ''; 314 | 315 | $data['xml_body'] = implode('', $xml_body); 316 | $data['service'] = str_replace("_", ".", __FUNCTION__); 317 | $xml = $this->get_xml($data); 318 | $response = $this->send($xml); 319 | 320 | $xml = simplexml_load_string($response); 321 | $Data = new stdClass; 322 | $Data->header = new stdClass; 323 | $Data->header->response = new stdClass; 324 | $Data->bodyContent = array(); 325 | 326 | $node = $xml->children(self::API_SCHEMA_SERVICE); 327 | $Data->header->response->result = (string) $node[0]->response->result; 328 | $Data->header->response->gsbStatus = (string) $node[0]->response->gsbStatus; 329 | 330 | $node_meeting = $node[1]->bodyContent; 331 | 332 | foreach($node_meeting->children(self::API_SCHEMA_MEETING) as $meeting) { 333 | if($meeting->meetingKey) { 334 | $MeetingData = new stdClass; 335 | $MeetingData->meetingKey = (string) $meeting->meetingKey; 336 | $MeetingData->confName = (string) $meeting->confName; 337 | $MeetingData->meetingType = (string) $meeting->meetingType; 338 | $MeetingData->hostWebExID = (string) $meeting->hostWebExID; 339 | $MeetingData->otherHostWebExID = (string) $meeting->otherHostWebExID; 340 | $MeetingData->timeZoneID = (string) $meeting->timeZoneID; 341 | $MeetingData->timeZone = (string) $meeting->timeZone; 342 | $MeetingData->status = (string) $meeting->status; 343 | $MeetingData->startDate = (string) $meeting->startDate; 344 | $MeetingData->duration = (string) $meeting->duration; 345 | $MeetingData->listStatus = (string) $meeting->listStatus; 346 | $MeetingData->hostJoined = (string) $meeting->hostJoined; 347 | $MeetingData->participantsJoined = (string) $meeting->participantsJoined; 348 | $MeetingData->telePresence = (string) $meeting->telePresence; 349 | $Data->bodyContent[] = $MeetingData; 350 | } 351 | } 352 | 353 | $this->data[$this->action][self::DATA_RESPONSE][self::DATA_RESPONSE_DATA] = $Data; 354 | $this->data[$this->action][self::DATA_RESPONSE][self::DATA_RESPONSE_XML] = $response; 355 | $this->action++; 356 | } 357 | 358 | //public function user_AuthenticateUser() 359 | //public function user_CreateUser() 360 | //public function user_DelUser() 361 | //public function user_DelSessionTemplates() 362 | //public function user_GetloginTicket() 363 | //public function user_GetloginurlUser() 364 | //public function user_GetlogouturlUser() 365 | //public function user_GetUser() 366 | //public function user_LstsummaryUser() 367 | //public function user_SetUser() 368 | //public function user_UploadPMRIImage() 369 | 370 | //public function meeting_CreateMeeting() 371 | //public function meeting_CreateTeleconferenceSession() 372 | //public function meeting_DelMeeting() 373 | //public function meeting_GethosturlMeeting() 374 | //public function meeting_GetMeeting() 375 | //public function meeting_GetTeleconferenceSession() 376 | //public function meeting_LstsummaryMeeting() 377 | //public function meeting_SetMeeting() 378 | //public function meeting_SetTeleconferenceSession() 379 | //public function meeting_GetjoinurlMeeting() 380 | 381 | //public function event_CreateEvent() 382 | //public function event_DelEvent() 383 | //public function event_GetEvent() 384 | //public function event_LstRecordedEvent() 385 | //public function event_LstsummaryProgram() 386 | //public function event_SendInvitationEmail() 387 | //public function event_SetEvent() 388 | //public function event_UploadEventImage() 389 | //public function event_LstsummaryEvent() 390 | 391 | //public function attendee_CreateMeetingAttendee() 392 | //public function attendee_LstMeetingAttendee() 393 | //public function attendee_RegisterMeetingAttendee() 394 | //public function history_LstmeetingattendeeHistory() 395 | } --------------------------------------------------------------------------------