diff --git a/lib/GergelyPolonkai/SmsSender/Sender.php b/lib/GergelyPolonkai/SmsSender/Sender.php index 887e587..88d9b86 100644 --- a/lib/GergelyPolonkai/SmsSender/Sender.php +++ b/lib/GergelyPolonkai/SmsSender/Sender.php @@ -1,6 +1,202 @@ cookies = array(); + $this->token = null; + + /* + * Set up the CURL handle based on configuration options + */ + $this->curl_handle = curl_init(); + curl_setopt($this->curl_handle, CURLOPT_SSL_VERIFYPEER, $verifySsl); + curl_setopt($this->curl_handle, CURLOPT_URL, $senderUrl); + curl_setopt($this->curl_handle, CURLOPT_HTTPHEADER, array( + 'Content-Type: ' . $contentType, + 'Content-Encoding: ' . $contentEncoding, + )); + curl_setopt($this->curl_handle, CURLOPT_VERBOSE, $verbose); + // TODO: Make this configurable + curl_setopt($this->curl_handle, CURLOPT_PROXY, false); + + curl_setopt($this->curl_handle, CURLOPT_POST, true); + curl_setopt($this->curl_handle, CURLOPT_HEADER, true); + curl_setopt($this->curl_handle, CURLOPT_TRANSFERTEXT, false); + curl_setopt($this->curl_handle, CURLOPT_RETURNTRANSFER, true); + + } + + /** + * Set a cookie for the connection + * + * @param string $name The name of the cookie + * @param string $value The value of the cookie + */ + public function setCookie($name, $value) + { + if ($value === null) { + unset($this->cookies[$name]); + } else { + $this->cookies[$name] = $value; + } + } + + /** + * Get the value of a cookie + * + * @param string $name The name of the cookie to get + * @return string The value of the cookie, or null if the cookie is + * not found + */ + public function getCookie($name) + { + if (array_key_exists($name, $this->cookies)) { + return $this->cookies[$name]; + } + + return null; + } + + /** + * Get all the cookies for CURLOPT_COOKIE + * + * @return string All the cookies in the form "name=value; name=value" + */ + private function getCookies() + { + $ret = array(); + foreach ($this->cookies as $name => $value) { + $ret[] = urlencode($name) . '=' . urlencode($value); + } + + return implode(';', $ret); + } + + /** + * Send a JSON-RPC request to the server, and returns the result + * + * @param string $method The RPC method name + * @param array $data The post data + * @return mixed The JSON data returned by the server + * @throws RuntimeException Upon a HTTP (CURL) error + * @throws RuntimeException Upon an invalid HTTP response + * @throws RuntimeException Upon a JSON response containing an error + * @throws RuntimeException Upon an invalid JSON response + */ + private function jsonRequest($method, $data) + { + // TODO: Use JMSSerializer maybe? + $postData = json_encode(array( + 'jsonrpc' => '1.0', + 'id' => $method . '-' . uniqid(), + 'method' => $method, + 'params' => $data, + )); + curl_setopt($this->curl_handle, CURLOPT_POSTFIELDS, $postData); + curl_setopt($this->curl_handle, CURLOPT_COOKIE, $this->getCookies()); + $result = curl_exec($this->curl_handle); + + if ($result === false) { + throw new RuntimeException('CURL error: ' . curl_error($this->curl_handle)); + } + + $info = curl_getinfo($this->curl_handle); + if ($info['http_code'] != 200) { + throw new RuntimeException('Bad status code received (' . $info['http_code'] . ')!'); + } + + $m = array(); + if (!preg_match('/(.*?)\r\n\r\n(.*)/s', $result, $m)) { + throw new RuntimeException('Invalid HTTP response!'); + } + list($all, $headers, $body) = $m; + + $matches = array(); + preg_match_all('/Set-Cookie: ([^=]+)=(.*);/U', $headers, $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $this->setCookie($match[1], $match[2]); + } + + // TODO: use JMSSerializer maybe? + $resultObj = json_decode($body, true); + if (!is_array($resultObj)) { + throw new RuntimeException('Result is not a JSON response!'); + } elseif (array_key_exists('error', $resultObj) && ($resultObj['error'] !== null)) { + throw new RuntimeException('Result has an error: ' . $resultObj['error']); + } elseif (!array_key_exists('result', $resultObj)) { + throw new RuntimeException('Result has no "result" field'); + } + + return $resultObj['result']; + } + + public function login($username, $password) + { + try { + $this->token = $this->jsonRequest('login', array($username, $password)); + } catch (RuntimeException $e) { + $this->token = null; + } + return ($this->token !== null); + } + + public function sendMessage($recipient, $message, array $passwordLocations) + { + if ($this->token === null) { + return false; + } + + if ($passwordLocations === null) { + $passwordLocations = array(); + } + + $this->jsonRequest('send', array($this->token, $recipient, $message, $passwordLocations)); + + return true; + } + + public function logout() + { + $this->jsonRequest('logout', array($this->token)); + + return true; + } }