Upgrade phpCAS
[piwik-CASLogin.git] / CAS / CAS / ProxiedService / Imap.php
1 <?php
2
3 /**
4  * Licensed to Jasig under one or more contributor license
5  * agreements. See the NOTICE file distributed with this work for
6  * additional information regarding copyright ownership.
7  *
8  * Jasig licenses this file to you under the Apache License,
9  * Version 2.0 (the "License"); you may not use this file except in
10  * compliance with the License. You may obtain a copy of the License at:
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * PHP Version 5
21  *
22  * @file     CAS/ProxiedService/Imap.php
23  * @category Authentication
24  * @package  PhpCAS
25  * @author   Adam Franco <afranco@middlebury.edu>
26  * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
27  * @link     https://wiki.jasig.org/display/CASC/phpCAS
28  */
29
30 /**
31  * Provides access to a proxy-authenticated IMAP stream
32  *
33  * @class    CAS_ProxiedService_Imap
34  * @category Authentication
35  * @package  PhpCAS
36  * @author   Adam Franco <afranco@middlebury.edu>
37  * @license  http://www.apache.org/licenses/LICENSE-2.0  Apache License 2.0
38  * @link     https://wiki.jasig.org/display/CASC/phpCAS
39  */
40 class CAS_ProxiedService_Imap
41 extends CAS_ProxiedService_Abstract
42 {
43
44     /**
45      * The username to send via imap_open.
46      *
47      * @var string $_username;
48      */
49     private $_username;
50
51     /**
52      * Constructor.
53      *
54      * @param string $username Username
55      *
56      * @return void
57      */
58     public function __construct ($username)
59     {
60         if (!is_string($username) || !strlen($username)) {
61             throw new CAS_InvalidArgumentException('Invalid username.');
62         }
63
64         $this->_username = $username;
65     }
66
67     /**
68      * The target service url.
69      * @var string $_url;
70      */
71     private $_url;
72
73     /**
74      * Answer a service identifier (URL) for whom we should fetch a proxy ticket.
75      *
76      * @return string
77      * @throws Exception If no service url is available.
78      */
79     public function getServiceUrl ()
80     {
81         if (empty($this->_url)) {
82             throw new CAS_ProxiedService_Exception('No URL set via '.get_class($this).'->getServiceUrl($url).');
83         }
84
85         return $this->_url;
86     }
87
88     /*********************************************************
89      * Configure the Stream
90     *********************************************************/
91
92     /**
93      * Set the URL of the service to pass to CAS for proxy-ticket retrieval.
94      *
95      * @param string $url Url to set
96      *
97      * @return void
98      * @throws CAS_OutOfSequenceException If called after the stream has been opened.
99      */
100     public function setServiceUrl ($url)
101     {
102         if ($this->hasBeenOpened()) {
103             throw new CAS_OutOfSequenceException('Cannot set the URL, stream already opened.');
104         }
105         if (!is_string($url) || !strlen($url)) {
106             throw new CAS_InvalidArgumentException('Invalid url.');
107         }
108
109         $this->_url = $url;
110     }
111
112     /**
113      * The mailbox to open. See the $mailbox parameter of imap_open().
114      *
115      * @var string $_mailbox
116      */
117     private $_mailbox;
118
119     /**
120      * Set the mailbox to open. See the $mailbox parameter of imap_open().
121      *
122      * @param string $mailbox Mailbox to set
123      *
124      * @return void
125      * @throws CAS_OutOfSequenceException If called after the stream has been opened.
126      */
127     public function setMailbox ($mailbox)
128     {
129         if ($this->hasBeenOpened()) {
130             throw new CAS_OutOfSequenceException('Cannot set the mailbox, stream already opened.');
131         }
132         if (!is_string($mailbox) || !strlen($mailbox)) {
133             throw new CAS_InvalidArgumentException('Invalid mailbox.');
134         }
135
136         $this->_mailbox = $mailbox;
137     }
138
139     /**
140      * A bit mask of options to pass to imap_open() as the $options parameter.
141      *
142      * @var int $_options
143      */
144     private $_options = null;
145
146     /**
147      * Set the options for opening the stream. See the $options parameter of
148      * imap_open().
149      *
150      * @param int $options Options for the stream
151      *
152      * @return void
153      * @throws CAS_OutOfSequenceException If called after the stream has been opened.
154      */
155     public function setOptions ($options)
156     {
157         if ($this->hasBeenOpened()) {
158             throw new CAS_OutOfSequenceException('Cannot set options, stream already opened.');
159         }
160         if (!is_int($options)) {
161             throw new CAS_InvalidArgumentException('Invalid options.');
162         }
163
164         $this->_options = $options;
165     }
166
167     /*********************************************************
168      * 2. Open the stream
169     *********************************************************/
170
171     /**
172      * Open the IMAP stream (similar to imap_open()).
173      *
174      * @return resource Returns an IMAP stream on success
175      * @throws CAS_OutOfSequenceException If called multiple times.
176      * @throws CAS_ProxyTicketException If there is a proxy-ticket failure.
177      *          The code of the Exception will be one of:
178      *                  PHPCAS_SERVICE_PT_NO_SERVER_RESPONSE
179      *                  PHPCAS_SERVICE_PT_BAD_SERVER_RESPONSE
180      *                  PHPCAS_SERVICE_PT_FAILURE
181      * @throws CAS_ProxiedService_Exception If there is a failure sending the request to the target service.     */
182     public function open ()
183     {
184         if ($this->hasBeenOpened()) {
185             throw new CAS_OutOfSequenceException('Stream already opened.');
186         }
187         if (empty($this->_mailbox)) {
188             throw new CAS_ProxiedService_Exception('You must specify a mailbox via '.get_class($this).'->setMailbox($mailbox)');
189         }
190
191         phpCAS::traceBegin();
192
193         // Get our proxy ticket and append it to our URL.
194         $this->initializeProxyTicket();
195         phpCAS::trace('opening IMAP mailbox `'.$this->_mailbox.'\'...');
196         $this->_stream = @imap_open($this->_mailbox, $this->_username, $this->getProxyTicket(), $this->_options);
197         if ($this->_stream) {
198             phpCAS::trace('ok');
199         } else {
200             phpCAS::trace('could not open mailbox');
201             // @todo add localization integration.
202             $message = 'IMAP Error: '.$url.' '. var_export(imap_errors(), true);
203             phpCAS::trace($message);
204             throw new CAS_ProxiedService_Exception($message);
205         }
206
207         phpCAS::traceEnd();
208         return $this->_stream;
209     }
210
211     /**
212      * Answer true if our request has been sent yet.
213      *
214      * @return bool
215      */
216     protected function hasBeenOpened ()
217     {
218         return !empty($this->_stream);
219     }
220
221     /*********************************************************
222      * 3. Access the result
223     *********************************************************/
224     /**
225      * The IMAP stream
226      *
227      * @var resource $_stream
228      */
229     private $_stream;
230
231     /**
232      * Answer the IMAP stream
233      *
234      * @return resource
235      */
236     public function getStream ()
237     {
238         if (!$this->hasBeenOpened()) {
239             throw new CAS_OutOfSequenceException('Cannot access stream, not opened yet.');
240         }
241         return $this->_stream;
242     }
243
244     /**
245      * CAS_Client::serviceMail() needs to return the proxy ticket for some reason,
246      * so this method provides access to it.
247      *
248      * @return string
249      * @throws CAS_OutOfSequenceException If called before the stream has been
250      * opened.
251      */
252     public function getImapProxyTicket ()
253     {
254         if (!$this->hasBeenOpened()) {
255             throw new CAS_OutOfSequenceException('Cannot access errors, stream not opened yet.');
256         }
257         return $this->getProxyTicket();
258     }
259 }
260 ?>