xref: /plugin/davcal/vendor/sabre/http/lib/Message.php (revision a1a3b6794e0e143a4a8b51d3185ce2d339be61ab)
1*a1a3b679SAndreas Boehler<?php
2*a1a3b679SAndreas Boehler
3*a1a3b679SAndreas Boehlernamespace Sabre\HTTP;
4*a1a3b679SAndreas Boehler
5*a1a3b679SAndreas Boehler/**
6*a1a3b679SAndreas Boehler * This is the abstract base class for both the Request and Response objects.
7*a1a3b679SAndreas Boehler *
8*a1a3b679SAndreas Boehler * This object contains a few simple methods that are shared by both.
9*a1a3b679SAndreas Boehler *
10*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2009-2015 fruux GmbH (https://fruux.com/).
11*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/)
12*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License
13*a1a3b679SAndreas Boehler */
14*a1a3b679SAndreas Boehlerabstract class Message implements MessageInterface {
15*a1a3b679SAndreas Boehler
16*a1a3b679SAndreas Boehler    /**
17*a1a3b679SAndreas Boehler     * Request body
18*a1a3b679SAndreas Boehler     *
19*a1a3b679SAndreas Boehler     * This should be a stream resource
20*a1a3b679SAndreas Boehler     *
21*a1a3b679SAndreas Boehler     * @var resource
22*a1a3b679SAndreas Boehler     */
23*a1a3b679SAndreas Boehler    protected $body;
24*a1a3b679SAndreas Boehler
25*a1a3b679SAndreas Boehler    /**
26*a1a3b679SAndreas Boehler     * Contains the list of HTTP headers
27*a1a3b679SAndreas Boehler     *
28*a1a3b679SAndreas Boehler     * @var array
29*a1a3b679SAndreas Boehler     */
30*a1a3b679SAndreas Boehler    protected $headers = [];
31*a1a3b679SAndreas Boehler
32*a1a3b679SAndreas Boehler    /**
33*a1a3b679SAndreas Boehler     * HTTP message version (1.0 or 1.1)
34*a1a3b679SAndreas Boehler     *
35*a1a3b679SAndreas Boehler     * @var string
36*a1a3b679SAndreas Boehler     */
37*a1a3b679SAndreas Boehler    protected $httpVersion = '1.1';
38*a1a3b679SAndreas Boehler
39*a1a3b679SAndreas Boehler    /**
40*a1a3b679SAndreas Boehler     * Returns the body as a readable stream resource.
41*a1a3b679SAndreas Boehler     *
42*a1a3b679SAndreas Boehler     * Note that the stream may not be rewindable, and therefore may only be
43*a1a3b679SAndreas Boehler     * read once.
44*a1a3b679SAndreas Boehler     *
45*a1a3b679SAndreas Boehler     * @return resource
46*a1a3b679SAndreas Boehler     */
47*a1a3b679SAndreas Boehler    function getBodyAsStream() {
48*a1a3b679SAndreas Boehler
49*a1a3b679SAndreas Boehler        $body = $this->getBody();
50*a1a3b679SAndreas Boehler        if (is_string($body) || is_null($body)) {
51*a1a3b679SAndreas Boehler            $stream = fopen('php://temp', 'r+');
52*a1a3b679SAndreas Boehler            fwrite($stream, $body);
53*a1a3b679SAndreas Boehler            rewind($stream);
54*a1a3b679SAndreas Boehler            return $stream;
55*a1a3b679SAndreas Boehler        }
56*a1a3b679SAndreas Boehler        return $body;
57*a1a3b679SAndreas Boehler
58*a1a3b679SAndreas Boehler    }
59*a1a3b679SAndreas Boehler
60*a1a3b679SAndreas Boehler    /**
61*a1a3b679SAndreas Boehler     * Returns the body as a string.
62*a1a3b679SAndreas Boehler     *
63*a1a3b679SAndreas Boehler     * Note that because the underlying data may be based on a stream, this
64*a1a3b679SAndreas Boehler     * method could only work correctly the first time.
65*a1a3b679SAndreas Boehler     *
66*a1a3b679SAndreas Boehler     * @return string
67*a1a3b679SAndreas Boehler     */
68*a1a3b679SAndreas Boehler    function getBodyAsString() {
69*a1a3b679SAndreas Boehler
70*a1a3b679SAndreas Boehler        $body = $this->getBody();
71*a1a3b679SAndreas Boehler        if (is_string($body)) {
72*a1a3b679SAndreas Boehler            return $body;
73*a1a3b679SAndreas Boehler        }
74*a1a3b679SAndreas Boehler        if (is_null($body)) {
75*a1a3b679SAndreas Boehler            return '';
76*a1a3b679SAndreas Boehler        }
77*a1a3b679SAndreas Boehler        return stream_get_contents($body);
78*a1a3b679SAndreas Boehler
79*a1a3b679SAndreas Boehler    }
80*a1a3b679SAndreas Boehler
81*a1a3b679SAndreas Boehler    /**
82*a1a3b679SAndreas Boehler     * Returns the message body, as it's internal representation.
83*a1a3b679SAndreas Boehler     *
84*a1a3b679SAndreas Boehler     * This could be either a string or a stream.
85*a1a3b679SAndreas Boehler     *
86*a1a3b679SAndreas Boehler     * @return resource|string
87*a1a3b679SAndreas Boehler     */
88*a1a3b679SAndreas Boehler    function getBody() {
89*a1a3b679SAndreas Boehler
90*a1a3b679SAndreas Boehler        return $this->body;
91*a1a3b679SAndreas Boehler
92*a1a3b679SAndreas Boehler    }
93*a1a3b679SAndreas Boehler
94*a1a3b679SAndreas Boehler    /**
95*a1a3b679SAndreas Boehler     * Replaces the body resource with a new stream or string.
96*a1a3b679SAndreas Boehler     *
97*a1a3b679SAndreas Boehler     * @param resource|string $body
98*a1a3b679SAndreas Boehler     */
99*a1a3b679SAndreas Boehler    function setBody($body) {
100*a1a3b679SAndreas Boehler
101*a1a3b679SAndreas Boehler        $this->body = $body;
102*a1a3b679SAndreas Boehler
103*a1a3b679SAndreas Boehler    }
104*a1a3b679SAndreas Boehler
105*a1a3b679SAndreas Boehler    /**
106*a1a3b679SAndreas Boehler     * Returns all the HTTP headers as an array.
107*a1a3b679SAndreas Boehler     *
108*a1a3b679SAndreas Boehler     * Every header is returned as an array, with one or more values.
109*a1a3b679SAndreas Boehler     *
110*a1a3b679SAndreas Boehler     * @return array
111*a1a3b679SAndreas Boehler     */
112*a1a3b679SAndreas Boehler    function getHeaders() {
113*a1a3b679SAndreas Boehler
114*a1a3b679SAndreas Boehler        $result = [];
115*a1a3b679SAndreas Boehler        foreach ($this->headers as $headerInfo) {
116*a1a3b679SAndreas Boehler            $result[$headerInfo[0]] = $headerInfo[1];
117*a1a3b679SAndreas Boehler        }
118*a1a3b679SAndreas Boehler        return $result;
119*a1a3b679SAndreas Boehler
120*a1a3b679SAndreas Boehler    }
121*a1a3b679SAndreas Boehler
122*a1a3b679SAndreas Boehler    /**
123*a1a3b679SAndreas Boehler     * Will return true or false, depending on if a HTTP header exists.
124*a1a3b679SAndreas Boehler     *
125*a1a3b679SAndreas Boehler     * @param string $name
126*a1a3b679SAndreas Boehler     * @return bool
127*a1a3b679SAndreas Boehler     */
128*a1a3b679SAndreas Boehler    function hasHeader($name) {
129*a1a3b679SAndreas Boehler
130*a1a3b679SAndreas Boehler        return isset($this->headers[strtolower($name)]);
131*a1a3b679SAndreas Boehler
132*a1a3b679SAndreas Boehler    }
133*a1a3b679SAndreas Boehler
134*a1a3b679SAndreas Boehler    /**
135*a1a3b679SAndreas Boehler     * Returns a specific HTTP header, based on it's name.
136*a1a3b679SAndreas Boehler     *
137*a1a3b679SAndreas Boehler     * The name must be treated as case-insensitive.
138*a1a3b679SAndreas Boehler     * If the header does not exist, this method must return null.
139*a1a3b679SAndreas Boehler     *
140*a1a3b679SAndreas Boehler     * If a header appeared more than once in a HTTP request, this method will
141*a1a3b679SAndreas Boehler     * concatenate all the values with a comma.
142*a1a3b679SAndreas Boehler     *
143*a1a3b679SAndreas Boehler     * Note that this not make sense for all headers. Some, such as
144*a1a3b679SAndreas Boehler     * `Set-Cookie` cannot be logically combined with a comma. In those cases
145*a1a3b679SAndreas Boehler     * you *should* use getHeaderAsArray().
146*a1a3b679SAndreas Boehler     *
147*a1a3b679SAndreas Boehler     * @param string $name
148*a1a3b679SAndreas Boehler     * @return string|null
149*a1a3b679SAndreas Boehler     */
150*a1a3b679SAndreas Boehler    function getHeader($name) {
151*a1a3b679SAndreas Boehler
152*a1a3b679SAndreas Boehler        $name = strtolower($name);
153*a1a3b679SAndreas Boehler
154*a1a3b679SAndreas Boehler        if (isset($this->headers[$name])) {
155*a1a3b679SAndreas Boehler            return implode(',', $this->headers[$name][1]);
156*a1a3b679SAndreas Boehler        }
157*a1a3b679SAndreas Boehler        return null;
158*a1a3b679SAndreas Boehler
159*a1a3b679SAndreas Boehler    }
160*a1a3b679SAndreas Boehler
161*a1a3b679SAndreas Boehler    /**
162*a1a3b679SAndreas Boehler     * Returns a HTTP header as an array.
163*a1a3b679SAndreas Boehler     *
164*a1a3b679SAndreas Boehler     * For every time the HTTP header appeared in the request or response, an
165*a1a3b679SAndreas Boehler     * item will appear in the array.
166*a1a3b679SAndreas Boehler     *
167*a1a3b679SAndreas Boehler     * If the header did not exists, this method will return an empty array.
168*a1a3b679SAndreas Boehler     *
169*a1a3b679SAndreas Boehler     * @param string $name
170*a1a3b679SAndreas Boehler     * @return string[]
171*a1a3b679SAndreas Boehler     */
172*a1a3b679SAndreas Boehler    function getHeaderAsArray($name) {
173*a1a3b679SAndreas Boehler
174*a1a3b679SAndreas Boehler        $name = strtolower($name);
175*a1a3b679SAndreas Boehler
176*a1a3b679SAndreas Boehler        if (isset($this->headers[$name])) {
177*a1a3b679SAndreas Boehler            return $this->headers[$name][1];
178*a1a3b679SAndreas Boehler        }
179*a1a3b679SAndreas Boehler
180*a1a3b679SAndreas Boehler        return [];
181*a1a3b679SAndreas Boehler
182*a1a3b679SAndreas Boehler    }
183*a1a3b679SAndreas Boehler
184*a1a3b679SAndreas Boehler    /**
185*a1a3b679SAndreas Boehler     * Updates a HTTP header.
186*a1a3b679SAndreas Boehler     *
187*a1a3b679SAndreas Boehler     * The case-sensitity of the name value must be retained as-is.
188*a1a3b679SAndreas Boehler     *
189*a1a3b679SAndreas Boehler     * If the header already existed, it will be overwritten.
190*a1a3b679SAndreas Boehler     *
191*a1a3b679SAndreas Boehler     * @param string $name
192*a1a3b679SAndreas Boehler     * @param string|string[] $value
193*a1a3b679SAndreas Boehler     * @return void
194*a1a3b679SAndreas Boehler     */
195*a1a3b679SAndreas Boehler    function setHeader($name, $value) {
196*a1a3b679SAndreas Boehler
197*a1a3b679SAndreas Boehler        $this->headers[strtolower($name)] = [$name, (array)$value];
198*a1a3b679SAndreas Boehler
199*a1a3b679SAndreas Boehler    }
200*a1a3b679SAndreas Boehler
201*a1a3b679SAndreas Boehler    /**
202*a1a3b679SAndreas Boehler     * Sets a new set of HTTP headers.
203*a1a3b679SAndreas Boehler     *
204*a1a3b679SAndreas Boehler     * The headers array should contain headernames for keys, and their value
205*a1a3b679SAndreas Boehler     * should be specified as either a string or an array.
206*a1a3b679SAndreas Boehler     *
207*a1a3b679SAndreas Boehler     * Any header that already existed will be overwritten.
208*a1a3b679SAndreas Boehler     *
209*a1a3b679SAndreas Boehler     * @param array $headers
210*a1a3b679SAndreas Boehler     * @return void
211*a1a3b679SAndreas Boehler     */
212*a1a3b679SAndreas Boehler    function setHeaders(array $headers) {
213*a1a3b679SAndreas Boehler
214*a1a3b679SAndreas Boehler        foreach ($headers as $name => $value) {
215*a1a3b679SAndreas Boehler            $this->setHeader($name, $value);
216*a1a3b679SAndreas Boehler        }
217*a1a3b679SAndreas Boehler
218*a1a3b679SAndreas Boehler    }
219*a1a3b679SAndreas Boehler
220*a1a3b679SAndreas Boehler    /**
221*a1a3b679SAndreas Boehler     * Adds a HTTP header.
222*a1a3b679SAndreas Boehler     *
223*a1a3b679SAndreas Boehler     * This method will not overwrite any existing HTTP header, but instead add
224*a1a3b679SAndreas Boehler     * another value. Individual values can be retrieved with
225*a1a3b679SAndreas Boehler     * getHeadersAsArray.
226*a1a3b679SAndreas Boehler     *
227*a1a3b679SAndreas Boehler     * @param string $name
228*a1a3b679SAndreas Boehler     * @param string $value
229*a1a3b679SAndreas Boehler     * @return void
230*a1a3b679SAndreas Boehler     */
231*a1a3b679SAndreas Boehler    function addHeader($name, $value) {
232*a1a3b679SAndreas Boehler
233*a1a3b679SAndreas Boehler        $lName = strtolower($name);
234*a1a3b679SAndreas Boehler        if (isset($this->headers[$lName])) {
235*a1a3b679SAndreas Boehler            $this->headers[$lName][1] = array_merge(
236*a1a3b679SAndreas Boehler                $this->headers[$lName][1],
237*a1a3b679SAndreas Boehler                (array)$value
238*a1a3b679SAndreas Boehler            );
239*a1a3b679SAndreas Boehler        } else {
240*a1a3b679SAndreas Boehler            $this->headers[$lName] = [
241*a1a3b679SAndreas Boehler                $name,
242*a1a3b679SAndreas Boehler                (array)$value
243*a1a3b679SAndreas Boehler            ];
244*a1a3b679SAndreas Boehler        }
245*a1a3b679SAndreas Boehler
246*a1a3b679SAndreas Boehler    }
247*a1a3b679SAndreas Boehler
248*a1a3b679SAndreas Boehler    /**
249*a1a3b679SAndreas Boehler     * Adds a new set of HTTP headers.
250*a1a3b679SAndreas Boehler     *
251*a1a3b679SAndreas Boehler     * Any existing headers will not be overwritten.
252*a1a3b679SAndreas Boehler     *
253*a1a3b679SAndreas Boehler     * @param array $headers
254*a1a3b679SAndreas Boehler     * @return void
255*a1a3b679SAndreas Boehler     */
256*a1a3b679SAndreas Boehler    function addHeaders(array $headers) {
257*a1a3b679SAndreas Boehler
258*a1a3b679SAndreas Boehler        foreach ($headers as $name => $value) {
259*a1a3b679SAndreas Boehler            $this->addHeader($name, $value);
260*a1a3b679SAndreas Boehler        }
261*a1a3b679SAndreas Boehler
262*a1a3b679SAndreas Boehler    }
263*a1a3b679SAndreas Boehler
264*a1a3b679SAndreas Boehler
265*a1a3b679SAndreas Boehler    /**
266*a1a3b679SAndreas Boehler     * Removes a HTTP header.
267*a1a3b679SAndreas Boehler     *
268*a1a3b679SAndreas Boehler     * The specified header name must be treated as case-insenstive.
269*a1a3b679SAndreas Boehler     * This method should return true if the header was successfully deleted,
270*a1a3b679SAndreas Boehler     * and false if the header did not exist.
271*a1a3b679SAndreas Boehler     *
272*a1a3b679SAndreas Boehler     * @return bool
273*a1a3b679SAndreas Boehler     */
274*a1a3b679SAndreas Boehler    function removeHeader($name) {
275*a1a3b679SAndreas Boehler
276*a1a3b679SAndreas Boehler        $name = strtolower($name);
277*a1a3b679SAndreas Boehler        if (!isset($this->headers[$name])) {
278*a1a3b679SAndreas Boehler            return false;
279*a1a3b679SAndreas Boehler        }
280*a1a3b679SAndreas Boehler        unset($this->headers[$name]);
281*a1a3b679SAndreas Boehler        return true;
282*a1a3b679SAndreas Boehler
283*a1a3b679SAndreas Boehler    }
284*a1a3b679SAndreas Boehler
285*a1a3b679SAndreas Boehler    /**
286*a1a3b679SAndreas Boehler     * Sets the HTTP version.
287*a1a3b679SAndreas Boehler     *
288*a1a3b679SAndreas Boehler     * Should be 1.0 or 1.1.
289*a1a3b679SAndreas Boehler     *
290*a1a3b679SAndreas Boehler     * @param string $version
291*a1a3b679SAndreas Boehler     * @return void
292*a1a3b679SAndreas Boehler     */
293*a1a3b679SAndreas Boehler    function setHttpVersion($version) {
294*a1a3b679SAndreas Boehler
295*a1a3b679SAndreas Boehler        $this->httpVersion = $version;
296*a1a3b679SAndreas Boehler
297*a1a3b679SAndreas Boehler    }
298*a1a3b679SAndreas Boehler
299*a1a3b679SAndreas Boehler    /**
300*a1a3b679SAndreas Boehler     * Returns the HTTP version.
301*a1a3b679SAndreas Boehler     *
302*a1a3b679SAndreas Boehler     * @return string
303*a1a3b679SAndreas Boehler     */
304*a1a3b679SAndreas Boehler    function getHttpVersion() {
305*a1a3b679SAndreas Boehler
306*a1a3b679SAndreas Boehler        return $this->httpVersion;
307*a1a3b679SAndreas Boehler
308*a1a3b679SAndreas Boehler    }
309*a1a3b679SAndreas Boehler}
310