xref: /plugin/davcal/vendor/sabre/http/lib/Sapi.php (revision a1a3b6794e0e143a4a8b51d3185ce2d339be61ab)
1*a1a3b679SAndreas Boehler<?php
2*a1a3b679SAndreas Boehler
3*a1a3b679SAndreas Boehlernamespace Sabre\HTTP;
4*a1a3b679SAndreas Boehler
5*a1a3b679SAndreas Boehler/**
6*a1a3b679SAndreas Boehler * PHP SAPI
7*a1a3b679SAndreas Boehler *
8*a1a3b679SAndreas Boehler * This object is responsible for:
9*a1a3b679SAndreas Boehler * 1. Constructing a Request object based on the current HTTP request sent to
10*a1a3b679SAndreas Boehler *    the PHP process.
11*a1a3b679SAndreas Boehler * 2. Sending the Response object back to the client.
12*a1a3b679SAndreas Boehler *
13*a1a3b679SAndreas Boehler * It could be said that this class provides a mapping between the Request and
14*a1a3b679SAndreas Boehler * Response objects, and php's:
15*a1a3b679SAndreas Boehler *
16*a1a3b679SAndreas Boehler * * $_SERVER
17*a1a3b679SAndreas Boehler * * $_POST
18*a1a3b679SAndreas Boehler * * $_FILES
19*a1a3b679SAndreas Boehler * * php://input
20*a1a3b679SAndreas Boehler * * echo()
21*a1a3b679SAndreas Boehler * * header()
22*a1a3b679SAndreas Boehler * * php://output
23*a1a3b679SAndreas Boehler *
24*a1a3b679SAndreas Boehler * You can choose to either call all these methods statically, but you can also
25*a1a3b679SAndreas Boehler * instantiate this as an object to allow for polymorhpism.
26*a1a3b679SAndreas Boehler *
27*a1a3b679SAndreas Boehler * @copyright Copyright (C) 2009-2015 fruux GmbH (https://fruux.com/).
28*a1a3b679SAndreas Boehler * @author Evert Pot (http://evertpot.com/)
29*a1a3b679SAndreas Boehler * @license http://sabre.io/license/ Modified BSD License
30*a1a3b679SAndreas Boehler */
31*a1a3b679SAndreas Boehlerclass Sapi {
32*a1a3b679SAndreas Boehler
33*a1a3b679SAndreas Boehler    /**
34*a1a3b679SAndreas Boehler     * This static method will create a new Request object, based on the
35*a1a3b679SAndreas Boehler     * current PHP request.
36*a1a3b679SAndreas Boehler     *
37*a1a3b679SAndreas Boehler     * @return Request
38*a1a3b679SAndreas Boehler     */
39*a1a3b679SAndreas Boehler    static function getRequest() {
40*a1a3b679SAndreas Boehler
41*a1a3b679SAndreas Boehler        $r = self::createFromServerArray($_SERVER);
42*a1a3b679SAndreas Boehler        $r->setBody(fopen('php://input', 'r'));
43*a1a3b679SAndreas Boehler        $r->setPostData($_POST);
44*a1a3b679SAndreas Boehler        return $r;
45*a1a3b679SAndreas Boehler
46*a1a3b679SAndreas Boehler    }
47*a1a3b679SAndreas Boehler
48*a1a3b679SAndreas Boehler    /**
49*a1a3b679SAndreas Boehler     * Sends the HTTP response back to a HTTP client.
50*a1a3b679SAndreas Boehler     *
51*a1a3b679SAndreas Boehler     * This calls php's header() function and streams the body to php://output.
52*a1a3b679SAndreas Boehler     *
53*a1a3b679SAndreas Boehler     * @param ResponseInterface $response
54*a1a3b679SAndreas Boehler     * @return void
55*a1a3b679SAndreas Boehler     */
56*a1a3b679SAndreas Boehler    static function sendResponse(ResponseInterface $response) {
57*a1a3b679SAndreas Boehler
58*a1a3b679SAndreas Boehler        header('HTTP/' . $response->getHttpVersion() . ' ' . $response->getStatus() . ' ' . $response->getStatusText());
59*a1a3b679SAndreas Boehler        foreach ($response->getHeaders() as $key => $value) {
60*a1a3b679SAndreas Boehler
61*a1a3b679SAndreas Boehler            foreach ($value as $k => $v) {
62*a1a3b679SAndreas Boehler                if ($k === 0) {
63*a1a3b679SAndreas Boehler                    header($key . ': ' . $v);
64*a1a3b679SAndreas Boehler                } else {
65*a1a3b679SAndreas Boehler                    header($key . ': ' . $v, false);
66*a1a3b679SAndreas Boehler                }
67*a1a3b679SAndreas Boehler            }
68*a1a3b679SAndreas Boehler
69*a1a3b679SAndreas Boehler        }
70*a1a3b679SAndreas Boehler
71*a1a3b679SAndreas Boehler        $body = $response->getBody();
72*a1a3b679SAndreas Boehler        if (is_null($body)) return;
73*a1a3b679SAndreas Boehler
74*a1a3b679SAndreas Boehler        $contentLength = $response->getHeader('Content-Length');
75*a1a3b679SAndreas Boehler        if ($contentLength !== null) {
76*a1a3b679SAndreas Boehler            $output = fopen('php://output', 'wb');
77*a1a3b679SAndreas Boehler            if (is_resource($body) && get_resource_type($body) == 'stream') {
78*a1a3b679SAndreas Boehler                stream_copy_to_stream($body, $output, $contentLength);
79*a1a3b679SAndreas Boehler            } else {
80*a1a3b679SAndreas Boehler                fwrite($output, $body, $contentLength);
81*a1a3b679SAndreas Boehler            }
82*a1a3b679SAndreas Boehler        } else {
83*a1a3b679SAndreas Boehler            file_put_contents('php://output', $body);
84*a1a3b679SAndreas Boehler        }
85*a1a3b679SAndreas Boehler
86*a1a3b679SAndreas Boehler        if (is_resource($body)) {
87*a1a3b679SAndreas Boehler            fclose($body);
88*a1a3b679SAndreas Boehler        }
89*a1a3b679SAndreas Boehler
90*a1a3b679SAndreas Boehler    }
91*a1a3b679SAndreas Boehler
92*a1a3b679SAndreas Boehler    /**
93*a1a3b679SAndreas Boehler     * This static method will create a new Request object, based on a PHP
94*a1a3b679SAndreas Boehler     * $_SERVER array.
95*a1a3b679SAndreas Boehler     *
96*a1a3b679SAndreas Boehler     * @param array $serverArray
97*a1a3b679SAndreas Boehler     * @return Request
98*a1a3b679SAndreas Boehler     */
99*a1a3b679SAndreas Boehler    static function createFromServerArray(array $serverArray) {
100*a1a3b679SAndreas Boehler
101*a1a3b679SAndreas Boehler        $headers = [];
102*a1a3b679SAndreas Boehler        $method = null;
103*a1a3b679SAndreas Boehler        $url = null;
104*a1a3b679SAndreas Boehler        $httpVersion = '1.1';
105*a1a3b679SAndreas Boehler
106*a1a3b679SAndreas Boehler        $protocol = 'http';
107*a1a3b679SAndreas Boehler        $hostName = 'localhost';
108*a1a3b679SAndreas Boehler
109*a1a3b679SAndreas Boehler        foreach ($serverArray as $key => $value) {
110*a1a3b679SAndreas Boehler
111*a1a3b679SAndreas Boehler            switch ($key) {
112*a1a3b679SAndreas Boehler
113*a1a3b679SAndreas Boehler                case 'SERVER_PROTOCOL' :
114*a1a3b679SAndreas Boehler                    if ($value === 'HTTP/1.0') {
115*a1a3b679SAndreas Boehler                        $httpVersion = '1.0';
116*a1a3b679SAndreas Boehler                    }
117*a1a3b679SAndreas Boehler                    break;
118*a1a3b679SAndreas Boehler                case 'REQUEST_METHOD' :
119*a1a3b679SAndreas Boehler                    $method = $value;
120*a1a3b679SAndreas Boehler                    break;
121*a1a3b679SAndreas Boehler                case 'REQUEST_URI' :
122*a1a3b679SAndreas Boehler                    $url = $value;
123*a1a3b679SAndreas Boehler                    break;
124*a1a3b679SAndreas Boehler
125*a1a3b679SAndreas Boehler                // These sometimes should up without a HTTP_ prefix
126*a1a3b679SAndreas Boehler                case 'CONTENT_TYPE' :
127*a1a3b679SAndreas Boehler                    $headers['Content-Type'] = $value;
128*a1a3b679SAndreas Boehler                    break;
129*a1a3b679SAndreas Boehler                case 'CONTENT_LENGTH' :
130*a1a3b679SAndreas Boehler                    $headers['Content-Length'] = $value;
131*a1a3b679SAndreas Boehler                    break;
132*a1a3b679SAndreas Boehler
133*a1a3b679SAndreas Boehler                // mod_php on apache will put credentials in these variables.
134*a1a3b679SAndreas Boehler                // (fast)cgi does not usually do this, however.
135*a1a3b679SAndreas Boehler                case 'PHP_AUTH_USER' :
136*a1a3b679SAndreas Boehler                    if (isset($serverArray['PHP_AUTH_PW'])) {
137*a1a3b679SAndreas Boehler                        $headers['Authorization'] = 'Basic ' . base64_encode($value . ':' . $serverArray['PHP_AUTH_PW']);
138*a1a3b679SAndreas Boehler                    }
139*a1a3b679SAndreas Boehler                    break;
140*a1a3b679SAndreas Boehler
141*a1a3b679SAndreas Boehler                // Similarly, mod_php may also screw around with digest auth.
142*a1a3b679SAndreas Boehler                case 'PHP_AUTH_DIGEST' :
143*a1a3b679SAndreas Boehler                    $headers['Authorization'] = 'Digest ' . $value;
144*a1a3b679SAndreas Boehler                    break;
145*a1a3b679SAndreas Boehler
146*a1a3b679SAndreas Boehler                // Apache may prefix the HTTP_AUTHORIZATION header with
147*a1a3b679SAndreas Boehler                // REDIRECT_, if mod_rewrite was used.
148*a1a3b679SAndreas Boehler                case 'REDIRECT_HTTP_AUTHORIZATION' :
149*a1a3b679SAndreas Boehler                    $headers['Authorization'] = $value;
150*a1a3b679SAndreas Boehler                    break;
151*a1a3b679SAndreas Boehler
152*a1a3b679SAndreas Boehler                case 'HTTP_HOST' :
153*a1a3b679SAndreas Boehler                    $hostName = $value;
154*a1a3b679SAndreas Boehler                    $headers['Host'] = $value;
155*a1a3b679SAndreas Boehler                    break;
156*a1a3b679SAndreas Boehler
157*a1a3b679SAndreas Boehler                case 'HTTPS' :
158*a1a3b679SAndreas Boehler                    if (!empty($value) && $value !== 'off') {
159*a1a3b679SAndreas Boehler                        $protocol = 'https';
160*a1a3b679SAndreas Boehler                    }
161*a1a3b679SAndreas Boehler                    break;
162*a1a3b679SAndreas Boehler
163*a1a3b679SAndreas Boehler                default :
164*a1a3b679SAndreas Boehler                    if (substr($key, 0, 5) === 'HTTP_') {
165*a1a3b679SAndreas Boehler                        // It's a HTTP header
166*a1a3b679SAndreas Boehler
167*a1a3b679SAndreas Boehler                        // Normalizing it to be prettier
168*a1a3b679SAndreas Boehler                        $header = strtolower(substr($key, 5));
169*a1a3b679SAndreas Boehler
170*a1a3b679SAndreas Boehler                        // Transforming dashes into spaces, and uppercasing
171*a1a3b679SAndreas Boehler                        // every first letter.
172*a1a3b679SAndreas Boehler                        $header = ucwords(str_replace('_', ' ', $header));
173*a1a3b679SAndreas Boehler
174*a1a3b679SAndreas Boehler                        // Turning spaces into dashes.
175*a1a3b679SAndreas Boehler                        $header = str_replace(' ', '-', $header);
176*a1a3b679SAndreas Boehler                        $headers[$header] = $value;
177*a1a3b679SAndreas Boehler
178*a1a3b679SAndreas Boehler                    }
179*a1a3b679SAndreas Boehler                    break;
180*a1a3b679SAndreas Boehler
181*a1a3b679SAndreas Boehler
182*a1a3b679SAndreas Boehler            }
183*a1a3b679SAndreas Boehler
184*a1a3b679SAndreas Boehler        }
185*a1a3b679SAndreas Boehler
186*a1a3b679SAndreas Boehler        $r = new Request($method, $url, $headers);
187*a1a3b679SAndreas Boehler        $r->setHttpVersion($httpVersion);
188*a1a3b679SAndreas Boehler        $r->setRawServerData($serverArray);
189*a1a3b679SAndreas Boehler        $r->setAbsoluteUrl($protocol . '://' . $hostName . $url);
190*a1a3b679SAndreas Boehler        return $r;
191*a1a3b679SAndreas Boehler
192*a1a3b679SAndreas Boehler    }
193*a1a3b679SAndreas Boehler
194*a1a3b679SAndreas Boehler}
195