xref: /plugin/authssocas/vendor/apereo/phpcas/source/CAS/Request/AbstractRequest.php (revision d10b5556242e78d8a430c323b91984ec16415a46)
1*d10b5556SXylle<?php
2*d10b5556SXylle
3*d10b5556SXylle/**
4*d10b5556SXylle * Licensed to Jasig under one or more contributor license
5*d10b5556SXylle * agreements. See the NOTICE file distributed with this work for
6*d10b5556SXylle * additional information regarding copyright ownership.
7*d10b5556SXylle *
8*d10b5556SXylle * Jasig licenses this file to you under the Apache License,
9*d10b5556SXylle * Version 2.0 (the "License"); you may not use this file except in
10*d10b5556SXylle * compliance with the License. You may obtain a copy of the License at:
11*d10b5556SXylle *
12*d10b5556SXylle * http://www.apache.org/licenses/LICENSE-2.0
13*d10b5556SXylle *
14*d10b5556SXylle * Unless required by applicable law or agreed to in writing, software
15*d10b5556SXylle * distributed under the License is distributed on an "AS IS" BASIS,
16*d10b5556SXylle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17*d10b5556SXylle * See the License for the specific language governing permissions and
18*d10b5556SXylle * limitations under the License.
19*d10b5556SXylle *
20*d10b5556SXylle * PHP Version 7
21*d10b5556SXylle *
22*d10b5556SXylle * @file     CAS/Request/AbstractRequest.php
23*d10b5556SXylle * @category Authentication
24*d10b5556SXylle * @package  PhpCAS
25*d10b5556SXylle * @author   Adam Franco <afranco@middlebury.edu>
26*d10b5556SXylle * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
27*d10b5556SXylle * @link     https://wiki.jasig.org/display/CASC/phpCAS
28*d10b5556SXylle */
29*d10b5556SXylle
30*d10b5556SXylle/**
31*d10b5556SXylle * Provides support for performing web-requests via curl
32*d10b5556SXylle *
33*d10b5556SXylle * @class    CAS_Request_AbstractRequest
34*d10b5556SXylle * @category Authentication
35*d10b5556SXylle * @package  PhpCAS
36*d10b5556SXylle * @author   Adam Franco <afranco@middlebury.edu>
37*d10b5556SXylle * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
38*d10b5556SXylle * @link     https://wiki.jasig.org/display/CASC/phpCAS
39*d10b5556SXylle */
40*d10b5556SXylleabstract class CAS_Request_AbstractRequest
41*d10b5556SXylleimplements CAS_Request_RequestInterface
42*d10b5556SXylle{
43*d10b5556SXylle
44*d10b5556SXylle    protected $url = null;
45*d10b5556SXylle    protected $cookies = array();
46*d10b5556SXylle    protected $headers = array();
47*d10b5556SXylle    protected $isPost = false;
48*d10b5556SXylle    protected $postBody = null;
49*d10b5556SXylle    protected $caCertPath = null;
50*d10b5556SXylle    protected $validateCN = true;
51*d10b5556SXylle    private $_sent = false;
52*d10b5556SXylle    private $_responseHeaders = array();
53*d10b5556SXylle    private $_responseBody = null;
54*d10b5556SXylle    private $_errorMessage = '';
55*d10b5556SXylle
56*d10b5556SXylle    /*********************************************************
57*d10b5556SXylle     * Configure the Request
58*d10b5556SXylle    *********************************************************/
59*d10b5556SXylle
60*d10b5556SXylle    /**
61*d10b5556SXylle     * Set the URL of the Request
62*d10b5556SXylle     *
63*d10b5556SXylle     * @param string $url Url to set
64*d10b5556SXylle     *
65*d10b5556SXylle     * @return void
66*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called after the Request has been sent.
67*d10b5556SXylle     */
68*d10b5556SXylle    public function setUrl ($url)
69*d10b5556SXylle    {
70*d10b5556SXylle        if ($this->_sent) {
71*d10b5556SXylle            throw new CAS_OutOfSequenceException(
72*d10b5556SXylle                'Request has already been sent cannot '.__METHOD__
73*d10b5556SXylle            );
74*d10b5556SXylle        }
75*d10b5556SXylle
76*d10b5556SXylle        $this->url = $url;
77*d10b5556SXylle    }
78*d10b5556SXylle
79*d10b5556SXylle    /**
80*d10b5556SXylle     * Add a cookie to the request.
81*d10b5556SXylle     *
82*d10b5556SXylle     * @param string $name  Name of entry
83*d10b5556SXylle     * @param string $value value of entry
84*d10b5556SXylle     *
85*d10b5556SXylle     * @return void
86*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called after the Request has been sent.
87*d10b5556SXylle     */
88*d10b5556SXylle    public function addCookie ($name, $value)
89*d10b5556SXylle    {
90*d10b5556SXylle        if ($this->_sent) {
91*d10b5556SXylle            throw new CAS_OutOfSequenceException(
92*d10b5556SXylle                'Request has already been sent cannot '.__METHOD__
93*d10b5556SXylle            );
94*d10b5556SXylle        }
95*d10b5556SXylle
96*d10b5556SXylle        $this->cookies[$name] = $value;
97*d10b5556SXylle    }
98*d10b5556SXylle
99*d10b5556SXylle    /**
100*d10b5556SXylle     * Add an array of cookies to the request.
101*d10b5556SXylle     * The cookie array is of the form
102*d10b5556SXylle     *     array('cookie_name' => 'cookie_value', 'cookie_name2' => cookie_value2')
103*d10b5556SXylle     *
104*d10b5556SXylle     * @param array $cookies cookies to add
105*d10b5556SXylle     *
106*d10b5556SXylle     * @return void
107*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called after the Request has been sent.
108*d10b5556SXylle     */
109*d10b5556SXylle    public function addCookies (array $cookies)
110*d10b5556SXylle    {
111*d10b5556SXylle        if ($this->_sent) {
112*d10b5556SXylle            throw new CAS_OutOfSequenceException(
113*d10b5556SXylle                'Request has already been sent cannot '.__METHOD__
114*d10b5556SXylle            );
115*d10b5556SXylle        }
116*d10b5556SXylle
117*d10b5556SXylle        $this->cookies = array_merge($this->cookies, $cookies);
118*d10b5556SXylle    }
119*d10b5556SXylle
120*d10b5556SXylle    /**
121*d10b5556SXylle     * Add a header string to the request.
122*d10b5556SXylle     *
123*d10b5556SXylle     * @param string $header Header to add
124*d10b5556SXylle     *
125*d10b5556SXylle     * @return void
126*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called after the Request has been sent.
127*d10b5556SXylle     */
128*d10b5556SXylle    public function addHeader ($header)
129*d10b5556SXylle    {
130*d10b5556SXylle        if ($this->_sent) {
131*d10b5556SXylle            throw new CAS_OutOfSequenceException(
132*d10b5556SXylle                'Request has already been sent cannot '.__METHOD__
133*d10b5556SXylle            );
134*d10b5556SXylle        }
135*d10b5556SXylle
136*d10b5556SXylle        $this->headers[] = $header;
137*d10b5556SXylle    }
138*d10b5556SXylle
139*d10b5556SXylle    /**
140*d10b5556SXylle     * Add an array of header strings to the request.
141*d10b5556SXylle     *
142*d10b5556SXylle     * @param array $headers headers to add
143*d10b5556SXylle     *
144*d10b5556SXylle     * @return void
145*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called after the Request has been sent.
146*d10b5556SXylle     */
147*d10b5556SXylle    public function addHeaders (array $headers)
148*d10b5556SXylle    {
149*d10b5556SXylle        if ($this->_sent) {
150*d10b5556SXylle            throw new CAS_OutOfSequenceException(
151*d10b5556SXylle                'Request has already been sent cannot '.__METHOD__
152*d10b5556SXylle            );
153*d10b5556SXylle        }
154*d10b5556SXylle
155*d10b5556SXylle        $this->headers = array_merge($this->headers, $headers);
156*d10b5556SXylle    }
157*d10b5556SXylle
158*d10b5556SXylle    /**
159*d10b5556SXylle     * Make the request a POST request rather than the default GET request.
160*d10b5556SXylle     *
161*d10b5556SXylle     * @return void
162*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called after the Request has been sent.
163*d10b5556SXylle     */
164*d10b5556SXylle    public function makePost ()
165*d10b5556SXylle    {
166*d10b5556SXylle        if ($this->_sent) {
167*d10b5556SXylle            throw new CAS_OutOfSequenceException(
168*d10b5556SXylle                'Request has already been sent cannot '.__METHOD__
169*d10b5556SXylle            );
170*d10b5556SXylle        }
171*d10b5556SXylle
172*d10b5556SXylle        $this->isPost = true;
173*d10b5556SXylle    }
174*d10b5556SXylle
175*d10b5556SXylle    /**
176*d10b5556SXylle     * Add a POST body to the request
177*d10b5556SXylle     *
178*d10b5556SXylle     * @param string $body body to add
179*d10b5556SXylle     *
180*d10b5556SXylle     * @return void
181*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called after the Request has been sent.
182*d10b5556SXylle     */
183*d10b5556SXylle    public function setPostBody ($body)
184*d10b5556SXylle    {
185*d10b5556SXylle        if ($this->_sent) {
186*d10b5556SXylle            throw new CAS_OutOfSequenceException(
187*d10b5556SXylle                'Request has already been sent cannot '.__METHOD__
188*d10b5556SXylle            );
189*d10b5556SXylle        }
190*d10b5556SXylle        if (!$this->isPost) {
191*d10b5556SXylle            throw new CAS_OutOfSequenceException(
192*d10b5556SXylle                'Cannot add a POST body to a GET request, use makePost() first.'
193*d10b5556SXylle            );
194*d10b5556SXylle        }
195*d10b5556SXylle
196*d10b5556SXylle        $this->postBody = $body;
197*d10b5556SXylle    }
198*d10b5556SXylle
199*d10b5556SXylle    /**
200*d10b5556SXylle     * Specify the path to an SSL CA certificate to validate the server with.
201*d10b5556SXylle     *
202*d10b5556SXylle     * @param string $caCertPath  path to cert
203*d10b5556SXylle     * @param bool   $validate_cn valdiate CN of certificate
204*d10b5556SXylle     *
205*d10b5556SXylle     * @return void
206*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called after the Request has been sent.
207*d10b5556SXylle     */
208*d10b5556SXylle    public function setSslCaCert ($caCertPath,$validate_cn=true)
209*d10b5556SXylle    {
210*d10b5556SXylle        if ($this->_sent) {
211*d10b5556SXylle            throw new CAS_OutOfSequenceException(
212*d10b5556SXylle                'Request has already been sent cannot '.__METHOD__
213*d10b5556SXylle            );
214*d10b5556SXylle        }
215*d10b5556SXylle        $this->caCertPath = $caCertPath;
216*d10b5556SXylle        $this->validateCN = $validate_cn;
217*d10b5556SXylle    }
218*d10b5556SXylle
219*d10b5556SXylle    /*********************************************************
220*d10b5556SXylle     * 2. Send the Request
221*d10b5556SXylle    *********************************************************/
222*d10b5556SXylle
223*d10b5556SXylle    /**
224*d10b5556SXylle     * Perform the request.
225*d10b5556SXylle     *
226*d10b5556SXylle     * @return bool TRUE on success, FALSE on failure.
227*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called multiple times.
228*d10b5556SXylle     */
229*d10b5556SXylle    public function send ()
230*d10b5556SXylle    {
231*d10b5556SXylle        if ($this->_sent) {
232*d10b5556SXylle            throw new CAS_OutOfSequenceException(
233*d10b5556SXylle                'Request has already been sent cannot send again.'
234*d10b5556SXylle            );
235*d10b5556SXylle        }
236*d10b5556SXylle        if (is_null($this->url) || !$this->url) {
237*d10b5556SXylle            throw new CAS_OutOfSequenceException(
238*d10b5556SXylle                'A url must be specified via setUrl() before the request can be sent.'
239*d10b5556SXylle            );
240*d10b5556SXylle        }
241*d10b5556SXylle        $this->_sent = true;
242*d10b5556SXylle        return $this->sendRequest();
243*d10b5556SXylle    }
244*d10b5556SXylle
245*d10b5556SXylle    /**
246*d10b5556SXylle     * Send the request and store the results.
247*d10b5556SXylle     *
248*d10b5556SXylle     * @return bool TRUE on success, FALSE on failure.
249*d10b5556SXylle     */
250*d10b5556SXylle    abstract protected function sendRequest ();
251*d10b5556SXylle
252*d10b5556SXylle    /**
253*d10b5556SXylle     * Store the response headers.
254*d10b5556SXylle     *
255*d10b5556SXylle     * @param array $headers headers to store
256*d10b5556SXylle     *
257*d10b5556SXylle     * @return void
258*d10b5556SXylle     */
259*d10b5556SXylle    protected function storeResponseHeaders (array $headers)
260*d10b5556SXylle    {
261*d10b5556SXylle        $this->_responseHeaders = array_merge($this->_responseHeaders, $headers);
262*d10b5556SXylle    }
263*d10b5556SXylle
264*d10b5556SXylle    /**
265*d10b5556SXylle     * Store a single response header to our array.
266*d10b5556SXylle     *
267*d10b5556SXylle     * @param string $header header to store
268*d10b5556SXylle     *
269*d10b5556SXylle     * @return void
270*d10b5556SXylle     */
271*d10b5556SXylle    protected function storeResponseHeader ($header)
272*d10b5556SXylle    {
273*d10b5556SXylle        $this->_responseHeaders[] = $header;
274*d10b5556SXylle    }
275*d10b5556SXylle
276*d10b5556SXylle    /**
277*d10b5556SXylle     * Store the response body.
278*d10b5556SXylle     *
279*d10b5556SXylle     * @param string $body body to store
280*d10b5556SXylle     *
281*d10b5556SXylle     * @return void
282*d10b5556SXylle     */
283*d10b5556SXylle    protected function storeResponseBody ($body)
284*d10b5556SXylle    {
285*d10b5556SXylle        $this->_responseBody = $body;
286*d10b5556SXylle    }
287*d10b5556SXylle
288*d10b5556SXylle    /**
289*d10b5556SXylle     * Add a string to our error message.
290*d10b5556SXylle     *
291*d10b5556SXylle     * @param string $message message to add
292*d10b5556SXylle     *
293*d10b5556SXylle     * @return void
294*d10b5556SXylle     */
295*d10b5556SXylle    protected function storeErrorMessage ($message)
296*d10b5556SXylle    {
297*d10b5556SXylle        $this->_errorMessage .= $message;
298*d10b5556SXylle    }
299*d10b5556SXylle
300*d10b5556SXylle    /*********************************************************
301*d10b5556SXylle     * 3. Access the response
302*d10b5556SXylle    *********************************************************/
303*d10b5556SXylle
304*d10b5556SXylle    /**
305*d10b5556SXylle     * Answer the headers of the response.
306*d10b5556SXylle     *
307*d10b5556SXylle     * @return array An array of header strings.
308*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called before the Request has been sent.
309*d10b5556SXylle     */
310*d10b5556SXylle    public function getResponseHeaders ()
311*d10b5556SXylle    {
312*d10b5556SXylle        if (!$this->_sent) {
313*d10b5556SXylle            throw new CAS_OutOfSequenceException(
314*d10b5556SXylle                'Request has not been sent yet. Cannot '.__METHOD__
315*d10b5556SXylle            );
316*d10b5556SXylle        }
317*d10b5556SXylle        return $this->_responseHeaders;
318*d10b5556SXylle    }
319*d10b5556SXylle
320*d10b5556SXylle    /**
321*d10b5556SXylle     * Answer HTTP status code of the response
322*d10b5556SXylle     *
323*d10b5556SXylle     * @return int
324*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called before the Request has been sent.
325*d10b5556SXylle     * @throws CAS_Request_Exception if the response did not contain a status code
326*d10b5556SXylle     */
327*d10b5556SXylle    public function getResponseStatusCode ()
328*d10b5556SXylle    {
329*d10b5556SXylle        if (!$this->_sent) {
330*d10b5556SXylle            throw new CAS_OutOfSequenceException(
331*d10b5556SXylle                'Request has not been sent yet. Cannot '.__METHOD__
332*d10b5556SXylle            );
333*d10b5556SXylle        }
334*d10b5556SXylle
335*d10b5556SXylle        if (!preg_match(
336*d10b5556SXylle            '/HTTP\/[0-9.]+\s+([0-9]+)\s*(.*)/',
337*d10b5556SXylle            $this->_responseHeaders[0], $matches
338*d10b5556SXylle        )
339*d10b5556SXylle        ) {
340*d10b5556SXylle            throw new CAS_Request_Exception(
341*d10b5556SXylle                'Bad response, no status code was found in the first line.'
342*d10b5556SXylle            );
343*d10b5556SXylle        }
344*d10b5556SXylle
345*d10b5556SXylle        return intval($matches[1]);
346*d10b5556SXylle    }
347*d10b5556SXylle
348*d10b5556SXylle    /**
349*d10b5556SXylle     * Answer the body of response.
350*d10b5556SXylle     *
351*d10b5556SXylle     * @return string
352*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called before the Request has been sent.
353*d10b5556SXylle     */
354*d10b5556SXylle    public function getResponseBody ()
355*d10b5556SXylle    {
356*d10b5556SXylle        if (!$this->_sent) {
357*d10b5556SXylle            throw new CAS_OutOfSequenceException(
358*d10b5556SXylle                'Request has not been sent yet. Cannot '.__METHOD__
359*d10b5556SXylle            );
360*d10b5556SXylle        }
361*d10b5556SXylle
362*d10b5556SXylle        return $this->_responseBody;
363*d10b5556SXylle    }
364*d10b5556SXylle
365*d10b5556SXylle    /**
366*d10b5556SXylle     * Answer a message describing any errors if the request failed.
367*d10b5556SXylle     *
368*d10b5556SXylle     * @return string
369*d10b5556SXylle     * @throws CAS_OutOfSequenceException If called before the Request has been sent.
370*d10b5556SXylle     */
371*d10b5556SXylle    public function getErrorMessage ()
372*d10b5556SXylle    {
373*d10b5556SXylle        if (!$this->_sent) {
374*d10b5556SXylle            throw new CAS_OutOfSequenceException(
375*d10b5556SXylle                'Request has not been sent yet. Cannot '.__METHOD__
376*d10b5556SXylle            );
377*d10b5556SXylle        }
378*d10b5556SXylle        return $this->_errorMessage;
379*d10b5556SXylle    }
380*d10b5556SXylle}
381