203 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			203 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
namespace GergelyPolonkai\SmsSender;
 | 
						|
 | 
						|
use RuntimeException;
 | 
						|
 | 
						|
class Sender
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * The internal libCURL handle
 | 
						|
     *
 | 
						|
     * @var resource $curl_handle
 | 
						|
     */
 | 
						|
    private $curl_handle;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The Cookie Jar
 | 
						|
     *
 | 
						|
     * @var array $cookies
 | 
						|
     */
 | 
						|
    private $cookies;
 | 
						|
 | 
						|
    /**
 | 
						|
     * The authentication token received from the server during login
 | 
						|
     *
 | 
						|
     * @var string $token
 | 
						|
     */
 | 
						|
    private $token;
 | 
						|
 | 
						|
    /**
 | 
						|
     * Constructor
 | 
						|
     *
 | 
						|
     * @param string  $senderUrl
 | 
						|
     * @param string  $contentType
 | 
						|
     * @param string  $contentEncoding
 | 
						|
     * @param boolean $verifySsl
 | 
						|
     * @param boolean $verbose
 | 
						|
     */
 | 
						|
    public function __construct($senderUrl, $contentType = 'application/json', $contentEncoding = 'utf-8', $verifySsl = false, $verbose = false)
 | 
						|
    {
 | 
						|
        /*
 | 
						|
         * Set up internal variables
 | 
						|
         */
 | 
						|
        $this->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;
 | 
						|
    }
 | 
						|
}
 |