Imap.php 8.0 KB

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