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/PGTStorage/Db.php 23 * @category Authentication 24 * @package PhpCAS 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 28 */ 29 30 define('CAS_PGT_STORAGE_DB_DEFAULT_TABLE', 'cas_pgts'); 31 32 /** 33 * Basic class for PGT database storage 34 * The CAS_PGTStorage_Db class is a class for PGT database storage. 35 * 36 * @class CAS_PGTStorage_Db 37 * @category Authentication 38 * @package PhpCAS 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 42 * 43 * @ingroup internalPGTStorageDb 44 */ 45 46 class CAS_PGTStorage_Db extends CAS_PGTStorage_AbstractStorage 47 { 48 /** 49 * @addtogroup internalCAS_PGTStorageDb 50 * @{ 51 */ 52 53 /** 54 * the PDO object to use for database interactions 55 */ 56 private $_pdo; 57 58 /** 59 * This method returns the PDO object to use for database interactions. 60 * 61 * @return PDO object 62 */ 63 private function _getPdo() 64 { 65 return $this->_pdo; 66 } 67 68 /** 69 * database connection options to use when creating a new PDO object 70 */ 71 private $_dsn; 72 private $_username; 73 private $_password; 74 private $_driver_options; 75 76 /** 77 * @var string the table to use for storing/retrieving pgt's 78 */ 79 private $_table; 80 81 /** 82 * This method returns the table to use when storing/retrieving PGT's 83 * 84 * @return string the name of the pgt storage table. 85 */ 86 private function _getTable() 87 { 88 return $this->_table; 89 } 90 91 // ######################################################################## 92 // DEBUGGING 93 // ######################################################################## 94 95 /** 96 * This method returns an informational string giving the type of storage 97 * used by the object (used for debugging purposes). 98 * 99 * @return string an informational string. 100 */ 101 public function getStorageType() 102 { 103 return "db"; 104 } 105 106 /** 107 * This method returns an informational string giving informations on the 108 * parameters of the storage.(used for debugging purposes). 109 * 110 * @return string an informational string. 111 * @public 112 */ 113 public function getStorageInfo() 114 { 115 return 'table=`'.$this->_getTable().'\''; 116 } 117 118 // ######################################################################## 119 // CONSTRUCTOR 120 // ######################################################################## 121 122 /** 123 * The class constructor. 124 * 125 * @param CAS_Client $cas_parent the CAS_Client instance that creates 126 * the object. 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 130 * the database 131 * @param string $password the password to use when connecting to 132 * the database 133 * @param string $table the table to use for storing and 134 * retrieving PGT's 135 * @param string $driver_options any driver options to use when 136 * connecting to the database 137 */ 138 public function __construct( 139 $cas_parent, $dsn_or_pdo, $username='', $password='', $table='', 140 $driver_options=null 141 ) { 142 phpCAS::traceBegin(); 143 // call the ancestor's constructor 144 parent::__construct($cas_parent); 145 146 // set default values 147 if ( empty($table) ) { 148 $table = CAS_PGT_STORAGE_DB_DEFAULT_TABLE; 149 } 150 if ( !is_array($driver_options) ) { 151 $driver_options = array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION); 152 } 153 154 // store the specified parameters 155 if ($dsn_or_pdo instanceof PDO) { 156 $this->_pdo = $dsn_or_pdo; 157 } else { 158 $this->_dsn = $dsn_or_pdo; 159 $this->_username = $username; 160 $this->_password = $password; 161 $this->_driver_options = $driver_options; 162 } 163 164 // store the table name 165 $this->_table = $table; 166 167 phpCAS::traceEnd(); 168 } 169 170 // ######################################################################## 171 // INITIALIZATION 172 // ######################################################################## 173 174 /** 175 * This method is used to initialize the storage. Halts on error. 176 * 177 * @return void 178 */ 179 public function init() 180 { 181 phpCAS::traceBegin(); 182 // if the storage has already been initialized, return immediatly 183 if ($this->isInitialized()) { 184 return; 185 } 186 187 // initialize the base object 188 parent::init(); 189 190 // create the PDO object if it doesn't exist already 191 if (!($this->_pdo instanceof PDO)) { 192 try { 193 $this->_pdo = new PDO( 194 $this->_dsn, $this->_username, $this->_password, 195 $this->_driver_options 196 ); 197 } 198 catch(PDOException $e) { 199 phpCAS::error('Database connection error: ' . $e->getMessage()); 200 } 201 } 202 203 phpCAS::traceEnd(); 204 } 205 206 // ######################################################################## 207 // PDO database interaction 208 // ######################################################################## 209 210 /** 211 * attribute that stores the previous error mode for the PDO handle while 212 * processing a transaction 213 */ 214 private $_errMode; 215 216 /** 217 * This method will enable the Exception error mode on the PDO object 218 * 219 * @return void 220 */ 221 private function _setErrorMode() 222 { 223 // get PDO object and enable exception error mode 224 $pdo = $this->_getPdo(); 225 $this->_errMode = $pdo->getAttribute(PDO::ATTR_ERRMODE); 226 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 227 } 228 229 /** 230 * this method will reset the error mode on the PDO object 231 * 232 * @return void 233 */ 234 private function _resetErrorMode() 235 { 236 // get PDO object and reset the error mode to what it was originally 237 $pdo = $this->_getPdo(); 238 $pdo->setAttribute(PDO::ATTR_ERRMODE, $this->_errMode); 239 } 240 241 // ######################################################################## 242 // database queries 243 // ######################################################################## 244 // these queries are potentially unsafe because the person using this library 245 // can set the table to use, but there is no reliable way to escape SQL 246 // fieldnames in PDO yet 247 248 /** 249 * This method returns the query used to create a pgt storage table 250 * 251 * @return string the create table SQL, no bind params in query 252 */ 253 protected function createTableSql() 254 { 255 return 'CREATE TABLE ' . $this->_getTable() 256 . ' (pgt_iou VARCHAR(255) NOT NULL PRIMARY KEY, pgt VARCHAR(255) NOT NULL)'; 257 } 258 259 /** 260 * This method returns the query used to store a pgt 261 * 262 * @return string the store PGT SQL, :pgt and :pgt_iou are the bind params contained 263 * in the query 264 */ 265 protected function storePgtSql() 266 { 267 return 'INSERT INTO ' . $this->_getTable() 268 . ' (pgt_iou, pgt) VALUES (:pgt_iou, :pgt)'; 269 } 270 271 /** 272 * This method returns the query used to retrieve a pgt. the first column 273 * of the first row should contain the pgt 274 * 275 * @return string the retrieve PGT SQL, :pgt_iou is the only bind param contained 276 * in the query 277 */ 278 protected function retrievePgtSql() 279 { 280 return 'SELECT pgt FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou'; 281 } 282 283 /** 284 * This method returns the query used to delete a pgt. 285 * 286 * @return string the delete PGT SQL, :pgt_iou is the only bind param contained in 287 * the query 288 */ 289 protected function deletePgtSql() 290 { 291 return 'DELETE FROM ' . $this->_getTable() . ' WHERE pgt_iou = :pgt_iou'; 292 } 293 294 // ######################################################################## 295 // PGT I/O 296 // ######################################################################## 297 298 /** 299 * This method creates the database table used to store pgt's and pgtiou's 300 * 301 * @return void 302 */ 303 public function createTable() 304 { 305 phpCAS::traceBegin(); 306 307 // initialize this PGTStorage object if it hasn't been initialized yet 308 if ( !$this->isInitialized() ) { 309 $this->init(); 310 } 311 312 // initialize the PDO object for this method 313 $pdo = $this->_getPdo(); 314 $this->_setErrorMode(); 315 316 try { 317 $pdo->beginTransaction(); 318 319 $query = $pdo->query($this->createTableSQL()); 320 $query->closeCursor(); 321 322 $pdo->commit(); 323 } 324 catch(PDOException $e) { 325 // attempt rolling back the transaction before throwing a phpCAS error 326 try { 327 $pdo->rollBack(); 328 } 329 catch(PDOException $e) { 330 } 331 phpCAS::error('error creating PGT storage table: ' . $e->getMessage()); 332 } 333 334 // reset the PDO object 335 $this->_resetErrorMode(); 336 337 phpCAS::traceEnd(); 338 } 339 340 /** 341 * This method stores a PGT and its corresponding PGT Iou in the database. 342 * Echoes a warning on error. 343 * 344 * @param string $pgt the PGT 345 * @param string $pgt_iou the PGT iou 346 * 347 * @return void 348 */ 349 public function write($pgt, $pgt_iou) 350 { 351 phpCAS::traceBegin(); 352 353 // initialize the PDO object for this method 354 $pdo = $this->_getPdo(); 355 $this->_setErrorMode(); 356 357 try { 358 $pdo->beginTransaction(); 359 360 $query = $pdo->prepare($this->storePgtSql()); 361 $query->bindValue(':pgt', $pgt, PDO::PARAM_STR); 362 $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR); 363 $query->execute(); 364 $query->closeCursor(); 365 366 $pdo->commit(); 367 } 368 catch(PDOException $e) { 369 // attempt rolling back the transaction before throwing a phpCAS error 370 try { 371 $pdo->rollBack(); 372 } 373 catch(PDOException $e) { 374 } 375 phpCAS::error('error writing PGT to database: ' . $e->getMessage()); 376 } 377 378 // reset the PDO object 379 $this->_resetErrorMode(); 380 381 phpCAS::traceEnd(); 382 } 383 384 /** 385 * This method reads a PGT corresponding to a PGT Iou and deletes the 386 * corresponding db entry. 387 * 388 * @param string $pgt_iou the PGT iou 389 * 390 * @return string|false the corresponding PGT, or FALSE on error 391 */ 392 public function read($pgt_iou) 393 { 394 phpCAS::traceBegin(); 395 $pgt = false; 396 397 // initialize the PDO object for this method 398 $pdo = $this->_getPdo(); 399 $this->_setErrorMode(); 400 401 try { 402 $pdo->beginTransaction(); 403 404 // fetch the pgt for the specified pgt_iou 405 $query = $pdo->prepare($this->retrievePgtSql()); 406 $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR); 407 $query->execute(); 408 $pgt = $query->fetchColumn(0); 409 $query->closeCursor(); 410 411 // delete the specified pgt_iou from the database 412 $query = $pdo->prepare($this->deletePgtSql()); 413 $query->bindValue(':pgt_iou', $pgt_iou, PDO::PARAM_STR); 414 $query->execute(); 415 $query->closeCursor(); 416 417 $pdo->commit(); 418 } 419 catch(PDOException $e) { 420 // attempt rolling back the transaction before throwing a phpCAS error 421 try { 422 $pdo->rollBack(); 423 } 424 catch(PDOException $e) { 425 } 426 phpCAS::trace('error reading PGT from database: ' . $e->getMessage()); 427 } 428 429 // reset the PDO object 430 $this->_resetErrorMode(); 431 432 phpCAS::traceEnd(); 433 return $pgt; 434 } 435 436 /** @} */ 437 438 } 439 440 ?>
title
Description
Body
title
Description
Body
title
Description
Body
title
Body