Completed
Pull Request — master (#64)
by
unknown
01:52
created

HTTPClient::__construct()   A

Complexity

Conditions 5
Paths 8

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 26
rs 9.1928
c 0
b 0
f 0
cc 5
nc 8
nop 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
        if (!empty($config['cookiejar'])) {
33
            $this->cookiejar = $config['cookiejar'];
34
        } else {
35
            $this->cookiejar = tempnam(sys_get_temp_dir(), 'ehc');
36
        }
37
38
        if (!is_readable($this->cookiejar) || !is_writable($this->cookiejar)) {
39
            throw new \Exception(
40
                sprintf(
41
                    'unable to read/write cookiejar: %s',
42
                    $this->cookiejar
43
                    )
44
                );
45
        }
46
    }
47
48
    public function __destruct()
49
    {
50
        $this->close();
51
    }
52
53
    private function setupCurl()
54
    {
55
        $this->curl = curl_init($this->host);
56
57
        if ($this->curl === false) {
58
            throw new \Exception('Cannot initialize cURL extension');
59
        }
60
61
        $this->setupCurlOpts();
62
63
        // certs
64
        if ($this->ssl) {
65
            $this->setupCurlSSL();
66
        }
67
    }
68
69
    private function setupCurlOpts()
70
    {
71
        // set stream time out
72
        curl_setopt($this->curl, CURLOPT_TIMEOUT, $this->timeout);
73
        curl_setopt(
74
            $this->curl,
75
            CURLOPT_CONNECTTIMEOUT,
76
            $this->connect_timeout
77
            );
78
79
        // set necessary options
80
        curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
81
        curl_setopt($this->curl, CURLOPT_FOLLOWLOCATION, true);
82
        curl_setopt($this->curl, CURLOPT_HEADER, false);
83
84
        // cookies
85
        curl_setopt($this->curl, CURLOPT_COOKIEFILE, $this->cookiejar);
86
        curl_setopt($this->curl, CURLOPT_COOKIEJAR, $this->cookiejar);
87
    }
88
89
    private function setupCurlSSL()
90
    {
91
        curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, true);
92
        curl_setopt($this->curl, CURLOPT_SSLKEYTYPE, 'PEM');
93
94
        if ($this->ca_cert) {
95
            curl_setopt($this->curl, CURLOPT_CAINFO, $this->ca_cert);
96
        }
97
        if ($this->pk_cert) {
98
            curl_setopt($this->curl, CURLOPT_SSLKEY, $this->pk_cert);
99
        }
100
        if ($this->local_cert) {
101
            curl_setopt($this->curl, CURLOPT_SSLCERT, $this->local_cert);
102
        }
103
        if ($this->passphrase) {
104
            curl_setopt($this->curl, CURLOPT_SSLCERTPASSWD, $this->passphrase);
105
        }
106
    }
107
108
    /**
109
     * Open a new connection to the EPP server
110
     *
111
     * @param bool|string $newPassword String with new password to set upon login, false if no password
112
     */
113
    public function connect($newPassword = false)
114
    {
115
        $this->setupCurl();
116
117
        // get greeting
118
        $greeting = $this->request(new \AfriCC\EPP\Frame\Hello());
119
120
        // login
121
        $this->login($newPassword);
122
123
        // return greeting
124
        return $greeting;
125
    }
126
127
    /**
128
     * Closes a previously opened EPP connection
129
     */
130
    public function close()
131
    {
132
        if ($this->active()) {
133
            // send logout frame
134
            $this->request(new LogoutCommand());
135
136
            return curl_close($this->curl);
137
        }
138
139
        return false;
140
    }
141
142
    /**
143
     * sends a XML-based frame to the server
144
     *
145
     * @param FrameInterface $frame the frame to send to the server
146
     *
147
     * @return string
148
     */
149
    public function send(FrameInterface $frame)
150
    {
151
        $content = (string) $frame;
152
        curl_setopt($this->curl, CURLOPT_POSTFIELDS, $content);
153
154
        return curl_exec($this->curl);
155
    }
156
157
    /**
158
     * request via EPP
159
     *
160
     * @param FrameInterface $frame Request frame to server
161
     *
162
     * @return string|\AfriCC\EPP\Frame\Response\MessageQueue|\AfriCC\EPP\Frame\Response Response from server
163
     */
164
    public function request(FrameInterface $frame)
165
    {
166
        if ($frame instanceof TransactionAwareInterface) {
167
            $frame->setClientTransactionId(
168
                $this->generateClientTransactionId()
169
                );
170
        }
171
172
        $return = $this->send($frame);
173
174
        if ($return === false) {
175
            $code = curl_errno($this->curl);
176
            $msg = curl_error($this->curl);
177
            throw new \Exception($msg, $code);
178
        }
179
180
        return ResponseFactory::build($return);
181
    }
182
183
    protected function log($message)
184
    {
185
        if ($this->debug) {
186
            \error_log($message);
187
        }
188
    }
189
190
    /**
191
     * Check if curl session is still active
192
     *
193
     * @return bool
194
     */
195
    private function active()
196
    {
197
        return is_resource($this->curl);
198
    }
199
}
200