1<?php
2
3namespace dokuwiki\plugin\letsencrypt\classes;
4
5require_once __DIR__ . '/../Lescript.php';
6
7class Client implements \Analogic\ACME\ClientInterface {
8
9    protected $base;
10
11    protected $http;
12
13    /**
14     * Constructor
15     *
16     * @param string $base the ACME API base all relative requests are sent to
17     */
18    public function __construct($base) {
19        $this->base = $base;
20        $this->http = new \DokuHTTPClient();
21        $this->http->keep_alive = false; // SSL seems to break after several requests
22    }
23
24    /**
25     * Send a POST request
26     *
27     * @param string $url URL to post to
28     * @param array $fields fields to sent via post
29     * @return array|string the parsed JSON response, raw response on error
30     */
31    public function post($url, $fields) {
32        if(!preg_match('/^https?:\/\//', $url)) $url = $this->base . $url;
33        $this->http->headers['Content-Type'] = 'application/json';
34        $response = $this->http->post($url, $fields);
35        if($response === false) $response = $this->http->resp_body;
36        $data = json_decode($response, true);
37        return $data === null ? $response : $data;
38    }
39
40    /**
41     * @param string $url URL to request via get
42     * @return array|string the parsed JSON response, raw response on error
43     */
44    public function get($url) {
45        if(!preg_match('/^https?:\/\//', $url)) $url = $this->base . $url;
46        $response = $this->http->get($url);
47        if($response === false) $response = $this->http->resp_body;
48        $data = json_decode($response, true);
49        return $data === null ? $response : $data;
50    }
51
52    /**
53     * Returns the Replay-Nonce header of the last request
54     *
55     * if no request has been made, yet. A GET on $base/directory is done and the
56     * resulting nonce returned
57     *
58     * @return string
59     * @throws Exception
60     */
61    public function getLastNonce() {
62        if(isset($this->http->resp_headers['replay-nonce'])) {
63            return $this->http->resp_headers['replay-nonce'];
64        } else {
65            $result = $this->get('/directory');
66            if(!$result) throw new Exception('Failed to get nonce');
67            return $this->getLastNonce();
68        }
69
70    }
71
72    /**
73     * Return the Location header of the last request
74     *
75     * returns null if last request had no location header
76     *
77     * @return string|null
78     */
79    public function getLastLocation() {
80        if(isset($this->http->resp_headers['location'])) {
81            return $this->http->resp_headers['location'];
82        } else {
83            return null;
84        }
85    }
86
87    /**
88     * Return the HTTP status code of the last request
89     *
90     * @return int
91     */
92    public function getLastCode() {
93        return (int) $this->http->status;
94    }
95
96    /**
97     * Get all Link headers of the last request
98     *
99     * @return string[]
100     */
101    public function getLastLinks() {
102        if(preg_match('~<(.+)>;rel="up"~', $this->http->resp_headers['link'], $matches)) {
103            return array($matches[1]);
104        }
105        return array();
106    }
107}
108