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/PGTStorage/Db.php
23 * @category Authentication
25 * @author Daniel Frett <daniel.frett@gmail.com>
26 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
27 * @link https://wiki.jasig.org/display/CASC/phpCAS
30 define('CAS_PGT_STORAGE_DB_DEFAULT_TABLE', 'cas_pgts');
33 * Basic class for PGT database storage
34 * The CAS_PGTStorage_Db class is a class for PGT database storage.
36 * @class CAS_PGTStorage_Db
37 * @category Authentication
39 * @author Daniel Frett <daniel.frett@gmail.com>
40 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
41 * @link https://wiki.jasig.org/display/CASC/phpCAS
43 * @ingroup internalPGTStorageDb
46 class CAS_PGTStorage_Db extends CAS_PGTStorage_AbstractStorage
49 * @addtogroup internalCAS_PGTStorageDb
54 * the PDO object to use for database interactions
59 * This method returns the PDO object to use for database interactions.
61 * @return the PDO object
63 private function _getPdo()
69 * database connection options to use when creating a new PDO object
74 private $_table_options;
77 * the table to use for storing/retrieving pgt's
82 * This method returns the table to use when storing/retrieving PGT's
84 * @return the name of the pgt storage table.
86 private function _getTable()
91 // ########################################################################
93 // ########################################################################
96 * This method returns an informational string giving the type of storage
97 * used by the object (used for debugging purposes).
99 * @return an informational string.
101 public function getStorageType()
107 * This method returns an informational string giving informations on the
108 * parameters of the storage.(used for debugging purposes).
110 * @return an informational string.
113 public function getStorageInfo()
115 return 'table=`'.$this->_getTable().'\'';
118 // ########################################################################
120 // ########################################################################
123 * The class constructor.
125 * @param CAS_Client $cas_parent the CAS_Client instance that creates
127 * @param string $dsn_or_pdo a dsn string to use for creating a PDO
128 * object or a PDO object
129 * @param string $username the username to use when connecting to
131 * @param string $password the password to use when connecting to
133 * @param string $table the table to use for storing and
135 * @param string $driver_options any driver options to use when
136 * connecting to the database
138 public function __construct($cas_parent, $dsn_or_pdo, $username='', $password='', $table='', $driver_options=null)
140 phpCAS::traceBegin();
141 // call the ancestor's constructor
142 parent::__construct($cas_parent);
144 // set default values
145 if ( empty($table) ) {
146 $table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE;
148 if ( !is_array($driver_options) ) {
149 $driver_options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
152 // store the specified parameters
153 if ($dsn_or_pdo instanceof PDO) {
154 $this->_pdo = $dsn_or_pdo;
156 $this->_dsn = $dsn_or_pdo;
157 $this->_username = $username;
158 $this->_password = $password;
159 $this->_driver_options = $driver_options;
162 // store the table name
163 $this->_table = $table;
168 // ########################################################################
170 // ########################################################################
173 * This method is used to initialize the storage. Halts on error.
177 public function init()
179 phpCAS::traceBegin();
180 // if the storage has already been initialized, return immediatly
181 if ($this->isInitialized()) {
185 // initialize the base object
188 // create the PDO object if it doesn't exist already
189 if (!($this->_pdo instanceof PDO)) {
191 $this->_pdo = new PDO($this->_dsn, $this->_username, $this->_password, $this->_driver_options);
193 catch(PDOException $e) {
194 phpCAS::error('Database connection error: ' . $e->getMessage());
201 // ########################################################################
202 // PDO database interaction
203 // ########################################################################
206 * attribute that stores the previous error mode for the PDO handle while
207 * processing a transaction
212 * This method will enable the Exception error mode on the PDO object
216 private function _setErrorMode()
218 // get PDO object and enable exception error mode
219 $pdo = $this->_getPdo();
220 $this->_errMode = $pdo->getAttribute(PDO::ATTR_ERRMODE);
221 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
225 * this method will reset the error mode on the PDO object
229 private function _resetErrorMode()
231 // get PDO object and reset the error mode to what it was originally
232 $pdo = $this->_getPdo();
233 $pdo->setAttribute(PDO::ATTR_ERRMODE, $this->_errMode);
236 // ########################################################################
238 // ########################################################################
239 // these queries are potentially unsafe because the person using this library
240 // can set the table to use, but there is no reliable way to escape SQL
241 // fieldnames in PDO yet
244 * This method returns the query used to create a pgt storage table
246 * @return the create table SQL, no bind params in query
248 protected function createTableSql()
250 return 'CREATE TABLE ' . $this->_getTable() . ' (pgt_iou VARCHAR(255) NOT NULL PRIMARY KEY, pgt VARCHAR(255) NOT NULL)';
254 * This method returns the query used to store a pgt
256 * @return the store PGT SQL, :pgt and :pgt_iou are the bind params contained in the query
258 protected function storePgtSql()
260 return 'INSERT INTO ' . $this->_getTable() . ' (pgt_iou, pgt) VALUES (:pgt_iou, :pgt)';
264 * This method returns the query used to retrieve a pgt. the first column of the first row should contain the pgt
266 * @return the retrieve PGT SQL, :pgt_iou is the only bind param contained in the query
268 protected function retrievePgtSql()
270 return 'SELECT pgt FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou';
274 * This method returns the query used to delete a pgt.
276 * @return the delete PGT SQL, :pgt_iou is the only bind param contained in the query
278 protected function deletePgtSql()
280 return 'DELETE FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou';
283 // ########################################################################
285 // ########################################################################
288 * This method creates the database table used to store pgt's and pgtiou's
292 public function createTable()
294 phpCAS::traceBegin();
296 // initialize this PGTStorage object if it hasn't been initialized yet
297 if ( !$this->isInitialized() ) {
301 // initialize the PDO object for this method
302 $pdo = $this->_getPdo();
303 $this->_setErrorMode();
306 $pdo->beginTransaction();
308 $query = $pdo->query($this->createTableSQL());
309 $query->closeCursor();
313 catch(PDOException $e) {
314 // attempt rolling back the transaction before throwing a phpCAS error
318 catch(PDOException $e) {
320 phpCAS::error('error creating PGT storage table: ' . $e->getMessage());
323 // reset the PDO object
324 $this->_resetErrorMode();
330 * This method stores a PGT and its corresponding PGT Iou in the database.
331 * Echoes a warning on error.
333 * @param string $pgt the PGT
334 * @param string $pgt_iou the PGT iou
338 public function write($pgt, $pgt_iou)
340 phpCAS::traceBegin();
342 // initialize the PDO object for this method
343 $pdo = $this->_getPdo();
344 $this->_setErrorMode();
347 $pdo->beginTransaction();
349 $query = $pdo->prepare($this->storePgtSql());
350 $query->bindValue(':pgt', $pgt, PDO::PARAM_STR);
351 $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
353 $query->closeCursor();
357 catch(PDOException $e) {
358 // attempt rolling back the transaction before throwing a phpCAS error
362 catch(PDOException $e) {
364 phpCAS::error('error writing PGT to database: ' . $e->getMessage());
367 // reset the PDO object
368 $this->_resetErrorMode();
374 * This method reads a PGT corresponding to a PGT Iou and deletes the
375 * corresponding db entry.
377 * @param string $pgt_iou the PGT iou
379 * @return the corresponding PGT, or FALSE on error
381 public function read($pgt_iou)
383 phpCAS::traceBegin();
386 // initialize the PDO object for this method
387 $pdo = $this->_getPdo();
388 $this->_setErrorMode();
391 $pdo->beginTransaction();
393 // fetch the pgt for the specified pgt_iou
394 $query = $pdo->prepare($this->retrievePgtSql());
395 $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
397 $pgt = $query->fetchColumn(0);
398 $query->closeCursor();
400 // delete the specified pgt_iou from the database
401 $query = $pdo->prepare($this->deletePgtSql());
402 $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR);
404 $query->closeCursor();
408 catch(PDOException $e) {
409 // attempt rolling back the transaction before throwing a phpCAS error
413 catch(PDOException $e) {
415 phpCAS::trace('error reading PGT from database: ' . $e->getMessage());
418 // reset the PDO object
419 $this->_resetErrorMode();