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.
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:
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 * @file CAS/ProxiedService/Imap.php
23 * @category Authentication
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
31 * Provides access to a proxy-authenticated IMAP stream
33 * @class CAS_ProxiedService_Imap
34 * @category Authentication
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
40 class CAS_ProxiedService_Imap
41 extends CAS_ProxiedService_Abstract
45 * The username to send via imap_open.
47 * @var string $_username;
54 * @param string $username Username
58 public function __construct ($username)
60 if (!is_string($username) || !strlen($username)) {
61 throw new CAS_InvalidArgumentException('Invalid username.');
64 $this->_username = $username;
68 * The target service url.
74 * Answer a service identifier (URL) for whom we should fetch a proxy ticket.
77 * @throws Exception If no service url is available.
79 public function getServiceUrl ()
81 if (empty($this->_url)) {
82 throw new CAS_ProxiedService_Exception('No URL set via '.get_class($this).'->getServiceUrl($url).');
88 /*********************************************************
89 * Configure the Stream
90 *********************************************************/
93 * Set the URL of the service to pass to CAS for proxy-ticket retrieval.
95 * @param string $url Url to set
98 * @throws CAS_OutOfSequenceException If called after the stream has been opened.
100 public function setServiceUrl ($url)
102 if ($this->hasBeenOpened()) {
103 throw new CAS_OutOfSequenceException('Cannot set the URL, stream already opened.');
105 if (!is_string($url) || !strlen($url)) {
106 throw new CAS_InvalidArgumentException('Invalid url.');
113 * The mailbox to open. See the $mailbox parameter of imap_open().
115 * @var string $_mailbox
120 * Set the mailbox to open. See the $mailbox parameter of imap_open().
122 * @param string $mailbox Mailbox to set
125 * @throws CAS_OutOfSequenceException If called after the stream has been opened.
127 public function setMailbox ($mailbox)
129 if ($this->hasBeenOpened()) {
130 throw new CAS_OutOfSequenceException('Cannot set the mailbox, stream already opened.');
132 if (!is_string($mailbox) || !strlen($mailbox)) {
133 throw new CAS_InvalidArgumentException('Invalid mailbox.');
136 $this->_mailbox = $mailbox;
140 * A bit mask of options to pass to imap_open() as the $options parameter.
144 private $_options = null;
147 * Set the options for opening the stream. See the $options parameter of
150 * @param int $options Options for the stream
153 * @throws CAS_OutOfSequenceException If called after the stream has been opened.
155 public function setOptions ($options)
157 if ($this->hasBeenOpened()) {
158 throw new CAS_OutOfSequenceException('Cannot set options, stream already opened.');
160 if (!is_int($options)) {
161 throw new CAS_InvalidArgumentException('Invalid options.');
164 $this->_options = $options;
167 /*********************************************************
169 *********************************************************/
172 * Open the IMAP stream (similar to imap_open()).
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 ()
184 if ($this->hasBeenOpened()) {
185 throw new CAS_OutOfSequenceException('Stream already opened.');
187 if (empty($this->_mailbox)) {
188 throw new CAS_ProxiedService_Exception('You must specify a mailbox via '.get_class($this).'->setMailbox($mailbox)');
191 phpCAS::traceBegin();
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) {
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);
208 return $this->_stream;
212 * Answer true if our request has been sent yet.
216 protected function hasBeenOpened ()
218 return !empty($this->_stream);
221 /*********************************************************
222 * 3. Access the result
223 *********************************************************/
227 * @var resource $_stream
232 * Answer the IMAP stream
236 public function getStream ()
238 if (!$this->hasBeenOpened()) {
239 throw new CAS_OutOfSequenceException('Cannot access stream, not opened yet.');
241 return $this->_stream;
245 * CAS_Client::serviceMail() needs to return the proxy ticket for some reason,
246 * so this method provides access to it.
249 * @throws CAS_OutOfSequenceException If called before the stream has been
252 public function getImapProxyTicket ()
254 if (!$this->hasBeenOpened()) {
255 throw new CAS_OutOfSequenceException('Cannot access errors, stream not opened yet.');
257 return $this->getProxyTicket();