Completed
Push — master ( 701151...0cad11 )
by Günter
01:43
created

HTTPClient   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 189
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 4

Importance

Changes 0
Metric Value
wmc 26
lcom 2
cbo 4
dl 0
loc 189
rs 10
c 0
b 0
f 0

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 13 2
A prepareCookieJar() 0 17 4
A __destruct() 0 4 1
A setupCurl() 0 15 3
A setupCurlOpts() 0 19 1
A setupCurlSSL() 0 18 5
A connect() 0 13 1
A close() 0 11 2
A send() 0 7 1
A request() 0 18 3
A log() 0 6 2
A active() 0 4 1
1
<?php
2
3
namespace AfriCC\EPP;
4
5
use AfriCC\EPP\Frame\Command\Logout as LogoutCommand;
6
use AfriCC\EPP\Frame\ResponseFactory;
7
8
/**
9
 * A high level HTTP(S) based client for the Extensible Provisioning Protocol (EPP)
10
 *
11
 * @see http://tools.ietf.org/html/rfc5734
12
 *
13
 * As this class deals directly with cURL it's untestable
14
 * @codeCoverageIgnore
15
 */
16
class HTTPClient extends AbstractClient implements ClientInterface
17
{
18
    protected $curl;
19
    protected $cookiejar;
20
21
    public function __construct(array $config)
22
    {
23
        parent::__construct($config);
24
25
        $proto = \parse_url($this->host, PHP_URL_SCHEME);
26
        if ($proto == 'https') {
27
            $this->ssl = true;
28
        } else {
29
            $this->ssl = false;
30
        }
31
32
        $this->prepareCookieJar($config);
33
    }
34
35
    protected function prepareCookieJar(array $config)
36
    {
37
        if (!empty($config['cookiejar'])) {
38
            $this->cookiejar = $config['cookiejar'];
39
        } else {
40
            $this->cookiejar = tempnam(sys_get_temp_dir(), 'ehc');
41
        }
42
43
        if (!is_readable($this->cookiejar) || !is_writable($this->cookiejar)) {
44
            throw new \Exception(
45
                sprintf(
46
                    'unable to read/write cookiejar: %s',
47
                    $this->cookiejar
48
                    )
49
                );
50
        }
51
    }
52
53
    public function __destruct()
54
    {
55
        $this->close();
56
    }
57
58
    private function setupCurl()
59
    {
60
        $this->curl = curl_init($this->host);
61
62
        if ($this->curl === false) {
63
            throw new \Exception('Cannot initialize cURL extension');
64
        }
65
66
        $this->setupCurlOpts();
67
68
        // certs
69
        if ($this->ssl) {
70
            $this->setupCurlSSL();
71
        }
72
    }
73
74
    private function setupCurlOpts()
75
    {
76
        // set stream time out
77
        curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
78
        curl_setopt(
79
            $this->curl,
80
            CURLOPT_CONNECTTIMEOUT,
81
            $this->connect_timeout
82
            );
83
84
        // set necessary options
85
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
86
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true);
87
        curl_setopt($this->curl, CURLOPT_HEADER, false);
88
89
        // cookies
90
        curl_setopt($this->curl, CURLOPT_COOKIEFILE, $this->cookiejar);
91
        curl_setopt($this->curl, CURLOPT_COOKIEJAR, $this->cookiejar);
92
    }
93
94
    private function setupCurlSSL()
95
    {
96
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, true);
97
        curl_setopt($this->curl, CURLOPT_SSLKEYTYPE, 'PEM');
98
99
        if ($this->ca_cert) {
100
            curl_setopt($this->curl, CURLOPT_CAINFO, $this->ca_cert);
101
        }
102
        if ($this->pk_cert) {
103
            curl_setopt($this->curl, CURLOPT_SSLKEY, $this->pk_cert);
104
        }
105
        if ($this->local_cert) {
106
            curl_setopt($this->curl, CURLOPT_SSLCERT, $this->local_cert);
107
        }
108
        if ($this->passphrase) {
109
            curl_setopt($this->curl, CURLOPT_SSLCERTPASSWD, $this->passphrase);
110
        }
111
    }
112
113
    /**
114
     * Open a new connection to the EPP server
115
     *
116
     * @param bool|string $newPassword String with new password to set upon login, false if no password
117
     */
118
    public function connect($newPassword = false)
119
    {
120
        $this->setupCurl();
121
122
        // get greeting
123
        $greeting = $this->request(new \AfriCC\EPP\Frame\Hello());
124
125
        // login
126
        $this->login($newPassword);
127
128
        // return greeting
129
        return $greeting;
130
    }
131
132
    /**
133
     * Closes a previously opened EPP connection
134
     */
135
    public function close()
136
    {
137
        if ($this->active()) {
138
            // send logout frame
139
            $this->request(new LogoutCommand());
140
141
            return curl_close($this->curl);
142
        }
143
144
        return false;
145
    }
146
147
    /**
148
     * sends a XML-based frame to the server
149
     *
150
     * @param FrameInterface $frame the frame to send to the server
151
     *
152
     * @return string
153
     */
154
    public function send(FrameInterface $frame)
155
    {
156
        $content = (string) $frame;
157
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $content);
158
159
        return curl_exec($this->curl);
160
    }
161
162
    /**
163
     * request via EPP
164
     *
165
     * @param FrameInterface $frame Request frame to server
166
     *
167
     * @return string|\AfriCC\EPP\Frame\Response\MessageQueue|\AfriCC\EPP\Frame\Response Response from server
168
     */
169
    public function request(FrameInterface $frame)
170
    {
171
        if ($frame instanceof TransactionAwareInterface) {
172
            $frame->setClientTransactionId(
173
                $this->generateClientTransactionId()
174
                );
175
        }
176
177
        $return = $this->send($frame);
178
179
        if ($return === false) {
180
            $code = curl_errno($this->curl);
181
            $msg = curl_error($this->curl);
182
            throw new \Exception($msg, $code);
183
        }
184
185
        return ResponseFactory::build($return);
186
    }
187
188
    protected function log($message)
189
    {
190
        if ($this->debug) {
191
            \error_log($message);
192
        }
193
    }
194
195
    /**
196
     * Check if curl session is still active
197
     *
198
     * @return bool
199
     */
200
    private function active()
201
    {
202
        return is_resource($this->curl);
203
    }
204
}
205